Quantcast

5.0.82

Steven Jackson [10-21-14 - 23:29]
5.0.82
Filename
Interface/AddOns/SVUI/License.txt
Interface/AddOns/SVUI/SVUI.toc
Interface/AddOns/SVUI/packages/bag/tools/sorting.lua
Interface/AddOns/SVUI/packages/unit/SVUnit.lua
Interface/AddOns/SVUI/packages/unit/SVUnit.xml
Interface/AddOns/SVUI/packages/unit/elements/essentials.lua
Interface/AddOns/SVUI/packages/unit/frames.lua
Interface/AddOns/SVUI/packages/unit/groups.lua
Interface/AddOns/SVUI/setup/installer.lua
Interface/AddOns/SVUI/system/_load.xml
Interface/AddOns/SVUI/system/animate.lua
Interface/AddOns/SVUI/system/common.lua
Interface/AddOns/SVUI/system/configs.lua
Interface/AddOns/SVUI/system/credits.lua
Interface/AddOns/SVUI/system/framework.lua
Interface/AddOns/SVUI/system/timers.lua
Interface/AddOns/SVUI/xml/widgets.xml
Interface/AddOns/SVUI_ConfigOMatic/License.txt
Interface/AddOns/SVUI_ConfigOMatic/components/units/grid.lua
Interface/AddOns/SVUI_ConfigOMatic/components/units/other.lua
Interface/AddOns/SVUI_ConfigOMatic/components/units/party.lua
Interface/AddOns/SVUI_ConfigOMatic/components/units/raid.lua
Interface/AddOns/SVUI_StyleOMatic/License.txt
Interface/AddOns/SVUI_StyleOMatic/components/blizzard/system.lua
diff --git a/Interface/AddOns/SVUI/License.txt b/Interface/AddOns/SVUI/License.txt
index 5bd9961..5cf3f8e 100644
--- a/Interface/AddOns/SVUI/License.txt
+++ b/Interface/AddOns/SVUI/License.txt
@@ -14,8 +14,6 @@

 SVUI License Copyright 2014 http://wowinterface.com

-(Adapted and inspired by ElvUI and TukUI) Copyright 2014 http://www.tukui.org
-
 The contents of this addon, excluding third-party resources, are
 copyrighted to their authors with all rights reserved.

@@ -32,7 +30,4 @@ Authors of this addon hereby grant you the following rights:
 All rights not explicitly addressed in this license are reserved by
 the copyright holders.

-You can write Munglunch at Wowinterface.com for reporting abuse / bugs.
-
-You can contact Tukz or Elv at Tukui.org for details regarding
-grants allowed for their respective licenses.
\ No newline at end of file
+You can write Munglunch at Wowinterface.com for reporting abuse / bugs.
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/SVUI.toc b/Interface/AddOns/SVUI/SVUI.toc
index a396bfd..1012ec8 100644
--- a/Interface/AddOns/SVUI/SVUI.toc
+++ b/Interface/AddOns/SVUI/SVUI.toc
@@ -9,7 +9,6 @@
 ## X-SVUI-Header: SuperVillain UI
 ## X-SVUI-Schema: Core
 ## X-oUF: oUF_Villain
-## X-Notes: Special thanks to Elv and Tukz for their incredible work.
 ## X-Email: munglunch@gmail.com

 SVUI.xml
diff --git a/Interface/AddOns/SVUI/packages/bag/tools/sorting.lua b/Interface/AddOns/SVUI/packages/bag/tools/sorting.lua
index a43490f..fd26f7f 100644
--- a/Interface/AddOns/SVUI/packages/bag/tools/sorting.lua
+++ b/Interface/AddOns/SVUI/packages/bag/tools/sorting.lua
@@ -12,7 +12,7 @@ _____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ##############################################################################
 S U P E R - V I L L A I N - U I   By: Munglunch                              #
 ##############################################################################
-credit: Elv.                      original logic from ElvUI. Adapted to SVUI #
+credit: Kemayo.               original logic from BankStack. Adapted to SVUI #
 ##############################################################################
 ##########################################################
 LOCALIZED LUA FUNCTIONS
@@ -60,6 +60,7 @@ local MOD = SV.SVBag;
 LOCAL VARS
 ##########################################################
 ]]--
+local WAIT_TIME = 0.05
 local bagGroups = {};
 local initialOrder = {};
 local bagSorted = {};
@@ -147,6 +148,30 @@ SORTING UPDATES HANDLER
 local SortUpdateTimer = CreateFrame("Frame")
 SortUpdateTimer.timeLapse = 0
 SortUpdateTimer:Hide()
+--[[
+##########################################################
+HELPERS
+##########################################################
+]]--
+local function ValidateBag(bagid)
+	return (bagid == BANK_CONTAINER or ((bagid >= 0) and bagid <= (NUM_BAG_SLOTS + NUM_BANKBAGSLOTS)))
+end
+local function ValidateBank(bagid)
+	return (bagid == BANK_CONTAINER or bagid == REAGENTBANK_CONTAINER or (bagid > NUM_BAG_SLOTS and bagid <= NUM_BANKBAGSLOTS))
+end
+local function ValidateGuildBank(bagid)
+	return (bagid > 50 and bagid <= 58)
+end
+local function BagEncoder(bag, slot) return (bag * 100) + slot end
+local function BagDecoder(int) return math.floor(int / 100), int % 100 end
+local function MoveEncoder(source, target) return (source * 10000) + target end
+local function MoveDecoder(move)
+	local s = math.floor(move / 10000)
+	local t = move % 10000
+	s = (t > 9000) and (s + 1) or s
+	t = (t > 9000) and (t - 10000) or t
+	return s, t
+end
 --[[
 ##########################################################
 LOCAL FUNCTIONS
@@ -287,7 +312,7 @@ local function GetSortingGroup(id)
 end

 local function GetSortingInfo(bag, slot)
-	if (bag > 50 and bag <= 58) then
+	if (ValidateGuildBank(bag)) then
 		return GetGuildBankItemInfo(bag - 50, slot)
 	else
 		return GetContainerItemInfo(bag, slot)
@@ -295,7 +320,7 @@ local function GetSortingInfo(bag, slot)
 end

 local function GetSortingItemLink(bag, slot)
-	if (bag > 50 and bag <= 58) then
+	if (ValidateGuildBank(bag)) then
 		return GetGuildBankItemLink(bag - 50, slot)
 	else
 		return GetContainerItemLink(bag, slot)
@@ -310,7 +335,7 @@ do
 	local bagRole;

 	local function GetNumSortingSlots(bag, role)
-		if (bag > 50 and bag <= 58) then
+		if (ValidateGuildBank(bag)) then
 			if not role then role = "deposit" end
 			local name, icon, canView, canDeposit, numWithdrawals = GetGuildBankTabInfo(bag - 50)
 			if name and canView then
@@ -393,18 +418,18 @@ EXTERNAL SORTING CALLS
 ##########################################################
 ]]--
 do
-	local function SetSortingPath(source, destination)
-		UpdateLocation(source, destination)
-		tinsert(sortingCache[6], 1, ((source * 10000) + destination))
+	local function SetSortingPath(source, target)
+		UpdateLocation(source, target)
+		tinsert(sortingCache[6], 1, (MoveEncoder(source, target)))
 	end

 	local function IsPartial(bag, slot)
-		local bagSlot = (bag*100) + slot
+		local bagSlot = BagEncoder(bag, slot)
 		return ((sortingCache[5][bagSlot] or 0) - (sortingCache[4][bagSlot] or 0)) > 0
 	end

 	local function IsSpecialtyBag(bagID)
-		if bagID == BANK_CONTAINER or bagID == REAGENTBANK_CONTAINER or bagID == 0 or (bagID > 50 and bagID <= 58) then return false end
+		if(bagID == 0 or (ValidateBank(bagID)) or (ValidateGuildBank(bagID))) then return false end
 		local inventorySlot = ContainerIDToInventoryID(bagID)
 		if not inventorySlot then return false end
 		local bag = GetInventoryItemLink("player", inventorySlot)
@@ -415,8 +440,8 @@ do
 	end

 	local function CanItemGoInBag(bag, slot, targetBag)
-		if (targetBag > 50 and targetBag <= 58) then return true end
-		local item = sortingCache[2][((bag*100) + slot)]
+		if (ValidateGuildBank(targetBag)) then return true end
+		local item = sortingCache[2][(BagEncoder(bag, slot))]
 		local itemFamily = GetItemFamily(item)
 		if itemFamily and itemFamily > 0 then
 			local equipSlot = select(9, GetItemInfo(item))
@@ -456,7 +481,7 @@ do
 		ignoreItems = ignoreItems:gsub(',%s', ',')
 		SetBlockedCache(split(",", ignoreItems))
 		for i, bag, slot in IterateBagsForSorting(bags, nil, 'both') do
-			local bagSlot = (bag*100) + slot
+			local bagSlot = BagEncoder(bag, slot)
 			local link = GetSortingItemLink(bag, slot);
 			if link and blackList[GetItemInfo(link)] then
 				blackListedSlots[bagSlot] = true
@@ -472,7 +497,7 @@ do
 			passNeeded = false
 			local i = 1
 			for _, bag, slot in IterateBagsForSorting(bags, nil, 'both') do
-				local destination = (bag*100) + slot
+				local destination = BagEncoder(bag, slot)
 				local source = bagSorted[i]
 				if not blackListedSlots[destination] then
 					if(ShouldMove(source, destination)) then
@@ -497,15 +522,15 @@ do
 	local function SortFiller(sourceBags, targetBags, reverse, canMove)
 		if not canMove then canMove = true end
 		for _, bag, slot in IterateBagsForSorting(targetBags, reverse, "deposit") do
-			local bagSlot = (bag*100) + slot
+			local bagSlot = BagEncoder(bag, slot)
 			if not sortingCache[2][bagSlot] then
 				tinsert(emptySlots, bagSlot)
 			end
 		end
 		for _, bag, slot in IterateBagsForSorting(sourceBags, not reverse, "withdraw") do
 			if #emptySlots == 0 then break end
-			local bagSlot = (bag*100) + slot
-			local targetBag, targetSlot = floor(emptySlots[1]/100), emptySlots[1] % 100
+			local bagSlot = BagEncoder(bag, slot)
+			local targetBag, targetSlot = BagDecoder(emptySlots)
 			if sortingCache[2][bagSlot] and CanItemGoInBag(bag, slot, targetBag) and (canMove == true or canMove(sortingCache[2][bagSlot], bag, slot)) then
 				SetSortingPath(bagSlot, tremove(emptySlots, 1))
 			end
@@ -544,7 +569,7 @@ do
 	function MOD.Transfer(sourceBags, targetBags, canMove)
 		if not canMove then canMove = true end
 		for _, bag, slot in IterateBagsForSorting(targetBags, nil, "deposit") do
-			local bagSlot = (bag*100) + slot
+			local bagSlot = BagEncoder(bag, slot)
 			local itemID = sortingCache[2][bagSlot]
 			if itemID and (sortingCache[4][bagSlot] ~= sortingCache[5][bagSlot]) then
 				targetItems[itemID] = (targetItems[itemID] or 0) + 1
@@ -553,7 +578,7 @@ do
 		end

 		for _, bag, slot in IterateBagsForSorting(sourceBags, true, "withdraw") do
-			local sourceSlot = (bag*100) + slot
+			local sourceSlot = BagEncoder(bag, slot)
 			local itemID = sortingCache[2][sourceSlot]
 			if itemID and targetItems[itemID] and (canMove == true or canMove(itemID, bag, slot)) then
 				for i = #targetSlots, 1, -1 do
@@ -581,7 +606,7 @@ do
 	function MOD.Stack(bags, canMove)
 		if not canMove then canMove = true end
 		for _, bag, slot in IterateBagsForSorting(bags, nil, "deposit") do
-			local bagSlot = (bag*100) + slot
+			local bagSlot = BagEncoder(bag, slot)
 			local itemID = sortingCache[2][bagSlot]
 			if itemID and (sortingCache[4][bagSlot] ~= sortingCache[5][bagSlot]) then
 				targetItems[itemID] = (targetItems[itemID] or 0) + 1
@@ -590,7 +615,7 @@ do
 		end

 		for _, bag, slot in IterateBagsForSorting(bags, true, "withdraw") do
-			local sourceSlot = (bag*100) + slot
+			local sourceSlot = BagEncoder(bag, slot)
 			local itemID = sortingCache[2][sourceSlot]
 			if itemID and targetItems[itemID] and (canMove == true or (type(canMove) == "function" and canMove(itemID, bag, slot))) then
 				for i = #targetSlots, 1, -1 do
@@ -621,16 +646,8 @@ INTERNAL SORTING CALLS
 ##########################################################
 ]]--
 do
-	local function GetMovement(move)
-		local s = floor(move/10000)
-		local t = move%10000
-		s = (t>9000) and (s+1) or s
-		t = (t>9000) and (t-10000) or t
-		return s, t
-	end
-
 	local function GetSortingItemID(bag, slot)
-		if (bag > 50 and bag <= 58) then
+		if (ValidateGuildBank(bag)) then
 			local link = GetSortingItemLink(bag, slot)
 			return link and tonumber(string.match(link, "item:(%d+)"))
 		else
@@ -653,9 +670,9 @@ do
 		if GetCursorInfo() == "item" then
 			return false, 'cursorhasitem'
 		end
-		local source, target = GetMovement(move)
-		local sourceBag, sourceSlot = floor(source/100), source % 100
-		local targetBag, targetSlot = floor(target/100), target % 100
+		local source, target = MoveDecoder(move)
+		local sourceBag, sourceSlot = BagDecoder(source)
+		local targetBag, targetSlot = BagDecoder(target)
 		local _, sourceCount, sourceLocked = GetSortingInfo(sourceBag, sourceSlot)
 		local _, targetCount, targetLocked = GetSortingInfo(targetBag, targetSlot)
 		if sourceLocked or targetLocked then
@@ -664,6 +681,7 @@ do
 		local sourceLink = GetSortingItemLink(sourceBag, sourceSlot)
 		local sourceItemID = GetSortingItemID(sourceBag, sourceSlot)
 		local targetItemID = GetSortingItemID(targetBag, targetSlot)
+
 		if not sourceItemID then
 			if moveTracker[source] then
 				return false, 'move incomplete'
@@ -671,30 +689,35 @@ do
 				return self:StopStacking(L['Confused.. Try Again!'])
 			end
 		end
+
 		local stackSize = select(8, GetItemInfo(sourceItemID))
+
+		local sourceGuild = ValidateGuildBank(sourceBag)
+		local targetGuild = ValidateGuildBank(targetBag)
+
 		if (sourceItemID == targetItemID) and (targetCount ~= stackSize) and ((targetCount + sourceCount) > stackSize) then
 			local amount = (stackSize - targetCount)
-			if (sourceBag > 50 and sourceBag <= 58) then
+			if (sourceGuild) then
 				SplitGuildBankItem(sourceBag - 50, sourceSlot, amount)
 			else
 				SplitContainerItem(sourceBag, sourceSlot, amount)
 			end
 		else
-			if (sourceBag > 50 and sourceBag <= 58) then
+			if (sourceGuild) then
 				PickupGuildBankItem(sourceBag - 50, sourceSlot)
 			else
 				PickupContainerItem(sourceBag, sourceSlot)
 			end
 		end
+
 		if GetCursorInfo() == "item" then
-			if (targetBag > 50 and targetBag <= 58) then
+			if (targetGuild) then
 				PickupGuildBankItem(targetBag - 50, targetSlot)
 			else
 				PickupContainerItem(targetBag, targetSlot)
 			end
 		end
-		local sourceGuild = (sourceBag > 50 and sourceBag <= 58)
-		local targetGuild = (targetBag > 50 and targetBag <= 58)
+
 		if sourceGuild then
 			QueryGuildBankTab(sourceBag - 50)
 		end
@@ -709,18 +732,18 @@ do
 		if(self.timeLapse > 0.05) then
 			self.timeLapse = 0
 			if InCombatLockdown() then
-				return self:StopStacking(L['Confused.. Try Again!'])
+				return self:StopStacking(L["Can't Clean Bags in Combat!"])
 			end
 			local cursorType, cursorItemID = GetCursorInfo()
 			if cursorType == "item" and cursorItemID then
 				if lastItemID ~= cursorItemID then
-					return self:StopStacking(L['Confused.. Try Again!'])
+					return self:StopStacking(L["Bag Cleaning Error, Try Again"])
 				end
 				if moveRetries < 100 then
-					local targetBag, targetSlot = floor(lastDestination/100), lastDestination % 100
+					local targetBag, targetSlot = BagDecoder(lastDestination)
 					local _, _, targetLocked = GetSortingInfo(targetBag, targetSlot)
 					if not targetLocked then
-						if (targetBag > 50 and targetBag <= 58) then
+						if(ValidateGuildBank(targetBag)) then
 							PickupGuildBankItem(targetBag - 50, targetSlot)
 						else
 							PickupContainerItem(targetBag, targetSlot)
@@ -735,8 +758,9 @@ do
 			if lockStop then
 				local i = 1;
 				for slot, itemID in pairs(moveTracker) do
-					local actualItemID = GetSortingItemID(floor(slot/100), slot % 100)
-					if actualItemID  ~= itemid then
+					local sourceBag, sourceSlot = BagDecoder(slot)
+					local actualItemID = GetSortingItemID(sourceBag, sourceSlot)
+					if actualItemID ~= itemID then
 						WAIT_TIME = 0.1
 						if (GetTime() - lockStop) > 1.25 then
 							if lastMove and moveRetries < 100 then
@@ -834,7 +858,7 @@ function MOD:RunSortingProcess(func, groupsDefaults, altFunc)
 				end
 			end
 			for _, bag, slot in IterateBagsForSorting(scanningCache.all) do
-				local bagSlot = (bag*100) + slot
+				local bagSlot = BagEncoder(bag, slot)
 				local itemID, isBattlePet = ConvertLinkToID(GetSortingItemLink(bag, slot))
 				if itemID then
 					if isBattlePet then
diff --git a/Interface/AddOns/SVUI/packages/unit/SVUnit.lua b/Interface/AddOns/SVUI/packages/unit/SVUnit.lua
index 37a442f..6f13e07 100644
--- a/Interface/AddOns/SVUI/packages/unit/SVUnit.lua
+++ b/Interface/AddOns/SVUI/packages/unit/SVUnit.lua
@@ -1231,7 +1231,6 @@ local _ENV = {
 		return LOCALIZED_CLASS_NAMES_MALE[token], token
 	end,
 	Hex = function(r, g, b)
-		if not r then return end
 		if type(r) == "table" then
 			if r.r then r, g, b = r.r, r.g, r.b else r, g, b = unpack(r) end
 		end
@@ -1274,10 +1273,11 @@ local function ChangeGroupIndex(self)
 	if not self:GetParent().forceShow and not self.forceShow then return end
 	if not self:IsShown() then return end

+	local max = MAX_RAID_MEMBERS;
 	local key = self.___groupkey
 	local db = SV.db.SVUnit[key]

-	local newIndex = -4;
+	local newIndex = db.customSorting and -(min(db.groupCount * (db.gRowCol * 5), max) + 1 ) or -4;
 	if self:GetAttribute("startingIndex") ~= newIndex then
 		self:SetAttribute("startingIndex", newIndex)
 		self.isForced = true;
@@ -1285,7 +1285,7 @@ local function ChangeGroupIndex(self)
 	end
 end

-function MOD:SwapElement(unit, numGroup)
+function MOD:ViewEnemyFrames(unit, numGroup)
 	if InCombatLockdown()then return end
 	for i=1, numGroup do
 		local unitName = unit..i
@@ -1300,17 +1300,22 @@ function MOD:SwapElement(unit, numGroup)
 	end
 end

-function MOD:UpdateGroupConfig(headerFrame, setForced, overrideToken)
+local attrOverride = {
+	["showRaid"] = true,
+	["showParty"] = true,
+	["showSolo"] = true
+}
+
+function MOD:ViewGroupFrames(headerFrame, setForced)
 	if InCombatLockdown() then return end

 	SetProxyEnv()
+	local key = headerFrame.___groupkey
+	local db = SV.db.SVUnit[key]
 	headerFrame.forceShow = setForced;
 	headerFrame.forceShowAuras = setForced;
 	headerFrame.isForced = setForced;

-	local raidToken = headerFrame.___groupkey
-	local db = SV.db.SVUnit[raidToken]
-
 	if setForced then
 		for _, func in pairs(tags) do
 			if type(func) == "function" then
@@ -1333,30 +1338,29 @@ function MOD:UpdateGroupConfig(headerFrame, setForced, overrideToken)
 		end
 	end

-	local groupCount = db.groupCount
-	for i = 1, groupCount do
+	for i = 1, #headerFrame.groups do
 		local groupFrame = headerFrame.groups[i]
-		groupFrame.forceShow = headerFrame.forceShow;
-		groupFrame.forceShowAuras = headerFrame.forceShowAuras;
-		if(not groupFrame.ChangeHooked) then
+
+		if groupFrame:IsShown()then
+			groupFrame.forceShow = headerFrame.forceShow;
+			groupFrame.forceShowAuras = headerFrame.forceShowAuras;
 			groupFrame:HookScript("OnAttributeChanged", ChangeGroupIndex)
-			groupFrame.ChangeHooked = true
-		end
-		if setForced then
-			groupFrame:SetAttribute("showRaid", nil)
-			groupFrame:SetAttribute("showParty", nil)
-			groupFrame:SetAttribute("showSolo", nil)
+			if setForced then
+				for attr in pairs(attrOverride)do
+					groupFrame:SetAttribute(attr, nil)
+				end

-			ChangeGroupIndex(groupFrame)
-			groupFrame:Update()
-		else
-			groupFrame:SetAttribute("showRaid", true)
-			groupFrame:SetAttribute("showParty", true)
-			groupFrame:SetAttribute("showSolo", true)
+				ChangeGroupIndex(groupFrame)
+				groupFrame:Update()
+			else
+				for attr in pairs(attrOverride)do
+					groupFrame:SetAttribute(attr, true)
+				end

-			self:RestrictChildren(groupFrame, groupFrame:GetChildren())
-			groupFrame:SetAttribute("startingIndex", 1)
-			groupFrame:Update()
+				self:RestrictChildren(groupFrame, groupFrame:GetChildren())
+				groupFrame:SetAttribute("startingIndex", 1)
+				groupFrame:Update()
+			end
 		end
 	end

@@ -1382,13 +1386,13 @@ function MOD:FrameForge()
 		LoadedUnitFrames = true;
 	end
 	if not LoadedGroupHeaders then
-		self:SetRaidGroup("raid10")
-		self:SetRaidGroup("raid25")
-		self:SetRaidGroup("raid40")
-		self:SetRaidPetGroup("raidpet")
-		self:SetPartyGroup("party")
-		self:SetTankAssistFrame("tank")
-		self:SetTankAssistFrame("assist")
+		self:SetGroupFrame("raid10")
+		self:SetGroupFrame("raid25")
+		self:SetGroupFrame("raid40")
+		self:SetGroupFrame("raidpet", nil, "SVUI_UNITPET", nil, "SecureGroupPetHeaderTemplate")
+		self:SetGroupFrame("party", nil, "SVUI_UNITPET, SVUI_UNITTARGET")
+		self:SetGroupFrame("tank", "MAINTANK", "SVUI_UNITTARGET")
+		self:SetGroupFrame("assist", "MAINASSIST", "SVUI_UNITTARGET")
 		LoadedGroupHeaders = true
 	end
 end
diff --git a/Interface/AddOns/SVUI/packages/unit/SVUnit.xml b/Interface/AddOns/SVUI/packages/unit/SVUnit.xml
index a414258..a8bbb31 100644
--- a/Interface/AddOns/SVUI/packages/unit/SVUnit.xml
+++ b/Interface/AddOns/SVUI/packages/unit/SVUnit.xml
@@ -61,5 +61,4 @@
     <Script file="resources\warrior.lua"/>

     <Script file="frames.lua"/>
-    <Script file="groups.lua"/>
 </Ui>
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/packages/unit/elements/essentials.lua b/Interface/AddOns/SVUI/packages/unit/elements/essentials.lua
index 17f5170..1588993 100644
--- a/Interface/AddOns/SVUI/packages/unit/elements/essentials.lua
+++ b/Interface/AddOns/SVUI/packages/unit/elements/essentials.lua
@@ -673,7 +673,7 @@ end
 PORTRAIT
 ##########################################################
 ]]--
-function MOD:CreatePortrait(frame,smallUnit,isPlayer)
+function MOD:CreatePortrait(frame, smallUnit, isPlayer)
 	-- 3D Portrait
 	local portrait3D = CreateFrame("PlayerModel",nil,frame)
 	portrait3D:SetFrameStrata("LOW")
diff --git a/Interface/AddOns/SVUI/packages/unit/frames.lua b/Interface/AddOns/SVUI/packages/unit/frames.lua
index 6deac6f..8437d72 100644
--- a/Interface/AddOns/SVUI/packages/unit/frames.lua
+++ b/Interface/AddOns/SVUI/packages/unit/frames.lua
@@ -62,8 +62,68 @@ if(not MOD) then return end
 LOCAL DATA
 ##########################################################
 ]]--
-local CONSTRUCTORS = {}
+local CONSTRUCTORS, GROUP_UPDATES = {}, {}
 local lastArenaFrame, lastBossFrame
+local sortMapping = {
+    ["DOWN_RIGHT"] = {[1]="TOP",[2]="TOPLEFT",[3]="LEFT",[4]="RIGHT",[5]="LEFT",[6]=1,[7]=-1,[8]=false},
+    ["DOWN_LEFT"] = {[1]="TOP",[2]="TOPRIGHT",[3]="RIGHT",[4]="LEFT",[5]="RIGHT",[6]=1,[7]=-1,[8]=false},
+    ["UP_RIGHT"] = {[1]="BOTTOM",[2]="BOTTOMLEFT",[3]="LEFT",[4]="RIGHT",[5]="LEFT",[6]=1,[7]=1,[8]=false},
+    ["UP_LEFT"] = {[1]="BOTTOM",[2]="BOTTOMRIGHT",[3]="RIGHT",[4]="LEFT",[5]="RIGHT",[6]=-1,[7]=1,[8]=false},
+    ["RIGHT_DOWN"] = {[1]="LEFT",[2]="TOPLEFT",[3]="TOP",[4]="BOTTOM",[5]="TOP",[6]=1,[7]=-1,[8]=true},
+    ["RIGHT_UP"] = {[1]="LEFT",[2]="BOTTOMLEFT",[3]="BOTTOM",[4]="TOP",[5]="BOTTOM",[6]=1,[7]=1,[8]=true},
+    ["LEFT_DOWN"] = {[1]="RIGHT",[2]="TOPRIGHT",[3]="TOP",[4]="BOTTOM",[5]="TOP",[6]=-1,[7]=-1,[8]=true},
+    ["LEFT_UP"] = {[1]="RIGHT",[2]="BOTTOMRIGHT",[3]="BOTTOM",[4]="TOP",[5]="BOTTOM",[6]=-1,[7]=1,[8]=true},
+    ["UP"] = {[1]="BOTTOM",[2]="BOTTOM",[3]="BOTTOM",[4]="TOP",[5]="TOP",[6]=1,[7]=1,[8]=false},
+    ["DOWN"] = {[1]="TOP",[2]="TOP",[3]="TOP",[4]="BOTTOM",[5]="BOTTOM",[6]=1,[7]=1,[8]=false},
+}
+local GroupDistributor = {
+    ["CLASS"] = function(x)
+        x:SetAttribute("groupingOrder","DEATHKNIGHT,DRUID,HUNTER,MAGE,PALADIN,PRIEST,SHAMAN,WARLOCK,WARRIOR,MONK")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","CLASS")
+    end,
+    ["MTMA"] = function(x)
+        x:SetAttribute("groupingOrder","MAINTANK,MAINASSIST,NONE")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","ROLE")
+    end,
+    ["ROLE_TDH"] = function(x)
+        x:SetAttribute("groupingOrder","TANK,DAMAGER,HEALER,NONE")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","ASSIGNEDROLE")
+    end,
+    ["ROLE_HTD"] = function(x)
+        x:SetAttribute("groupingOrder","HEALER,TANK,DAMAGER,NONE")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","ASSIGNEDROLE")
+    end,
+    ["ROLE_HDT"] = function(x)
+        x:SetAttribute("groupingOrder","HEALER,DAMAGER,TANK,NONE")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","ASSIGNEDROLE")
+    end,
+    ["ROLE"] = function(x)
+        x:SetAttribute("groupingOrder","TANK,HEALER,DAMAGER,NONE")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy","ASSIGNEDROLE")
+    end,
+    ["NAME"] = function(x)
+        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy",nil)
+    end,
+    ["GROUP"] = function(x)
+        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
+        x:SetAttribute("sortMethod","INDEX")
+        x:SetAttribute("groupBy","GROUP")
+    end,
+    ["PETNAME"] = function(x)
+        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
+        x:SetAttribute("sortMethod","NAME")
+        x:SetAttribute("groupBy", nil)
+        x:SetAttribute("filterOnPet", true)
+    end
+}
 --[[
 ##########################################################
 ALL UNIT HELPERS
@@ -95,6 +155,8 @@ local UpdateTargetGlow = function(self)
 end
 --[[
 ##########################################################
+STANDARD UNITS
+##########################################################
 PLAYER
 ##########################################################
 ]]--
@@ -723,6 +785,50 @@ end
 ARENA
 ##########################################################
 ]]--
+local function CreatePrepFrame(frameName, parentFrame, parentID)
+    local prep = CreateFrame("Frame", frameName, UIParent)
+    prep:SetFrameStrata("MEDIUM")
+    prep:SetAllPoints(parentFrame)
+    prep:SetID(parentID)
+    prep:SetPanelTemplate("Bar", true, 3, 1, 1)
+
+    local health = CreateFrame("StatusBar", nil, prep)
+    health:SetAllPoints(prep)
+    health:SetStatusBarTexture([[Interface\AddOns\SVUI\assets\artwork\Bars\DEFAULT]])
+    prep.Health = health
+
+    local icon = CreateFrame("Frame", nil, prep)
+    icon:SetSize(45,45)
+    icon:SetPoint("LEFT", prep, "RIGHT", 2, 0)
+    icon:SetBackdrop({
+        bgFile = [[Interface\BUTTONS\WHITE8X8]],
+        tile = false,
+        tileSize = 0,
+        edgeFile = [[Interface\BUTTONS\WHITE8X8]],
+        edgeSize = 2,
+        insets = {
+            left = 0,
+            right = 0,
+            top = 0,
+            bottom = 0
+        }
+    })
+    icon:SetBackdropColor(0, 0, 0, 0)
+    icon:SetBackdropBorderColor(0, 0, 0)
+    icon.Icon = icon:CreateTexture(nil, "OVERLAY")
+    icon.Icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
+    icon.Icon:FillInner(icon, 2, 2)
+    prep.SpecIcon = icon
+
+    local text = prep.Health:CreateFontString(nil, "OVERLAY")
+    text:SetFont(SV.Media.font.names, 16, "OUTLINE")
+    text:SetTextColor(1, 1, 1)
+    text:SetPoint("CENTER")
+    prep.SpecClass = text
+
+    prep:Hide()
+end
+
 local UpdateArenaFrame = function(self)
     local db = SV.db.SVUnit["arena"]
     local INDEX = self:GetID() or 1;
@@ -827,49 +933,7 @@ CONSTRUCTORS["arena"] = function(self, unit)
     self.Range = { insideAlpha = 1, outsideAlpha = 1 }
     self:SetAttribute("type2", "focus")

-    if(not _G[prepName]) then
-        local prep = CreateFrame("Frame", prepName, UIParent)
-        prep:SetFrameStrata("MEDIUM")
-        prep:SetAllPoints(self)
-        prep:SetID(selfID)
-        prep:SetPanelTemplate("Bar", true, 3, 1, 1)
-
-        local health = CreateFrame("StatusBar", nil, prep)
-        health:SetAllPoints(prep)
-        health:SetStatusBarTexture([[Interface\AddOns\SVUI\assets\artwork\Bars\DEFAULT]])
-        prep.Health = health
-
-        local icon = CreateFrame("Frame", nil, prep)
-        icon:SetSize(45,45)
-        icon:SetPoint("LEFT", prep, "RIGHT", 2, 0)
-        icon:SetBackdrop({
-            bgFile = [[Interface\BUTTONS\WHITE8X8]],
-            tile = false,
-            tileSize = 0,
-            edgeFile = [[Interface\BUTTONS\WHITE8X8]],
-            edgeSize = 2,
-            insets = {
-                left = 0,
-                right = 0,
-                top = 0,
-                bottom = 0
-            }
-        })
-        icon:SetBackdropColor(0, 0, 0, 0)
-        icon:SetBackdropBorderColor(0, 0, 0)
-        icon.Icon = icon:CreateTexture(nil, "OVERLAY")
-        icon.Icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
-        icon.Icon:FillInner(icon, 2, 2)
-        prep.SpecIcon = icon
-
-        local text = prep.Health:CreateFontString(nil, "OVERLAY")
-        text:SetFont(SV.Media.font.names, 16, "OUTLINE")
-        text:SetTextColor(1, 1, 1)
-        text:SetPoint("CENTER")
-        prep.SpecClass = text
-
-        prep:Hide()
-    end
+    if(not _G[prepName]) then CreatePrepFrame(prepName, self, selfID) end

     if(not _G["SVUI_Arena_MOVE"]) then
         self:Point("RIGHT", SV.UIParent, "RIGHT", -105, 0)
@@ -1016,4 +1080,1050 @@ function MOD:SetEnemyFrames(key, maxCount)
             frame:Disable()
         end
     end
+end
+--[[
+##########################################################
+HEADER UNITS
+##########################################################
+HEADER FRAME HELPERS
+##########################################################
+]]--
+local GroupMediaUpdate = function(self)
+    local key = self.___groupkey
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+    while childFrame do
+        MOD.RefreshUnitMedia(childFrame, key)
+        if(_G[childFrame:GetName().."Pet"]) then
+            MOD.RefreshUnitMedia(_G[childFrame:GetName().."Pet"], key)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            MOD.RefreshUnitMedia(_G[childFrame:GetName().."Target"], key)
+        end
+        childFrame:UpdateAllElements()
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+local DetachSubFrames = function(...)
+    for i = 1, select("#", ...) do
+        local frame = select(i,...)
+        frame:ClearAllPoints()
+    end
+end
+--[[
+##########################################################
+RAID 10, 25, 40
+##########################################################
+]]--
+local Raid10Visibility = function(self, event)
+    local db = SV.db.SVUnit["raid10"]
+    if (not db or (db and not db.enable) or (SV.db.SVUnit and not SV.db.SVUnit.smartRaidFilter) or self.isForced) then return end
+
+    local instance, instanceType = IsInInstance()
+    if(event == "PLAYER_REGEN_ENABLED") then
+        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+    end
+    if not InCombatLockdown() then
+        if(instance and (instanceType == "raid")) then
+            UnregisterStateDriver(self, "visibility")
+            local maxPlayers = select(5, GetInstanceInfo())
+            if((maxPlayers and maxPlayers == 10)) then
+                self:Show()
+            else
+                self:Hide()
+            end
+        elseif db.visibility then
+            RegisterStateDriver(self, "visibility", db.visibility)
+        end
+    else
+        self:RegisterEvent("PLAYER_REGEN_ENABLED")
+        return
+    end
+end
+
+local Raid25Visibility = function(self, event)
+    local db = SV.db.SVUnit["raid25"]
+    if (not db or (db and not db.enable) or (SV.db.SVUnit and not SV.db.SVUnit.smartRaidFilter) or self.isForced) then return end
+
+    local instance, instanceType = IsInInstance()
+
+    if event == "PLAYER_REGEN_ENABLED"then
+        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+    end
+    if not InCombatLockdown()then
+        if(instance and (instanceType == "raid")) then
+            UnregisterStateDriver(self, "visibility")
+            local maxPlayers = select(5, GetInstanceInfo())
+            if((maxPlayers and (maxPlayers > 10 and maxPlayers < 26))) then
+                self:Show()
+            else
+                self:Hide()
+            end
+        elseif db.visibility then
+            RegisterStateDriver(self, "visibility", db.visibility)
+        end
+    else
+        self:RegisterEvent("PLAYER_REGEN_ENABLED")
+        return
+    end
+end
+
+local Raid40Visibility = function(self, event)
+    local db = SV.db.SVUnit["raid40"]
+    if (not db or (db and not db.enable) or (SV.db.SVUnit and not SV.db.SVUnit.smartRaidFilter) or self.isForced) then return end
+
+    local instance, instanceType = IsInInstance()
+    if event == "PLAYER_REGEN_ENABLED"then
+        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+    end
+    if not InCombatLockdown()then
+        if(instance and (instanceType == "raid")) then
+            UnregisterStateDriver(self, "visibility")
+            local maxPlayers = select(5, GetInstanceInfo())
+            if((maxPlayers and maxPlayers > 25)) then
+                self:Show()
+            else
+                self:Hide()
+            end
+        elseif db.visibility then
+            RegisterStateDriver(self, "visibility", db.visibility)
+        end
+    else
+        self:RegisterEvent("PLAYER_REGEN_ENABLED")
+        return
+    end
+end
+
+local UpdateRaidSubUnit = function(self, key, db)
+    self.colors = oUF_Villain.colors;
+    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
+    local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
+    if not InCombatLockdown() then
+        self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+    end
+    do
+        local rdBuffs = self.RaidDebuffs;
+        if db.rdebuffs.enable then
+            if not self:IsElementEnabled('RaidDebuffs')then
+                self:EnableElement("RaidDebuffs")
+            end
+            local actualSz = numMin(db.rdebuffs.size, (UNIT_HEIGHT - 8))
+            rdBuffs:Size(actualSz)
+            rdBuffs:Point("CENTER", self, "CENTER", db.rdebuffs.xOffset, db.rdebuffs.yOffset)
+            rdBuffs:Show()
+        else
+            self:DisableElement("RaidDebuffs")
+            rdBuffs:Hide()
+        end
+    end
+    MOD.RefreshUnitMedia(self, key)
+    MOD:UpdateAuraWatch(self, key)
+    MOD:RefreshUnitLayout(self, key)
+    if(key ~= "raidpet") then
+        self:EnableElement("ReadyCheck")
+    end
+    self:UpdateAllElements()
+end
+
+GROUP_UPDATES["raid10"] = function(self)
+    local frame = self:GetParent()
+    if not frame.positioned then
+        frame:ClearAllPoints()
+        frame:Point("LEFT", SV.UIParent, "LEFT", 4, 0)
+        SV.Mentalo:Add(frame, L["Raid 10 Frames"], nil, nil, nil, "ALL, RAID"..10)
+        frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+        frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+        frame:SetScript("OnEvent", Raid10Visibility)
+        frame.positioned = true
+    end
+    Raid10Visibility(frame)
+    local key = "raid10"
+    local db = SV.db.SVUnit[key]
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+    while childFrame do
+        UpdateRaidSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+GROUP_UPDATES["raid25"] = function(self)
+    local frame = self:GetParent()
+    if not frame.positioned then
+        frame:ClearAllPoints()
+        frame:Point("LEFT", SV.UIParent, "LEFT", 4, 0)
+        SV.Mentalo:Add(frame, L["Raid 25 Frames"], nil, nil, nil, "ALL, RAID"..25)
+        frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+        frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+        frame:SetScript("OnEvent", Raid25Visibility)
+        frame.positioned = true
+    end
+    Raid25Visibility(frame)
+    local key = "raid25"
+    local db = SV.db.SVUnit[key]
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+    while childFrame do
+        UpdateRaidSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+GROUP_UPDATES["raid40"] = function(self)
+    local frame = self:GetParent()
+    if not frame.positioned then
+        frame:ClearAllPoints()
+        frame:Point("LEFT", SV.UIParent, "LEFT", 4, 0)
+        SV.Mentalo:Add(frame, L["Raid 40 Frames"], nil, nil, nil, "ALL, RAID"..40)
+        frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+        frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+        frame:SetScript("OnEvent", Raid40Visibility)
+        frame.positioned = true
+    end
+    Raid40Visibility(frame)
+    local key = "raid40"
+    local db = SV.db.SVUnit[key]
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+    while childFrame do
+        UpdateRaidSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+local function SetRaidFrame(frame)
+    frame:SetScript("OnEnter", UnitFrame_OnEnter)
+    frame:SetScript("OnLeave", UnitFrame_OnLeave)
+
+    frame.RaidDebuffs = MOD:CreateRaidDebuffs(frame)
+    frame.Afflicted = MOD:CreateAfflicted(frame)
+    frame.ResurrectIcon = MOD:CreateResurectionIcon(frame)
+    frame.LFDRole = MOD:CreateRoleIcon(frame)
+    frame.RaidRoleFramesAnchor = MOD:CreateRaidRoleFrames(frame)
+    frame.RaidIcon = MOD:CreateRaidIcon(frame)
+    frame.ReadyCheck = MOD:CreateReadyCheckIcon(frame)
+    frame.HealPrediction = MOD:CreateHealPrediction(frame)
+    frame.Range = { insideAlpha = 1, outsideAlpha = 1 }
+
+    local shadow = CreateFrame("Frame", nil, frame)
+    shadow:SetFrameLevel(1)
+    shadow:SetFrameStrata(frame:GetFrameStrata())
+    shadow:WrapOuter(frame, 3, 3)
+    shadow:SetBackdrop({
+        edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
+        edgeSize = 3,
+        insets = {
+            left = 5,
+            right = 5,
+            top = 5,
+            bottom = 5
+        }
+    })
+    shadow:SetBackdropColor(0, 0, 0, 0)
+    shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
+    shadow:Hide()
+    frame.TargetGlow = shadow
+    tinsert(frame.__elements, UpdateTargetGlow)
+    frame:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
+    frame:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
+
+    return frame
+end
+
+CONSTRUCTORS["raid10"] = function(self, unit)
+    local key = "raid10"
+    self.unit = unit
+    self.___key = key
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.Health.frequentUpdates = false
+    self.Power = MOD:CreatePowerBar(self, true)
+    self.Power.frequentUpdates = false
+    self.Buffs = MOD:CreateBuffs(self, key)
+    self.Debuffs = MOD:CreateDebuffs(self, key)
+    self.AuraWatch = MOD:CreateAuraWatch(self, key)
+    return SetRaidFrame(self)
+end
+
+CONSTRUCTORS["raid25"] = function(self, unit)
+    local key = "raid25"
+    self.unit = unit
+    self.___key = key
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.Health.frequentUpdates = false
+    self.Power = MOD:CreatePowerBar(self, true)
+    self.Power.frequentUpdates = false
+    self.Buffs = MOD:CreateBuffs(self, key)
+    self.Debuffs = MOD:CreateDebuffs(self, key)
+    self.AuraWatch = MOD:CreateAuraWatch(self, key)
+    return SetRaidFrame(self)
+end
+
+CONSTRUCTORS["raid40"] = function(self, unit)
+    local key = "raid40"
+    self.unit = unit
+    self.___key = key
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.Health.frequentUpdates = false
+    self.Power = MOD:CreatePowerBar(self, true)
+    self.Power.frequentUpdates = false
+    self.Buffs = MOD:CreateBuffs(self, key)
+    self.Debuffs = MOD:CreateDebuffs(self, key)
+    self.AuraWatch = MOD:CreateAuraWatch(self, key)
+    return SetRaidFrame(self)
+end
+--[[
+##########################################################
+RAID PETS
+##########################################################
+]]--
+local RaidPetVisibility = function(self, event)
+    local db = SV.db.SVUnit["raidpet"]
+    if (not db or (db and not db.enable) or (SV.db.SVUnit and not SV.db.SVUnit.smartRaidFilter) or self.isForced) then return end
+    local inInstance, instanceType = IsInInstance()
+    if event == "PLAYER_REGEN_ENABLED" then self:UnregisterEvent("PLAYER_REGEN_ENABLED") end
+
+    if not InCombatLockdown() then
+        if inInstance and instanceType == "raid" then
+            UnregisterStateDriver(self, "visibility")
+            self:Show()
+        elseif db.visibility then
+            RegisterStateDriver(self, "visibility", db.visibility)
+        end
+    else
+        self:RegisterEvent("PLAYER_REGEN_ENABLED")
+        return
+    end
+end
+
+GROUP_UPDATES["raidpet"] = function(self)
+    local raidPets = self:GetParent()
+    if not raidPets.positioned then
+        raidPets:ClearAllPoints()
+        raidPets:Point("BOTTOMLEFT", SV.UIParent, "BOTTOMLEFT", 4, 433)
+        SV.Mentalo:Add(raidPets, L["Raid Pet Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
+        raidPets:RegisterEvent("PLAYER_ENTERING_WORLD")
+        raidPets:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+        raidPets:SetScript("OnEvent", RaidPetVisibility)
+        raidPets.positioned = true;
+    end
+    RaidPetVisibility(raidPets)
+    local key = "raidpet"
+    local db = SV.db.SVUnit[key]
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+    while childFrame do
+        UpdateRaidSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateRaidSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+CONSTRUCTORS["raidpet"] = function(self, unit)
+    local key = "raidpet"
+    self.unit = unit
+    self.___key = key
+    self:SetScript("OnEnter", UnitFrame_OnEnter)
+    self:SetScript("OnLeave", UnitFrame_OnLeave)
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.Debuffs = MOD:CreateDebuffs(self, key)
+    self.AuraWatch = MOD:CreateAuraWatch(self, key)
+    self.RaidDebuffs = MOD:CreateRaidDebuffs(self)
+    self.Afflicted = MOD:CreateAfflicted(self)
+    self.RaidIcon = MOD:CreateRaidIcon(self)
+    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
+
+    local shadow = CreateFrame("Frame", nil, self)
+    shadow:SetFrameLevel(1)
+    shadow:SetFrameStrata(self:GetFrameStrata())
+    shadow:WrapOuter(self, 3, 3)
+    shadow:SetBackdrop({
+        edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
+        edgeSize = 3,
+        insets = {
+            left = 5,
+            right = 5,
+            top = 5,
+            bottom = 5
+        }
+    })
+    shadow:SetBackdropColor(0, 0, 0, 0)
+    shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
+    shadow:Hide()
+    self.TargetGlow = shadow
+    tinsert(self.__elements, UpdateTargetGlow)
+
+    self:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
+    self:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
+    return self
+end
+--[[
+##########################################################
+PARTY
+##########################################################
+]]--
+local PartyVisibility = function(self, event)
+    local db = SV.db.SVUnit["party"]
+    if (not db or (db and not db.enable) or (SV.db.SVUnit and not SV.db.SVUnit.smartRaidFilter) or self.isForced) then return end
+    local instance, instanceType = IsInInstance()
+    if(event == "PLAYER_REGEN_ENABLED") then
+        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
+    end
+    if(not InCombatLockdown()) then
+        if(instance and instanceType == "raid") then
+            UnregisterStateDriver(self,"visibility")
+            self:Hide()
+        elseif db.visibility then
+            RegisterStateDriver(self, "visibility", db.visibility)
+        end
+    else
+        self:RegisterEvent("PLAYER_REGEN_ENABLED")
+    end
+end
+
+local UpdatePartySubUnit = function(self, key, db)
+    self.colors = oUF_Villain.colors;
+    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and 'AnyDown' or 'AnyUp')
+    MOD.RefreshUnitMedia(self, key)
+    if self.isChild then
+        local altDB = db.petsGroup;
+        if self == _G[self.originalParent:GetName()..'Target'] then
+            altDB = db.targetsGroup
+        end
+        if not self.originalParent.childList then
+            self.originalParent.childList = {}
+        end
+        self.originalParent.childList[self] = true;
+        if not InCombatLockdown()then
+            if altDB.enable then
+                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(altDB)
+                self:SetParent(self.originalParent)
+                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+                self:ClearAllPoints()
+                SV:ReversePoint(self, altDB.anchorPoint, self.originalParent, altDB.xOffset, altDB.yOffset)
+            else
+                self:SetParent(SV.Cloaked)
+            end
+        end
+        do
+            local health = self.Health;
+            health.Smooth = nil;
+            health.frequentUpdates = nil;
+            health.colorSmooth = nil;
+            health.colorHealth = nil;
+            health.colorClass = true;
+            health.colorReaction = true;
+            health:ClearAllPoints()
+            health:Point("TOPRIGHT", self, "TOPRIGHT", -1, -1)
+            health:Point("BOTTOMLEFT", self, "BOTTOMLEFT", 1, 1)
+        end
+        do
+            local nametext = self.InfoPanel.Name
+            self:Tag(nametext, altDB.tags)
+        end
+    else
+        if not InCombatLockdown() then
+            local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
+            self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+        end
+        MOD:RefreshUnitLayout(self, key)
+        MOD:UpdateAuraWatch(self, key)
+    end
+    self:EnableElement('ReadyCheck')
+    self:UpdateAllElements()
+end
+
+GROUP_UPDATES["party"] = function(self)
+    local group = self:GetParent()
+    if not group.positioned then
+        group:ClearAllPoints()
+        group:Point("LEFT",SV.UIParent,"LEFT",40,0)
+        SV.Mentalo:Add(group, L['Party Frames'], nil, nil, nil, 'ALL,PARTY,ARENA');
+        group:RegisterEvent("PLAYER_ENTERING_WORLD")
+        group:RegisterEvent("ZONE_CHANGED_NEW_AREA")
+        group:SetScript("OnEvent", PartyVisibility)
+        group.positioned = true;
+    end
+    PartyVisibility(group)
+    local key = "party"
+    local db = SV.db.SVUnit[key]
+    local index = 1;
+    local childFrame = self:GetAttribute("child"..index)
+
+    while childFrame do
+        UpdatePartySubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdatePartySubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdatePartySubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+        index = index + 1;
+        childFrame = self:GetAttribute("child"..index)
+    end
+end
+
+CONSTRUCTORS["party"] = function(self, unit)
+    local key = "party"
+    self.unit = unit
+    self.___key = key
+    self:SetScript("OnEnter", UnitFrame_OnEnter)
+    self:SetScript("OnLeave", UnitFrame_OnLeave)
+
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+
+    if self.isChild then
+        self.originalParent = self:GetParent()
+    else
+        self.Power = MOD:CreatePowerBar(self, true)
+        self.Power.frequentUpdates = false
+        MOD:CreatePortrait(self, true)
+        self.Buffs = MOD:CreateBuffs(self, key)
+        self.Debuffs = MOD:CreateDebuffs(self, key)
+        self.AuraWatch = MOD:CreateAuraWatch(self, key)
+        self.Afflicted = MOD:CreateAfflicted(self)
+        self.ResurrectIcon = MOD:CreateResurectionIcon(self)
+        self.LFDRole = MOD:CreateRoleIcon(self)
+        self.RaidRoleFramesAnchor = MOD:CreateRaidRoleFrames(self)
+        self.RaidIcon = MOD:CreateRaidIcon(self)
+        self.ReadyCheck = MOD:CreateReadyCheckIcon(self)
+        self.HealPrediction = MOD:CreateHealPrediction(self)
+        --self.GPS = MOD:CreateGPS(self, true)
+
+        local shadow = CreateFrame("Frame", nil, self)
+        shadow:SetFrameLevel(1)
+        shadow:SetFrameStrata(self:GetFrameStrata())
+        shadow:WrapOuter(self, 3, 3)
+        shadow:SetBackdrop({
+            edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
+            edgeSize = 3,
+            insets = {
+                left = 5,
+                right = 5,
+                top = 5,
+                bottom = 5
+            }
+        })
+        shadow:SetBackdropColor(0, 0, 0, 0)
+        shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
+        shadow:Hide()
+        self.TargetGlow = shadow
+        tinsert(self.__elements, UpdateTargetGlow)
+        self:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
+        self:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
+        self:RegisterEvent("GROUP_ROSTER_UPDATE", UpdateTargetGlow)
+    end
+
+    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
+    return self
+end
+--[[
+##########################################################
+TANK
+##########################################################
+]]--
+local UpdateTankSubUnit = function(self, key, db)
+    self.colors = oUF_Villain.colors;
+    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
+    MOD.RefreshUnitMedia(self, key)
+    if self.isChild and self.originalParent then
+        local targets = db.targetsGroup;
+        if not self.originalParent.childList then
+            self.originalParent.childList = {}
+        end
+        self.originalParent.childList[self] = true;
+        if not InCombatLockdown()then
+            if targets.enable then
+                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(targets)
+                self:SetParent(self.originalParent)
+                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+                self:ClearAllPoints()
+                SV:ReversePoint(self, targets.anchorPoint, self.originalParent, targets.xOffset, targets.yOffset)
+            else
+                self:SetParent(SV.Cloaked)
+            end
+        end
+    elseif not InCombatLockdown() then
+        local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
+        self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+    end
+    MOD:RefreshUnitLayout(self, key)
+    do
+        local nametext = self.InfoPanel.Name;
+        if oUF_Villain.colors.healthclass then
+            self:Tag(nametext, "[name:10]")
+        else
+            self:Tag(nametext, "[name:color][name:10]")
+        end
+    end
+    self:UpdateAllElements()
+end
+
+local UpdateTankFrame = function(self)
+    local key = "tank"
+    local db = SV.db.SVUnit[key]
+    if db.enable ~= true then
+        UnregisterAttributeDriver(self, "state-visibility")
+        self:Hide()
+        return
+    end
+    self:Hide()
+    DetachSubFrames(self:GetChildren())
+    self:SetAttribute("startingIndex", -1)
+    RegisterAttributeDriver(self, "state-visibility", "show")
+    self.dirtyWidth, self.dirtyHeight = self:GetSize()
+    RegisterAttributeDriver(self, "state-visibility", "[@raid1, exists] show;hide")
+    self:SetAttribute("startingIndex", 1)
+    self:SetAttribute("point", "BOTTOM")
+    self:SetAttribute("columnAnchorPoint", "LEFT")
+    DetachSubFrames(self:GetChildren())
+    self:SetAttribute("yOffset", 7)
+    if not self.positioned then
+        self:ClearAllPoints()
+        self:Point("TOPLEFT", SV.UIParent, "TOPLEFT", 4, -40)
+        SV.Mentalo:Add(self, L["Tank Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
+        self.Avatar.positionOverride = "TOPLEFT"
+        self:SetAttribute("minHeight", self.dirtyHeight)
+        self:SetAttribute("minWidth", self.dirtyWidth)
+        self.positioned = true
+    end
+    for i = 1, self:GetNumChildren() do
+        local childFrame = select(i, self:GetChildren())
+        UpdateTankSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateTankSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateTankSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+    end
+end
+
+CONSTRUCTORS["tank"] = function(self, unit)
+    local key = "tank"
+    local db = SV.db.SVUnit[key]
+    self.unit = unit
+    self.___key = key
+    self:SetScript("OnEnter", UnitFrame_OnEnter)
+    self:SetScript("OnLeave", UnitFrame_OnLeave)
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.RaidIcon = MOD:CreateRaidIcon(self)
+    self.RaidIcon:SetPoint("BOTTOMRIGHT")
+    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
+    UpdateTankSubUnit(self, key, db)
+    self.originalParent = self:GetParent()
+    return self
+end
+--[[
+##########################################################
+ASSIST
+##########################################################
+]]--
+local UpdateAssistSubUnit = function(self, key, db)
+    self.colors = oUF_Villain.colors;
+    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
+    MOD.RefreshUnitMedia(self, key)
+    if self.isChild and self.originalParent then
+        local targets = db.targetsGroup;
+        if not self.originalParent.childList then
+            self.originalParent.childList = {}
+        end
+        self.originalParent.childList[self] = true;
+        if not InCombatLockdown()then
+            if targets.enable then
+                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(targets)
+                self:SetParent(self.originalParent)
+                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+                self:ClearAllPoints()
+                SV:ReversePoint(self, targets.anchorPoint, self.originalParent, targets.xOffset, targets.yOffset)
+            else
+                self:SetParent(SV.Cloaked)
+            end
+        end
+    elseif not InCombatLockdown() then
+        local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
+        self:Size(UNIT_WIDTH, UNIT_HEIGHT)
+    end
+
+    MOD:RefreshUnitLayout(self, key)
+
+    do
+        local nametext = self.InfoPanel.Name;
+        if oUF_Villain.colors.healthclass then
+            self:Tag(nametext, "[name:10]")
+        else
+            self:Tag(nametext, "[name:color][name:10]")
+        end
+    end
+    self:UpdateAllElements()
+end
+
+local UpdateAssistFrame = function(self)
+    local key = "assist"
+    local db = SV.db.SVUnit[key]
+    self:Hide()
+    DetachSubFrames(self:GetChildren())
+    self:SetAttribute("startingIndex", -1)
+    RegisterAttributeDriver(self, "state-visibility", "show")
+    self.dirtyWidth, self.dirtyHeight = self:GetSize()
+    RegisterAttributeDriver(self, "state-visibility", "[@raid1, exists] show;hide")
+    self:SetAttribute("startingIndex", 1)
+    self:SetAttribute("point", "BOTTOM")
+    self:SetAttribute("columnAnchorPoint", "LEFT")
+    DetachSubFrames(self:GetChildren())
+    self:SetAttribute("yOffset", 7)
+    if not self.positioned then
+        self:ClearAllPoints()
+        self:Point("TOPLEFT", SV.UIParent, "TOPLEFT", 4, -140)
+        SV.Mentalo:Add(self, L["Assist Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
+        self.Avatar.positionOverride = "TOPLEFT"
+        self:SetAttribute("minHeight", self.dirtyHeight)
+        self:SetAttribute("minWidth", self.dirtyWidth)
+        self.positioned = true
+    end
+    for i = 1, self:GetNumChildren() do
+        local childFrame = select(i, self:GetChildren())
+        UpdateAssistSubUnit(childFrame, key, db)
+        if(_G[childFrame:GetName().."Pet"]) then
+            UpdateAssistSubUnit(_G[childFrame:GetName().."Pet"], key, db)
+        end
+        if(_G[childFrame:GetName().."Target"]) then
+            UpdateAssistSubUnit(_G[childFrame:GetName().."Target"], key, db)
+        end
+    end
+end
+
+CONSTRUCTORS["assist"] = function(self, unit)
+    local key = "assist"
+    local db = SV.db.SVUnit[key]
+    self.unit = unit
+    self.___key = key
+    self:SetScript("OnEnter", UnitFrame_OnEnter)
+    self:SetScript("OnLeave", UnitFrame_OnLeave)
+    MOD:SetActionPanel(self, key)
+    self.Health = MOD:CreateHealthBar(self, true)
+    self.RaidIcon = MOD:CreateRaidIcon(self)
+    self.RaidIcon:SetPoint("BOTTOMRIGHT")
+    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
+    UpdateAssistSubUnit(self, key, db)
+    self.originalParent = self:GetParent()
+    return self
+end
+--[[
+##########################################################
+GROUP HEADER METHODS
+##########################################################
+]]--
+local GroupSetConfigEnvironment = function(self)
+    local key = self.___groupkey
+    local db = SV.db.SVUnit[key]
+    local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
+    local anchorPoint;
+    local sorting = db.showBy
+    local pointMap = sortMapping[sorting]
+    local sortMethod = db.sortMethod
+    local widthCalc, heightCalc, xCalc, yCalc = 0, 0, 0, 0;
+    local point1, point2, point3, point4, point5, horizontal, vertical, isHorizontal = pointMap[1], pointMap[2], pointMap[3], pointMap[4], pointMap[5], pointMap[6], pointMap[7], pointMap[8];
+    for i = 1, db.groupCount do
+        local frame = self.groups[i]
+        if frame then
+            if(db.showBy == "UP") then
+                db.showBy = "UP_RIGHT"
+            end
+            if(db.showBy == "DOWN") then
+                db.showBy = "DOWN_RIGHT"
+            end
+            if isHorizontal then
+                frame:SetAttribute("xOffset", db.wrapXOffset * horizontal)
+                frame:SetAttribute("yOffset", 0)
+                frame:SetAttribute("columnSpacing", db.wrapYOffset)
+            else
+                frame:SetAttribute("xOffset", 0)
+                frame:SetAttribute("yOffset", db.wrapYOffset * vertical)
+                frame:SetAttribute("columnSpacing", db.wrapXOffset)
+            end
+            if not frame.isForced then
+                if not frame.initialized then
+                    frame:SetAttribute("startingIndex", db.customSorting and (-numMin(db.groupCount * db.gRowCol * 5, MAX_RAID_MEMBERS) + 1) or -4)
+                    frame:Show()
+                    frame.initialized = true
+                end
+                frame:SetAttribute("startingIndex", 1)
+            end
+            frame:ClearAllPoints()
+            if db.customSorting and db.invertGroupingOrder then
+                frame:SetAttribute("columnAnchorPoint", point4)
+            else
+                frame:SetAttribute("columnAnchorPoint", point3)
+            end
+            DetachSubFrames(frame:GetChildren())
+            frame:SetAttribute("point", point1)
+            if not frame.isForced then
+                frame:SetAttribute("maxColumns", db.customSorting and db.groupCount or 1)
+                frame:SetAttribute("unitsPerColumn", db.customSorting and (db.gRowCol * 5) or 5)
+                GroupDistributor[sortMethod](frame)
+                frame:SetAttribute("sortDir", db.sortDir)
+                frame:SetAttribute("showPlayer", db.showPlayer)
+            end
+            if i == 1 and db.customSorting then
+                frame:SetAttribute("groupFilter", "1, 2, 3, 4, 5, 6, 7, 8")
+            else
+                frame:SetAttribute("groupFilter", tostring(i))
+            end
+        end
+        local anchorPoint = point2
+        if db.customSorting and db.startFromCenter then
+            anchorPoint = point5
+        end
+        if (i - 1) % db.gRowCol == 0 then
+            if isHorizontal then
+                if frame then
+                    frame:SetPoint(anchorPoint, self, anchorPoint, 0, heightCalc * vertical)
+                end
+                heightCalc = heightCalc + UNIT_HEIGHT + db.wrapYOffset;
+                yCalc = yCalc + 1
+            else
+                if frame then
+                    frame:SetPoint(anchorPoint, self, anchorPoint, widthCalc * horizontal, 0)
+                end
+                widthCalc = widthCalc + UNIT_WIDTH + db.wrapXOffset;
+                xCalc = xCalc + 1
+            end
+        else
+            if isHorizontal then
+                if yCalc == 1 then
+                    if frame then
+                        frame:SetPoint(anchorPoint, self, anchorPoint, widthCalc * horizontal, 0)
+                    end
+                    widthCalc = widthCalc + (UNIT_WIDTH + db.wrapXOffset) * 5;
+                    xCalc = xCalc + 1
+                elseif frame then
+                    frame:SetPoint(anchorPoint, self, anchorPoint, (((UNIT_WIDTH + db.wrapXOffset) * 5) * ((i - 1) % db.gRowCol)) * horizontal, ((UNIT_HEIGHT + db.wrapYOffset) * (yCalc - 1)) * vertical)
+                end
+            else
+                if xCalc == 1 then
+                    if frame then
+                        frame:SetPoint(anchorPoint, self, anchorPoint, 0, heightCalc * vertical)
+                    end
+                    heightCalc = heightCalc + (UNIT_HEIGHT + db.wrapYOffset) * 5;
+                    yCalc = yCalc + 1
+                elseif frame then
+                    frame:SetPoint(anchorPoint, self, anchorPoint, ((UNIT_WIDTH + db.wrapXOffset) * (xCalc - 1)) * horizontal, (((UNIT_HEIGHT + db.wrapYOffset) * 5) * ((i - 1) % db.gRowCol)) * vertical)
+                end
+            end
+        end
+        if heightCalc == 0 then
+            heightCalc = heightCalc + (UNIT_HEIGHT + db.wrapYOffset) * 5
+        elseif widthCalc == 0 then
+            widthCalc = widthCalc + (UNIT_WIDTH + db.wrapXOffset) * 5
+        end
+    end
+    self:SetSize(widthCalc - db.wrapXOffset, heightCalc - db.wrapYOffset)
+end
+
+local GroupHeaderUpdate = function(self)
+    local key = self.___groupkey
+    if SV.db.SVUnit[key].enable ~= true then
+        UnregisterAttributeDriver(self, "state-visibility")
+        self:Hide()
+        return
+    end
+    for i=1,#self.groups do
+        self.groups[i]:Update()
+    end
+end
+
+local GroupHeaderMediaUpdate = function(self)
+    for i=1,#self.groups do
+        self.groups[i]:MediaUpdate()
+    end
+end
+
+local GroupSetActiveState = function(self)
+    if not self.isForced then
+        local key = self.___groupkey
+        local db = SV.db.SVUnit[key]
+        if(db) then
+            for i=1,#self.groups do
+                local frame = self.groups[i]
+                if(i <= db.groupCount and ((db.customSorting and i <= 1) or not db.customSorting)) then
+
+                    frame:Show()
+                else
+                    if frame.forceShow then
+                        frame:Hide()
+                        MOD:RestrictChildren(frame, frame:GetChildren())
+                        frame:SetAttribute('startingIndex',1)
+                    else
+                        frame:ClearAllAttributes()
+                    end
+                end
+            end
+        end
+    end
+end
+--[[
+##########################################################
+SUBUNIT CONSTRUCTORS
+##########################################################
+]]--
+local SecureHeaderClear = function(self)
+    self:Hide()
+    self:SetAttribute("showPlayer", true)
+    self:SetAttribute("showSolo", true)
+    self:SetAttribute("showParty", true)
+    self:SetAttribute("showRaid", true)
+    self:SetAttribute("columnSpacing", nil)
+    self:SetAttribute("columnAnchorPoint", nil)
+    self:SetAttribute("sortMethod", nil)
+    self:SetAttribute("groupFilter", nil)
+    self:SetAttribute("groupingOrder", nil)
+    self:SetAttribute("maxColumns", nil)
+    self:SetAttribute("nameList", nil)
+    self:SetAttribute("point", nil)
+    self:SetAttribute("sortDir", nil)
+    self:SetAttribute("sortMethod", "NAME")
+    self:SetAttribute("startingIndex", nil)
+    self:SetAttribute("strictFiltering", nil)
+    self:SetAttribute("unitsPerColumn", nil)
+    self:SetAttribute("xOffset", nil)
+    self:SetAttribute("yOffset", nil)
+end
+
+function MOD:ConstructGroupHeader(parentFrame, filter, styleName, headerName, template1, groupName, template2, updateFunc)
+    local db = SV.db.SVUnit[groupName]
+    local UNIT_WIDTH, UNIT_HEIGHT = self:GetActiveSize(db)
+
+    oUF_Villain:SetActiveStyle(styleName)
+    local groupHeader = oUF_Villain:SpawnHeader(headerName, template2, nil,
+        "oUF-initialConfigFunction", ("self:SetWidth(%d); self:SetHeight(%d); self:SetFrameLevel(5)"):format(UNIT_WIDTH, UNIT_HEIGHT),
+        "groupFilter", filter,
+        "showParty", true,
+        "showRaid", true,
+        "showSolo", true,
+        template1 and "template", template1
+    )
+    groupHeader.___groupkey = groupName
+    groupHeader:SetParent(parentFrame)
+    groupHeader:Show()
+
+    groupHeader.Update = updateFunc or GROUP_UPDATES[groupName]
+    groupHeader.MediaUpdate = GroupMediaUpdate
+    groupHeader.ClearAllAttributes = SecureHeaderClear
+
+    return groupHeader
+end
+--[[
+##########################################################
+LOAD/UPDATE METHOD
+##########################################################
+]]--
+function MOD:SetGroupFrame(key, filter, template1, forceUpdate, template2)
+    if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
+    if(not SV.db.SVUnit.enable or not SV.db.SVUnit[key]) then return end
+    local db = SV.db.SVUnit[key]
+    local realName = key:gsub("(.)", upper, 1)
+    local styleName = "SVUI_"..realName
+    local frame, groupName
+
+    if(not self.Headers[key]) then
+        oUF_Villain:RegisterStyle(styleName, CONSTRUCTORS[key])
+        oUF_Villain:SetActiveStyle(styleName)
+
+        if(key == "tank") then
+            frame = self:ConstructGroupHeader(SVUI_UnitFrameParent, filter, styleName, styleName, template1, key, template2, UpdateTankFrame)
+        elseif(key == "assist") then
+            frame = self:ConstructGroupHeader(SVUI_UnitFrameParent, filter, styleName, styleName, template1, key, template2, UpdateAssistFrame)
+        else
+            frame = CreateFrame("Frame", styleName, SVUI_UnitFrameParent, "SecureHandlerStateTemplate")
+            frame.groups = {}
+            frame.___groupkey = key;
+            frame.Update = GroupHeaderUpdate
+            frame.MediaUpdate = GroupHeaderMediaUpdate
+            frame.SetActiveState = GroupSetActiveState
+            frame.SetConfigEnvironment = GroupSetConfigEnvironment
+        end
+        frame:Show()
+        self.Headers[key] = frame
+    else
+        frame = self.Headers[key]
+    end
+
+    if(key == "tank" or key == "assist") then
+        frame:Update()
+    else
+        if(db.enable ~= true and key ~= "raidpet") then
+            UnregisterStateDriver(frame, "visibility")
+            frame:Hide()
+            return
+        end
+
+        if(db.customSorting) then
+            if(not frame.groups[1]) then
+                groupName = styleName .. "Group1"
+                local subunit = self:ConstructGroupHeader(frame, 1, styleName, groupName, template1, key, template2)
+                frame.groups[1] = subunit
+            end
+        else
+            for i = 1, db.groupCount do
+                if(not frame.groups[i]) then
+                    groupName = styleName .. "Group" .. i
+                    local subunit = self:ConstructGroupHeader(frame, i, styleName, groupName, template1, key, template2)
+                    frame.groups[i] = subunit
+                end
+            end
+        end
+
+        frame:SetActiveState()
+
+        if(forceUpdate or not frame.Avatar) then
+            frame:SetConfigEnvironment()
+            if(not frame.isForced) then
+                RegisterStateDriver(frame, "visibility", db.visibility)
+            end
+        else
+            frame:SetConfigEnvironment()
+            frame:Update()
+        end
+
+        if(db.enable ~= true and key == "raidpet") then
+            UnregisterStateDriver(frame, "visibility")
+            frame:Hide()
+            return
+        end
+    end
 end
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/packages/unit/groups.lua b/Interface/AddOns/SVUI/packages/unit/groups.lua
deleted file mode 100644
index 99bce41..0000000
--- a/Interface/AddOns/SVUI/packages/unit/groups.lua
+++ /dev/null
@@ -1,1220 +0,0 @@
---[[
-##############################################################################
-_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
- ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
-  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
-   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
-    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
-     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
-      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
-       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
-        ___\///////////___________\///___________\/////////_____\///////////_#
-##############################################################################
-S U P E R - V I L L A I N - U I   By: Munglunch                              #
-##############################################################################
---]]
---LUA
-local unpack        = unpack;
-local select        = select;
-local pairs         = pairs;
-local type          = type;
-local rawset        = rawset;
-local rawget        = rawget;
-local tostring      = tostring;
-local error         = error;
-local next          = next;
-local pcall         = pcall;
-local getmetatable  = getmetatable;
-local setmetatable  = setmetatable;
-local assert        = assert;
---BLIZZARD
-local _G            = _G;
-local tinsert       = _G.tinsert;
-local tremove       = _G.tremove;
-local twipe         = _G.wipe;
---STRING
-local string        = string;
-local format        = string.format;
-local sub           = string.sub;
-local upper         = string.upper;
-local match         = string.match;
-local gsub          = string.gsub;
---MATH
-local math          = math;
-local numMin        = math.min;
---TABLE
-local table         = table;
-local tsort         = table.sort;
-local tremove       = table.remove;
-
-local SV = select(2, ...)
-local oUF_Villain = SV.oUF
-
-assert(oUF_Villain, "SVUI was unable to locate oUF.")
-
-local L = SV.L;
-local MOD = SV.SVUnit
-
-if(not MOD) then return end
---[[
-##########################################################
-LOCAL DATA
-##########################################################
-]]--
-local sortMapping = {
-    ["DOWN_RIGHT"] = {[1]="TOP",[2]="TOPLEFT",[3]="LEFT",[4]=1,[5]=-1,[6]=false},
-    ["DOWN_LEFT"] = {[1]="TOP",[2]="TOPRIGHT",[3]="RIGHT",[4]=1,[5]=-1,[6]=false},
-    ["UP_RIGHT"] = {[1]="BOTTOM",[2]="BOTTOMLEFT",[3]="LEFT",[4]=1,[5]=1,[6]=false},
-    ["UP_LEFT"] = {[1]="BOTTOM",[2]="BOTTOMRIGHT",[3]="RIGHT",[4]=-1,[5]=1,[6]=false},
-    ["RIGHT_DOWN"] = {[1]="LEFT",[2]="TOPLEFT",[3]="TOP",[4]=1,[5]=-1,[6]=true},
-    ["RIGHT_UP"] = {[1]="LEFT",[2]="BOTTOMLEFT",[3]="BOTTOM",[4]=1,[5]=1,[6]=true},
-    ["LEFT_DOWN"] = {[1]="RIGHT",[2]="TOPRIGHT",[3]="TOP",[4]=-1,[5]=-1,[6]=true},
-    ["LEFT_UP"] = {[1]="RIGHT",[2]="BOTTOMRIGHT",[3]="BOTTOM",[4]=-1,[5]=1,[6]=true},
-    ["UP"] = {[1]="BOTTOM",[2]="BOTTOM",[3]="BOTTOM",[4]=1,[5]=1,[6]=false},
-    ["DOWN"] = {[1]="TOP",[2]="TOP",[3]="TOP",[4]=1,[5]=1,[6]=false},
-}
-local GroupDistributor = {
-    ["CLASS"] = function(x)
-        x:SetAttribute("groupingOrder","DEATHKNIGHT,DRUID,HUNTER,MAGE,PALADIN,PRIEST,SHAMAN,WARLOCK,WARRIOR,MONK")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","CLASS")
-    end,
-    ["MTMA"] = function(x)
-        x:SetAttribute("groupingOrder","MAINTANK,MAINASSIST,NONE")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","ROLE")
-    end,
-    ["ROLE_TDH"] = function(x)
-        x:SetAttribute("groupingOrder","TANK,DAMAGER,HEALER,NONE")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","ASSIGNEDROLE")
-    end,
-    ["ROLE_HTD"] = function(x)
-        x:SetAttribute("groupingOrder","HEALER,TANK,DAMAGER,NONE")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","ASSIGNEDROLE")
-    end,
-    ["ROLE_HDT"] = function(x)
-        x:SetAttribute("groupingOrder","HEALER,DAMAGER,TANK,NONE")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","ASSIGNEDROLE")
-    end,
-    ["ROLE"] = function(x)
-        x:SetAttribute("groupingOrder","TANK,HEALER,DAMAGER,NONE")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy","ASSIGNEDROLE")
-    end,
-    ["NAME"] = function(x)
-        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy",nil)
-    end,
-    ["GROUP"] = function(x)
-        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
-        x:SetAttribute("sortMethod","INDEX")
-        x:SetAttribute("groupBy","GROUP")
-    end,
-    ["PETNAME"] = function(x)
-        x:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
-        x:SetAttribute("sortMethod","NAME")
-        x:SetAttribute("groupBy", nil)
-        x:SetAttribute("filterOnPet", true)
-    end
-}
---[[
-##########################################################
-FRAME HELPERS
-##########################################################
-]]--
-local function GetRaidToken(active)
-    local maxPlayers = select(5, GetInstanceInfo())
-    local token = "raid10";
-    if(maxPlayers > 10 and maxPlayers < 40) then
-        token = "raid25"
-    elseif(maxPlayers > 25) then
-        token = "raid40"
-    end
-
-    return token == active
-end
-
-local UpdateTargetGlow = function(self)
-    if not self.unit then return end
-    local unit = self.unit;
-    if(UnitIsUnit(unit, "target")) then
-        self.TargetGlow:Show()
-        local reaction = UnitReaction(unit, "player")
-        if(UnitIsPlayer(unit)) then
-            local _, class = UnitClass(unit)
-            if class then
-                local colors = RAID_CLASS_COLORS[class]
-                self.TargetGlow:SetBackdropBorderColor(colors.r, colors.g, colors.b)
-            else
-                self.TargetGlow:SetBackdropBorderColor(1, 1, 1)
-            end
-        elseif(reaction) then
-            local colors = FACTION_BAR_COLORS[reaction]
-            self.TargetGlow:SetBackdropBorderColor(colors.r, colors.g, colors.b)
-        else
-            self.TargetGlow:SetBackdropBorderColor(1, 1, 1)
-        end
-    else
-        self.TargetGlow:Hide()
-    end
-end
-
-local GroupMediaUpdate = function(self)
-    local token = self.___groupkey
-    local index = 1;
-    local attIndex = ("child%d"):format(index)
-    local childFrame = groupHeader:GetAttribute(attIndex)
-    local childName = childFrame:GetName()
-    local petFrame = _G[("%sPet"):format(childName)]
-    local targetFrame = _G[("%sTarget"):format(childName)]
-
-    while childFrame do
-        MOD.RefreshUnitMedia(childFrame, token)
-
-        if(petFrame) then
-            MOD.RefreshUnitMedia(petFrame, token)
-        end
-
-        if(targetFrame) then
-            MOD.RefreshUnitMedia(targetFrame, token)
-        end
-
-        index = index + 1;
-        attIndex = ("child%d"):format(index)
-        childFrame = raid:GetAttribute(attIndex)
-        childName = childFrame:GetName()
-        petFrame = _G[("%sPet"):format(childName)]
-        targetFrame = _G[("%sTarget"):format(childName)]
-    end
-end
-
-local GroupHeaderMediaUpdate = function(self)
-    for i=1,#self.groups do
-        self.groups[i]:MediaUpdate()
-    end
-end
-
-local SecureHeaderClear = function(self)
-    self:Hide()
-    self:SetAttribute("showPlayer", true)
-    self:SetAttribute("showSolo", true)
-    self:SetAttribute("showParty", true)
-    self:SetAttribute("showRaid", true)
-    self:SetAttribute("columnSpacing", nil)
-    self:SetAttribute("columnAnchorPoint", nil)
-    self:SetAttribute("sortMethod", nil)
-    self:SetAttribute("groupFilter", nil)
-    self:SetAttribute("groupingOrder", nil)
-    self:SetAttribute("maxColumns", nil)
-    self:SetAttribute("nameList", nil)
-    self:SetAttribute("point", nil)
-    self:SetAttribute("sortDir", nil)
-    self:SetAttribute("sortMethod", "NAME")
-    self:SetAttribute("startingIndex", nil)
-    self:SetAttribute("strictFiltering", nil)
-    self:SetAttribute("unitsPerColumn", nil)
-    self:SetAttribute("xOffset", nil)
-    self:SetAttribute("yOffset", nil)
-end
-
-local DetachSubFrames = function(...)
-    for i = 1, select("#", ...) do
-        local frame = select(i,...)
-        frame:ClearAllPoints()
-    end
-end
-
-local function SetForcedEnvironment(groupHeader)
-    local token = groupHeader.___groupkey
-    local settings = SV.db.SVUnit[token]
-    local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(settings)
-    local sorting = settings.showBy
-    local sortMethod = settings.sortMethod
-    local widthCalc, heightCalc, xCalc, yCalc = 0, 0, 0, 0;
-    local point, anchorPoint, columnAnchor, horizontal, vertical, isHorizontal = unpack(sortMapping[sorting]);
-    local groupCount = #groupHeader.groups
-    for i = 1, groupCount do
-        local frame = groupHeader.groups[i]
-        if frame then
-            if(settings.showBy == "UP") then
-                settings.showBy = "UP_RIGHT"
-            end
-            if(settings.showBy == "DOWN") then
-                settings.showBy = "DOWN_RIGHT"
-            end
-            if isHorizontal then
-                frame:SetAttribute("xOffset", settings.wrapXOffset * horizontal)
-                frame:SetAttribute("yOffset", 0)
-                frame:SetAttribute("columnSpacing", settings.wrapYOffset)
-            else
-                frame:SetAttribute("xOffset", 0)
-                frame:SetAttribute("yOffset", settings.wrapYOffset * vertical)
-                frame:SetAttribute("columnSpacing", settings.wrapXOffset)
-            end
-            if not frame.isForced then
-                if not frame.initialized then
-                    frame:SetAttribute("startingIndex", -4)
-                    frame:Show()
-                    frame.initialized = true
-                end
-                frame:SetAttribute("startingIndex", 1)
-            end
-            frame:ClearAllPoints()
-            frame:SetAttribute("columnAnchorPoint", columnAnchor)
-            DetachSubFrames(frame:GetChildren())
-            frame:SetAttribute("point", point)
-            if not frame.isForced then
-                frame:SetAttribute("maxColumns", 1)
-                frame:SetAttribute("unitsPerColumn", 5)
-                GroupDistributor[sortMethod](frame)
-                frame:SetAttribute("sortDir", settings.sortDir)
-                frame:SetAttribute("showPlayer", settings.showPlayer)
-            end
-            frame:SetAttribute("groupFilter", tostring(i))
-        end
-
-        if (i - 1) % settings.gRowCol == 0 then
-            if isHorizontal then
-                if frame then
-                    frame:SetPoint(anchorPoint, groupHeader, anchorPoint, 0, heightCalc * vertical)
-                end
-                heightCalc = heightCalc + UNIT_HEIGHT + settings.wrapYOffset;
-                yCalc = yCalc + 1
-            else
-                if frame then
-                    frame:SetPoint(anchorPoint, groupHeader, anchorPoint, widthCalc * horizontal, 0)
-                end
-                widthCalc = widthCalc + UNIT_WIDTH + settings.wrapXOffset;
-                xCalc = xCalc + 1
-            end
-        else
-            if isHorizontal then
-                if yCalc == 1 then
-                    if frame then
-                        frame:SetPoint(anchorPoint, groupHeader, anchorPoint, widthCalc * horizontal, 0)
-                    end
-                    widthCalc = widthCalc + (UNIT_WIDTH + settings.wrapXOffset) * 5;
-                    xCalc = xCalc + 1
-                elseif frame then
-                    frame:SetPoint(anchorPoint, groupHeader, anchorPoint, (((UNIT_WIDTH + settings.wrapXOffset) * 5) * ((i - 1) % settings.gRowCol)) * horizontal, ((UNIT_HEIGHT + settings.wrapYOffset) * (yCalc - 1)) * vertical)
-                end
-            else
-                if xCalc == 1 then
-                    if frame then
-                        frame:SetPoint(anchorPoint, groupHeader, anchorPoint, 0, heightCalc * vertical)
-                    end
-                    heightCalc = heightCalc + (UNIT_HEIGHT + settings.wrapYOffset) * 5;
-                    yCalc = yCalc + 1
-                elseif frame then
-                    frame:SetPoint(anchorPoint, groupHeader, anchorPoint, ((UNIT_WIDTH + settings.wrapXOffset) * (xCalc - 1)) * horizontal, (((UNIT_HEIGHT + settings.wrapYOffset) * 5) * ((i - 1) % settings.gRowCol)) * vertical)
-                end
-            end
-        end
-        if heightCalc == 0 then
-            heightCalc = heightCalc + (UNIT_HEIGHT + settings.wrapYOffset) * 5
-        elseif widthCalc == 0 then
-            widthCalc = widthCalc + (UNIT_WIDTH + settings.wrapXOffset) * 5
-        end
-    end
-    groupHeader:SetSize(widthCalc - settings.wrapXOffset, heightCalc - settings.wrapYOffset)
-end
-
-local function SetGroupHeader(parentFrame, filter, styleName, headerName, template1, token, template2, updateFunction)
-    local db = SV.db.SVUnit[token]
-    local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
-    local groupHeader = oUF_Villain:SpawnHeader(headerName, template2, nil,
-        "oUF-initialConfigFunction", ("self:SetWidth(%d); self:SetHeight(%d); self:SetFrameLevel(5)"):format(UNIT_WIDTH, UNIT_HEIGHT),
-        "groupFilter", filter,
-        "showParty", true,
-        "showRaid", true,
-        "showSolo", true,
-        template1 and "template", template1
-    )
-    groupHeader.___groupkey = token
-    groupHeader:SetParent(parentFrame)
-    groupHeader:Show()
-
-    groupHeader.Update = updateFunction
-    groupHeader.MediaUpdate = GroupMediaUpdate
-    groupHeader.ClearAllAttributes = SecureHeaderClear
-
-    return groupHeader
-end
---[[
-##########################################################
-PARTY FRAMES
-##########################################################
-]]--
-local PartyVisibility = function(self, event)
-    local db = SV.db.SVUnit.party
-    if(not SV.db.SVUnit or (not SV.db.SVUnit.party)) then return end
-    if ((not SV.db.SVUnit.party.enable) or self.isForced) then return end
-
-    if(event == "PLAYER_REGEN_ENABLED") then
-        self:UnregisterEvent("PLAYER_REGEN_ENABLED")
-    end
-
-    if(not InCombatLockdown()) then
-        local instance, instanceType = IsInInstance()
-        if(instance and instanceType == "raid") then
-            UnregisterStateDriver(self,"visibility")
-            self:Hide()
-        else
-            RegisterStateDriver(self, "visibility", "[@raid6, exists][nogroup] hide;show")
-        end
-    else
-        self:RegisterEvent("PLAYER_REGEN_ENABLED")
-    end
-end
-
-local UpdatePartySubUnit = function(self, key, db)
-    self.colors = oUF_Villain.colors;
-    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and 'AnyDown' or 'AnyUp')
-    MOD.RefreshUnitMedia(self, key)
-    if self.isChild then
-        local altDB = db.petsGroup;
-        if self == _G[self.originalParent:GetName()..'Target'] then
-            altDB = db.targetsGroup
-        end
-        if not self.originalParent.childList then
-            self.originalParent.childList = {}
-        end
-        self.originalParent.childList[self] = true;
-        if not InCombatLockdown()then
-            if altDB.enable then
-                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(altDB)
-                self:SetParent(self.originalParent)
-                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-                self:ClearAllPoints()
-                SV:ReversePoint(self, altDB.anchorPoint, self.originalParent, altDB.xOffset, altDB.yOffset)
-            else
-                self:SetParent(SV.Cloaked)
-            end
-        end
-        do
-            local health = self.Health;
-            health.Smooth = nil;
-            health.frequentUpdates = nil;
-            health.colorSmooth = nil;
-            health.colorHealth = nil;
-            health.colorClass = true;
-            health.colorReaction = true;
-            health:ClearAllPoints()
-            health:Point("TOPRIGHT", self, "TOPRIGHT", -1, -1)
-            health:Point("BOTTOMLEFT", self, "BOTTOMLEFT", 1, 1)
-        end
-        do
-            local nametext = self.InfoPanel.Name
-            self:Tag(nametext, altDB.tags)
-        end
-    else
-        if not InCombatLockdown() then
-            local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
-            self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-        end
-        MOD:RefreshUnitLayout(self, key)
-        MOD:UpdateAuraWatch(self, key)
-    end
-    self:EnableElement('ReadyCheck')
-    self:UpdateAllElements()
-end
-
-local PartyGroupUpdate = function(self)
-    local group = self:GetParent()
-
-    if not group.positioned then
-        group:ClearAllPoints()
-        group:Point("LEFT",SV.UIParent,"LEFT",40,0)
-        SV.Mentalo:Add(group, L['Party Frames'], nil, nil, nil, 'ALL,PARTY,ARENA');
-        group:RegisterEvent("PLAYER_ENTERING_WORLD")
-        group:RegisterEvent("ZONE_CHANGED_NEW_AREA")
-        group:SetScript("OnEvent", PartyVisibility)
-        group.positioned = true;
-    end
-
-    PartyVisibility(group)
-
-    local key = "party"
-    local db = SV.db.SVUnit[key]
-    local index = 1;
-    local childFrame = self:GetAttribute("child"..index)
-
-    while childFrame do
-        UpdatePartySubUnit(childFrame, key, db)
-        if(_G[childFrame:GetName().."Pet"]) then
-            UpdatePartySubUnit(_G[childFrame:GetName().."Pet"], key, db)
-        end
-        if(_G[childFrame:GetName().."Target"]) then
-            UpdatePartySubUnit(_G[childFrame:GetName().."Target"], key, db)
-        end
-        index = index + 1;
-        childFrame = self:GetAttribute("child"..index)
-    end
-end
-
-local PartyPrototype = function(self, unit)
-    local key = "party"
-    self.unit = unit
-    self.___key = key
-    self:SetScript("OnEnter", UnitFrame_OnEnter)
-    self:SetScript("OnLeave", UnitFrame_OnLeave)
-
-    MOD:SetActionPanel(self, key)
-    self.Health = MOD:CreateHealthBar(self, true)
-
-    if self.isChild then
-        self.originalParent = self:GetParent()
-    else
-        self.Power = MOD:CreatePowerBar(self, true)
-        self.Power.frequentUpdates = false
-        MOD:CreatePortrait(self, true)
-        self.Buffs = MOD:CreateBuffs(self, key)
-        self.Debuffs = MOD:CreateDebuffs(self, key)
-        self.AuraWatch = MOD:CreateAuraWatch(self, key)
-        self.Afflicted = MOD:CreateAfflicted(self)
-        self.ResurrectIcon = MOD:CreateResurectionIcon(self)
-        self.LFDRole = MOD:CreateRoleIcon(self)
-        self.RaidRoleFramesAnchor = MOD:CreateRaidRoleFrames(self)
-        self.RaidIcon = MOD:CreateRaidIcon(self)
-        self.ReadyCheck = MOD:CreateReadyCheckIcon(self)
-        self.HealPrediction = MOD:CreateHealPrediction(self)
-        --self.GPS = MOD:CreateGPS(self, true)
-
-        local shadow = CreateFrame("Frame", nil, self)
-        shadow:SetFrameLevel(1)
-        shadow:SetFrameStrata(self:GetFrameStrata())
-        shadow:WrapOuter(self, 3, 3)
-        shadow:SetBackdrop({
-            edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
-            edgeSize = 3,
-            insets = {
-                left = 5,
-                right = 5,
-                top = 5,
-                bottom = 5
-            }
-        })
-        shadow:SetBackdropColor(0, 0, 0, 0)
-        shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
-        shadow:Hide()
-        self.TargetGlow = shadow
-        tinsert(self.__elements, UpdateTargetGlow)
-        self:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
-        self:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
-        self:RegisterEvent("GROUP_ROSTER_UPDATE", UpdateTargetGlow)
-    end
-
-    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
-    return self
-end
-
-local PartyHeaderUpdate = function(self)
-    if SV.db.SVUnit.party.enable ~= true then
-        UnregisterAttributeDriver(self, "state-visibility")
-        self:Hide()
-        return
-    end
-    for i=1,#self.groups do
-        self.groups[i]:Update()
-    end
-end
-
-local SetPartyHeaderState = function(self)
-    if not self.isForced then
-        local db = SV.db.SVUnit.party
-        if(db) then
-            local groupCount = #self.groups
-            for i=1, groupCount do
-                local frame = self.groups[i]
-                frame:Show()
-            end
-        end
-    end
-end
-
-function MOD:SetPartyGroup(token, forceUpdate)
-    if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
-    if(not SV.db.SVUnit.enable) then return end
-    local settings = SV.db.SVUnit.party
-    local styleName = "SVUI_Party"
-    local partyGroup, groupName
-
-    if(not self.Headers.party) then
-        oUF_Villain:RegisterStyle(styleName, PartyPrototype)
-        oUF_Villain:SetActiveStyle(styleName)
-        partyGroup = CreateFrame("Frame", styleName, SVUI_UnitFrameParent, "SecureHandlerStateTemplate")
-        partyGroup.groups = {}
-        partyGroup.___groupkey = "party";
-        partyGroup.Update = PartyHeaderUpdate
-        partyGroup.MediaUpdate = GroupHeaderMediaUpdate
-        partyGroup.SetActiveState = SetPartyHeaderState
-        partyGroup.SetConfigEnvironment = SetForcedEnvironment
-        partyGroup:Show()
-
-        local groupHeader = SetGroupHeader(partyGroup, 1, styleName, "SVUI_PartyGroup1", "SVUI_UNITPET, SVUI_UNITTARGET", token, nil, PartyGroupUpdate)
-        partyGroup.groups[1] = groupHeader
-
-        self.Headers.party = partyGroup
-    else
-        partyGroup = self.Headers.party
-    end
-
-    if(SV.db.SVUnit.party.enable ~= true) then
-        UnregisterStateDriver(partyGroup, "visibility")
-        partyGroup:Hide()
-        return
-    end
-
-    partyGroup:SetActiveState()
-
-    if(forceUpdate or not partyGroup.Avatar) then
-        partyGroup:SetConfigEnvironment()
-        if(not partyGroup.isForced) then
-            RegisterStateDriver(partyGroup, "visibility", "[group:raid] show; hide")
-        end
-    else
-        partyGroup:SetConfigEnvironment()
-        partyGroup:Update()
-    end
-end
---[[
-##########################################################
-RAID FRAMES
-##########################################################
-]]--
-local function SetRaidFrame(frame)
-    frame:SetScript("OnEnter", UnitFrame_OnEnter)
-    frame:SetScript("OnLeave", UnitFrame_OnLeave)
-
-    frame.RaidDebuffs = MOD:CreateRaidDebuffs(frame)
-    frame.Afflicted = MOD:CreateAfflicted(frame)
-    frame.ResurrectIcon = MOD:CreateResurectionIcon(frame)
-    frame.LFDRole = MOD:CreateRoleIcon(frame)
-    frame.RaidRoleFramesAnchor = MOD:CreateRaidRoleFrames(frame)
-    frame.RaidIcon = MOD:CreateRaidIcon(frame)
-    frame.ReadyCheck = MOD:CreateReadyCheckIcon(frame)
-    frame.HealPrediction = MOD:CreateHealPrediction(frame)
-    frame.Range = { insideAlpha = 1, outsideAlpha = 1 }
-
-    local shadow = CreateFrame("Frame", nil, frame)
-    shadow:SetFrameLevel(1)
-    shadow:SetFrameStrata(frame:GetFrameStrata())
-    shadow:WrapOuter(frame, 3, 3)
-    shadow:SetBackdrop({
-        edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
-        edgeSize = 3,
-        insets = {
-            left = 5,
-            right = 5,
-            top = 5,
-            bottom = 5
-        }
-    })
-    shadow:SetBackdropColor(0, 0, 0, 0)
-    shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
-    shadow:Hide()
-    frame.TargetGlow = shadow
-    tinsert(frame.__elements, UpdateTargetGlow)
-    frame:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
-    frame:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
-
-    return frame
-end
-
-local function UpdateRaidSubUnit(subUnit, token)
-    local db = SV.db.SVUnit[token]
-    subUnit.colors = oUF_Villain.colors;
-    subUnit:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
-    local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
-    if not InCombatLockdown() then
-        subUnit:Size(UNIT_WIDTH, UNIT_HEIGHT)
-    end
-
-    do
-        local rdBuffs = subUnit.RaidDebuffs;
-        if db.rdebuffs.enable then
-            if not subUnit:IsElementEnabled('RaidDebuffs') then
-                subUnit:EnableElement("RaidDebuffs")
-            end
-            local actualSz = numMin(db.rdebuffs.size, (UNIT_HEIGHT - 8))
-            rdBuffs:Size(actualSz)
-            rdBuffs:Point("CENTER", subUnit, "CENTER", db.rdebuffs.xOffset, db.rdebuffs.yOffset)
-            rdBuffs:Show()
-        else
-            subUnit:DisableElement("RaidDebuffs")
-            rdBuffs:Hide()
-        end
-    end
-
-    MOD.RefreshUnitMedia(subUnit, token)
-    MOD:UpdateAuraWatch(subUnit, token)
-    MOD:RefreshUnitLayout(subUnit, token)
-
-    subUnit:EnableElement("ReadyCheck")
-    subUnit:UpdateAllElements()
-end
-
-local RaidVisibility = function(groupFrame, event)
-    if(not SV.db.SVUnit or (not SV.db.SVUnit.raid)) then return end
-    if ((not SV.db.SVUnit.raid.enable) or groupFrame.isForced) then return end
-
-    if(event == "PLAYER_REGEN_ENABLED") then
-        groupFrame:UnregisterEvent("PLAYER_REGEN_ENABLED")
-    end
-
-    if not InCombatLockdown() then
-        local token = groupFrame.___groupkey
-        local db = SV.db.SVUnit[token]
-        local instance, instanceType = IsInInstance()
-        if(instance and (instanceType == "raid")) then
-            UnregisterStateDriver(groupFrame, "visibility")
-            if(GetRaidToken(token)) then
-                groupFrame:Show()
-            else
-                groupFrame:Hide()
-            end
-        elseif(db.visibility) then
-            RegisterStateDriver(groupFrame, "visibility", db.visibility)
-        end
-    else
-        groupFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
-        return
-    end
-end
-
-local RaidGroupUpdate = function(groupHeader)
-    if(not SV.db.SVUnit or (not SV.db.SVUnit.raid)) then return end
-    local groupFrame = groupHeader:GetParent()
-    local token = groupFrame.___groupkey
-
-    if not groupFrame.positioned then
-        groupFrame:ClearAllPoints()
-        groupFrame:Point("LEFT", SV.UIParent, "LEFT", 4, 0)
-        SV.Mentalo:Add(groupFrame, L["Raid Frames"])
-        groupFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
-        groupFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
-        groupFrame:SetScript("OnEvent", RaidVisibility)
-        groupFrame.positioned = true
-    end
-
-    RaidVisibility(groupFrame)
-
-    local index = 1;
-    local attIndex = ("child%d"):format(index)
-    local childFrame = groupHeader:GetAttribute(attIndex)
-    local childName = childFrame:GetName()
-    local petFrame = _G[("%sPet"):format(childName)]
-    local targetFrame = _G[("%sTarget"):format(childName)]
-
-    while childFrame do
-        UpdateRaidSubUnit(childFrame, token)
-
-        childName = childFrame:GetName()
-        petFrame = _G[("%sPet"):format(childName)]
-        targetFrame = _G[("%sTarget"):format(childName)]
-
-        if(petFrame) then
-            UpdateRaidSubUnit(petFrame, token)
-        end
-
-        if(targetFrame) then
-            UpdateRaidSubUnit(targetFrame, token)
-        end
-
-        index = index + 1;
-        attIndex = ("child%d"):format(index)
-        childFrame = groupHeader:GetAttribute(attIndex)
-    end
-end
-
-local RaidPrototype = function(token)
-    return function(self, unit)
-        self.unit = unit
-        self.___key = token
-        MOD:SetActionPanel(self, token)
-        self.Health = MOD:CreateHealthBar(self, true)
-        self.Health.frequentUpdates = false
-        self.Power = MOD:CreatePowerBar(self, true)
-        self.Power.frequentUpdates = false
-        self.Buffs = MOD:CreateBuffs(self, token)
-        self.Debuffs = MOD:CreateDebuffs(self, token)
-        self.AuraWatch = MOD:CreateAuraWatch(self, token)
-        return SetRaidFrame(self)
-    end
-end
-
-local GroupHeaderUpdate = function(self)
-    if SV.db.SVUnit.raid.enable ~= true then
-        UnregisterAttributeDriver(self, "state-visibility")
-        self:Hide()
-        return
-    end
-    for i=1,#self.groups do
-        self.groups[i]:Update()
-    end
-end
-
-local SetGroupHeaderState = function(self)
-    if not self.isForced then
-        local token = self.___groupkey
-        local db = SV.db.SVUnit[token]
-        if(db) then
-            for i=1,#self.groups do
-                local frame = self.groups[i]
-                if(i <= db.groupCount) then
-                    frame:Show()
-                else
-                    if frame.forceShow then
-                        frame:Hide()
-                        MOD:RestrictChildren(frame, frame:GetChildren())
-                        frame:SetAttribute('startingIndex',1)
-                    else
-                        frame:ClearAllAttributes()
-                    end
-                end
-            end
-        end
-    end
-end
-
-function MOD:SetRaidGroup(token, forceUpdate)
-    if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
-    if(not SV.db.SVUnit.enable) then return end
-    local db = SV.db.SVUnit[token]
-    local realName = token:gsub("(.)", upper, 1)
-    local styleName = "SVUI_"..realName
-    local raidGroup, groupName
-
-    if(not self.Headers[token]) then
-        oUF_Villain:RegisterStyle(styleName, RaidPrototype(token))
-        oUF_Villain:SetActiveStyle(styleName)
-        raidGroup = CreateFrame("Frame", styleName, SVUI_UnitFrameParent, "SecureHandlerStateTemplate")
-        raidGroup.groups = {}
-        raidGroup.___groupkey = token;
-        raidGroup.Update = GroupHeaderUpdate
-        raidGroup.MediaUpdate = GroupHeaderMediaUpdate
-        raidGroup.SetActiveState = SetGroupHeaderState
-        raidGroup.SetConfigEnvironment = SetForcedEnvironment
-        raidGroup:Show()
-
-        self.Headers[token] = raidGroup
-    else
-        raidGroup = self.Headers[token]
-    end
-
-    if(SV.db.SVUnit.raid.enable ~= true) then
-        UnregisterStateDriver(raidGroup, "visibility")
-        raidGroup:Hide()
-        return
-    end
-
-    for i = 1, db.groupCount do
-        if(not raidGroup.groups[i]) then
-            groupName = styleName .. "Group" .. i
-            raidGroup.groups[i] = SetGroupHeader(raidGroup, i, styleName, groupName, nil, token, nil, RaidGroupUpdate)
-        end
-    end
-
-    raidGroup:SetActiveState()
-
-    if(forceUpdate or not raidGroup.Avatar) then
-        raidGroup:SetConfigEnvironment()
-        if(not raidGroup.isForced) then
-            RegisterStateDriver(raidGroup, "visibility", db.visibility)
-        end
-    else
-        raidGroup:SetConfigEnvironment()
-        raidGroup:Update()
-    end
-end
---[[
-##########################################################
-RAID PETS
-##########################################################
-]]--
-local RaidPetVisibility = function(self, event)
-    local db = SV.db.SVUnit["raidpet"]
-    if (not db or (db and not db.enable) or self.isForced) then return end
-    local inInstance, instanceType = IsInInstance()
-    if event == "PLAYER_REGEN_ENABLED" then self:UnregisterEvent("PLAYER_REGEN_ENABLED") end
-
-    if not InCombatLockdown() then
-        if inInstance and instanceType == "raid" then
-            UnregisterStateDriver(self, "visibility")
-            self:Show()
-        else
-            RegisterStateDriver(self, "visibility", "[group:raid] show; hide")
-        end
-    else
-        self:RegisterEvent("PLAYER_REGEN_ENABLED")
-        return
-    end
-end
-
-local RaidPetUpdate = function(self)
-    local raidPets = self:GetParent()
-    if not raidPets.positioned then
-        raidPets:ClearAllPoints()
-        raidPets:Point("BOTTOMLEFT", SV.UIParent, "BOTTOMLEFT", 4, 433)
-        SV.Mentalo:Add(raidPets, L["Raid Pet Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
-        raidPets:RegisterEvent("PLAYER_ENTERING_WORLD")
-        raidPets:RegisterEvent("ZONE_CHANGED_NEW_AREA")
-        raidPets:SetScript("OnEvent", RaidPetVisibility)
-        raidPets.positioned = true;
-    end
-    RaidPetVisibility(raidPets)
-    local key = "raidpet"
-    local db = SV.db.SVUnit[key]
-    local index = 1;
-    local childFrame = self:GetAttribute("child"..index)
-    while childFrame do
-        UpdateRaidSubUnit(childFrame, key, db)
-        if(_G[childFrame:GetName().."Pet"]) then
-            UpdateRaidSubUnit(_G[childFrame:GetName().."Pet"], key, db)
-        end
-        if(_G[childFrame:GetName().."Target"]) then
-            UpdateRaidSubUnit(_G[childFrame:GetName().."Target"], key, db)
-        end
-        index = index + 1;
-        childFrame = self:GetAttribute("child"..index)
-    end
-end
-
-local RaidPetPrototype = function(self, unit)
-    local key = "raidpet"
-    self.unit = unit
-    self.___key = key
-    self:SetScript("OnEnter", UnitFrame_OnEnter)
-    self:SetScript("OnLeave", UnitFrame_OnLeave)
-    MOD:SetActionPanel(self, key)
-    self.Health = MOD:CreateHealthBar(self, true)
-    self.Debuffs = MOD:CreateDebuffs(self, key)
-    self.AuraWatch = MOD:CreateAuraWatch(self, key)
-    self.RaidDebuffs = MOD:CreateRaidDebuffs(self)
-    self.Afflicted = MOD:CreateAfflicted(self)
-    self.RaidIcon = MOD:CreateRaidIcon(self)
-    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
-
-    local shadow = CreateFrame("Frame", nil, self)
-    shadow:SetFrameLevel(1)
-    shadow:SetFrameStrata(self:GetFrameStrata())
-    shadow:WrapOuter(self, 3, 3)
-    shadow:SetBackdrop({
-        edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
-        edgeSize = 3,
-        insets = {
-            left = 5,
-            right = 5,
-            top = 5,
-            bottom = 5
-        }
-    })
-    shadow:SetBackdropColor(0, 0, 0, 0)
-    shadow:SetBackdropBorderColor(0, 0, 0, 0.9)
-    shadow:Hide()
-    self.TargetGlow = shadow
-    tinsert(self.__elements, UpdateTargetGlow)
-
-    self:RegisterEvent("PLAYER_TARGET_CHANGED", UpdateTargetGlow)
-    self:RegisterEvent("PLAYER_ENTERING_WORLD", UpdateTargetGlow)
-    return self
-end
-
-local PetHeaderUpdate = function(self)
-    if SV.db.SVUnit.raidpet.enable ~= true then
-        UnregisterAttributeDriver(self, "state-visibility")
-        self:Hide()
-        return
-    end
-    for i=1,#self.groups do
-        self.groups[i]:Update()
-    end
-end
-
-local SetPetHeaderState = function(self)
-    if not self.isForced then
-        local db = SV.db.SVUnit.raidpet
-        if(db) then
-            local groupCount = #self.groups
-            for i=1, groupCount do
-                local frame = self.groups[i]
-                frame:Show()
-            end
-        end
-    end
-end
-
-function MOD:SetRaidPetGroup(token, forceUpdate)
-    if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
-    if(not SV.db.SVUnit.enable) then return end
-    local settings = SV.db.SVUnit.raidpet
-    local styleName = "SVUI_RaidPets"
-    local petGroup, groupName
-
-    if(not self.Headers.raidpet) then
-        oUF_Villain:RegisterStyle(styleName, RaidPetPrototype)
-        oUF_Villain:SetActiveStyle(styleName)
-        petGroup = CreateFrame("Frame", styleName, SVUI_UnitFrameParent, "SecureHandlerStateTemplate")
-        petGroup.groups = {}
-        petGroup.___groupkey = "raidpet";
-        petGroup.Update = PetHeaderUpdate
-        petGroup.MediaUpdate = GroupHeaderMediaUpdate
-        petGroup.SetActiveState = SetPetHeaderState
-        petGroup.SetConfigEnvironment = SetForcedEnvironment
-        petGroup:Show()
-        for i = 1, 2 do
-            if(not petGroup.groups[i]) then
-                groupName = "SVUI_RaidPetsGroup" .. i
-                local groupHeader = SetGroupHeader(petGroup, i, styleName, groupName, "SVUI_UNITPET", "raidpet", "SecureGroupPetHeaderTemplate", RaidPetUpdate)
-                petGroup.groups[i] = groupHeader
-            end
-        end
-
-        self.Headers.raidpet = petGroup
-    else
-        petGroup = self.Headers.raidpet
-    end
-
-    petGroup:SetActiveState()
-
-    if(forceUpdate or not petGroup.Avatar) then
-        petGroup:SetConfigEnvironment()
-        if(not petGroup.isForced) then
-            RegisterStateDriver(petGroup, "visibility", "[group:raid] show; hide")
-        end
-    else
-        petGroup:SetConfigEnvironment()
-        petGroup:Update()
-    end
-
-    if(settings.enable ~= true) then
-        UnregisterStateDriver(petGroup, "visibility")
-        petGroup:Hide()
-        return
-    end
-end
---[[
-##########################################################
-TANK
-##########################################################
-]]--
-local UpdateTankSubUnit = function(self, key, db)
-    self.colors = oUF_Villain.colors;
-    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
-    MOD.RefreshUnitMedia(self, key)
-    if self.isChild and self.originalParent then
-        local targets = db.targetsGroup;
-        if not self.originalParent.childList then
-            self.originalParent.childList = {}
-        end
-        self.originalParent.childList[self] = true;
-        if not InCombatLockdown()then
-            if targets.enable then
-                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(targets)
-                self:SetParent(self.originalParent)
-                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-                self:ClearAllPoints()
-                SV:ReversePoint(self, targets.anchorPoint, self.originalParent, targets.xOffset, targets.yOffset)
-            else
-                self:SetParent(SV.Cloaked)
-            end
-        end
-    elseif not InCombatLockdown() then
-        local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
-        self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-    end
-    MOD:RefreshUnitLayout(self, key)
-    do
-        local nametext = self.InfoPanel.Name;
-        if oUF_Villain.colors.healthclass then
-            self:Tag(nametext, "[name:10]")
-        else
-            self:Tag(nametext, "[name:color][name:10]")
-        end
-    end
-    self:UpdateAllElements()
-end
-
-local UpdateTankFrame = function(self)
-    local key = "tank"
-    local db = SV.db.SVUnit[key]
-    if db.enable ~= true then
-        UnregisterAttributeDriver(self, "state-visibility")
-        self:Hide()
-        return
-    end
-    self:Hide()
-    DetachSubFrames(self:GetChildren())
-    self:SetAttribute("startingIndex", -1)
-    RegisterAttributeDriver(self, "state-visibility", "show")
-    self.dirtyWidth, self.dirtyHeight = self:GetSize()
-    RegisterAttributeDriver(self, "state-visibility", "[@raid1, exists] show;hide")
-    self:SetAttribute("startingIndex", 1)
-    self:SetAttribute("point", "BOTTOM")
-    self:SetAttribute("columnAnchorPoint", "LEFT")
-    DetachSubFrames(self:GetChildren())
-    self:SetAttribute("yOffset", 7)
-    if not self.positioned then
-        self:ClearAllPoints()
-        self:Point("TOPLEFT", SV.UIParent, "TOPLEFT", 4, -40)
-        SV.Mentalo:Add(self, L["Tank Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
-        self.Avatar.positionOverride = "TOPLEFT"
-        self:SetAttribute("minHeight", self.dirtyHeight)
-        self:SetAttribute("minWidth", self.dirtyWidth)
-        self.positioned = true
-    end
-    for i = 1, self:GetNumChildren() do
-        local childFrame = select(i, self:GetChildren())
-        UpdateTankSubUnit(childFrame, key, db)
-        if(_G[childFrame:GetName().."Pet"]) then
-            UpdateTankSubUnit(_G[childFrame:GetName().."Pet"], key, db)
-        end
-        if(_G[childFrame:GetName().."Target"]) then
-            UpdateTankSubUnit(_G[childFrame:GetName().."Target"], key, db)
-        end
-    end
-end
-
-local TankPrototype = function(self, unit)
-    local key = "tank"
-    local db = SV.db.SVUnit[key]
-    self.unit = unit
-    self.___key = key
-    self:SetScript("OnEnter", UnitFrame_OnEnter)
-    self:SetScript("OnLeave", UnitFrame_OnLeave)
-    MOD:SetActionPanel(self, key)
-    self.Health = MOD:CreateHealthBar(self, true)
-    self.RaidIcon = MOD:CreateRaidIcon(self)
-    self.RaidIcon:SetPoint("BOTTOMRIGHT")
-    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
-    UpdateTankSubUnit(self, key, db)
-    self.originalParent = self:GetParent()
-    return self
-end
---[[
-##########################################################
-ASSIST
-##########################################################
-]]--
-local UpdateAssistSubUnit = function(self, key, db)
-    self.colors = oUF_Villain.colors;
-    self:RegisterForClicks(SV.db.SVUnit.fastClickTarget and "AnyDown" or "AnyUp")
-    MOD.RefreshUnitMedia(self, key)
-    if self.isChild and self.originalParent then
-        local targets = db.targetsGroup;
-        if not self.originalParent.childList then
-            self.originalParent.childList = {}
-        end
-        self.originalParent.childList[self] = true;
-        if not InCombatLockdown()then
-            if targets.enable then
-                local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(targets)
-                self:SetParent(self.originalParent)
-                self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-                self:ClearAllPoints()
-                SV:ReversePoint(self, targets.anchorPoint, self.originalParent, targets.xOffset, targets.yOffset)
-            else
-                self:SetParent(SV.Cloaked)
-            end
-        end
-    elseif not InCombatLockdown() then
-        local UNIT_WIDTH, UNIT_HEIGHT = MOD:GetActiveSize(db)
-        self:Size(UNIT_WIDTH, UNIT_HEIGHT)
-    end
-
-    MOD:RefreshUnitLayout(self, key)
-
-    do
-        local nametext = self.InfoPanel.Name;
-        if oUF_Villain.colors.healthclass then
-            self:Tag(nametext, "[name:10]")
-        else
-            self:Tag(nametext, "[name:color][name:10]")
-        end
-    end
-    self:UpdateAllElements()
-end
-
-local UpdateAssistFrame = function(self)
-    local key = "assist"
-    local db = SV.db.SVUnit[key]
-    self:Hide()
-    DetachSubFrames(self:GetChildren())
-    self:SetAttribute("startingIndex", -1)
-    RegisterAttributeDriver(self, "state-visibility", "show")
-    self.dirtyWidth, self.dirtyHeight = self:GetSize()
-    RegisterAttributeDriver(self, "state-visibility", "[@raid1, exists] show;hide")
-    self:SetAttribute("startingIndex", 1)
-    self:SetAttribute("point", "BOTTOM")
-    self:SetAttribute("columnAnchorPoint", "LEFT")
-    DetachSubFrames(self:GetChildren())
-    self:SetAttribute("yOffset", 7)
-    if not self.positioned then
-        self:ClearAllPoints()
-        self:Point("TOPLEFT", SV.UIParent, "TOPLEFT", 4, -140)
-        SV.Mentalo:Add(self, L["Assist Frames"], nil, nil, nil, "ALL, RAID10, RAID25, RAID40")
-        self.Avatar.positionOverride = "TOPLEFT"
-        self:SetAttribute("minHeight", self.dirtyHeight)
-        self:SetAttribute("minWidth", self.dirtyWidth)
-        self.positioned = true
-    end
-    for i = 1, self:GetNumChildren() do
-        local childFrame = select(i, self:GetChildren())
-        UpdateAssistSubUnit(childFrame, key, db)
-        if(_G[childFrame:GetName().."Pet"]) then
-            UpdateAssistSubUnit(_G[childFrame:GetName().."Pet"], key, db)
-        end
-        if(_G[childFrame:GetName().."Target"]) then
-            UpdateAssistSubUnit(_G[childFrame:GetName().."Target"], key, db)
-        end
-    end
-end
-
-local AssistPrototype = function(self, unit)
-    local key = "assist"
-    local db = SV.db.SVUnit[key]
-    self.unit = unit
-    self.___key = key
-    self:SetScript("OnEnter", UnitFrame_OnEnter)
-    self:SetScript("OnLeave", UnitFrame_OnLeave)
-    MOD:SetActionPanel(self, key)
-    self.Health = MOD:CreateHealthBar(self, true)
-    self.RaidIcon = MOD:CreateRaidIcon(self)
-    self.RaidIcon:SetPoint("BOTTOMRIGHT")
-    self.Range = { insideAlpha = 1, outsideAlpha = 1 }
-    UpdateAssistSubUnit(self, key, db)
-    self.originalParent = self:GetParent()
-    return self
-end
-
-function MOD:SetTankAssistFrame(token, forceUpdate)
-    if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED"); return end
-    if(not SV.db.SVUnit.enable or not SV.db.SVUnit[token]) then return end
-    local db = SV.db.SVUnit[token]
-    local realName = token:gsub("(.)", upper, 1)
-    local styleName = "SVUI_"..realName
-    local groupHeader, groupName
-
-    if(not self.Headers[token]) then
-        if(token == "tank") then
-            oUF_Villain:RegisterStyle(styleName, TankPrototype)
-            oUF_Villain:SetActiveStyle(styleName)
-            groupHeader = SetGroupHeader(SVUI_UnitFrameParent, "MAINTANK", styleName, styleName, "SVUI_UNITTARGET", token, nil, UpdateTankFrame)
-        else
-            oUF_Villain:RegisterStyle(styleName, AssistPrototype)
-            oUF_Villain:SetActiveStyle(styleName)
-            groupHeader = SetGroupHeader(SVUI_UnitFrameParent, "MAINASSIST", styleName, styleName, "SVUI_UNITTARGET", token, nil, UpdateAssistFrame)
-        end
-
-        groupHeader:Show()
-        self.Headers[token] = groupHeader
-    else
-        groupHeader = self.Headers[token]
-    end
-
-    groupHeader:Update()
-end
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/setup/installer.lua b/Interface/AddOns/SVUI/setup/installer.lua
index 6566bf7..af7a5dd 100644
--- a/Interface/AddOns/SVUI/setup/installer.lua
+++ b/Interface/AddOns/SVUI/setup/installer.lua
@@ -121,7 +121,7 @@ end
 local function ShowLayout(show40)
 	if(not _G["SVUI_Raid40"] or (show40 and _G["SVUI_Raid40"].forceShow == true)) then return end
 	if(not show40 and _G["SVUI_Raid40"].forceShow ~= true) then return end
-	SV.SVUnit:UpdateGroupConfig(_G["SVUI_Raid40"], show40)
+	SV.SVUnit:ViewGroupFrames(_G["SVUI_Raid40"], show40)
 end

 local function BarShuffle()
diff --git a/Interface/AddOns/SVUI/system/_load.xml b/Interface/AddOns/SVUI/system/_load.xml
index 2cd3e19..3b1ecb4 100644
--- a/Interface/AddOns/SVUI/system/_load.xml
+++ b/Interface/AddOns/SVUI/system/_load.xml
@@ -3,7 +3,7 @@
     <Script file="configs.lua"/>
 	<Script file="media.lua"/>
     <Script file="utilities.lua"/>
-    <Script file="common.lua"/>
+    <Script file="framework.lua"/>
     <Script file="visibility.lua"/>
     <Script file="slash.lua"/>
     <Script file="alerts.lua"/>
diff --git a/Interface/AddOns/SVUI/system/animate.lua b/Interface/AddOns/SVUI/system/animate.lua
deleted file mode 100644
index d6e3252..0000000
--- a/Interface/AddOns/SVUI/system/animate.lua
+++ /dev/null
@@ -1,499 +0,0 @@
---[[
-##############################################################################
-_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
- ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
-  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
-   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
-	______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
-	 _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
-	  __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
-	   _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
-		___\///////////___________\///___________\/////////_____\///////////_#
-##############################################################################
-S U P E R - V I L L A I N - U I   By: Munglunch                              #
-##############################################################################
-##########################################################
-LOCALIZED LUA FUNCTIONS
-##########################################################
-]]--
---[[ GLOBALS ]]--
-local _G = _G;
-local unpack    = _G.unpack;
-local select    = _G.select;
---[[
-##########################################################
-GET ADDON DATA
-##########################################################
-]]--
-local SV = select(2, ...)
-local L = SV.L
---[[
-##########################################################
-LOCALS
-##########################################################
-]]--
-local FlickerAlpha = {0.2,0.15,0.1,0.15,0.2,0.15,0.1,0.15}
-local Animate = {};
---[[
-######################################################################
-  /$$$$$$  /$$   /$$ /$$$$$$ /$$      /$$  /$$$$$$  /$$$$$$$$/$$$$$$$$
- /$$__  $$| $$$ | $$|_  $$_/| $$$    /$$$ /$$__  $$|__  $$__/ $$_____/
-| $$  \ $$| $$$$| $$  | $$  | $$$$  /$$$$| $$  \ $$   | $$  | $$
-| $$$$$$$$| $$ $$ $$  | $$  | $$ $$/$$ $$| $$$$$$$$   | $$  | $$$$$
-| $$__  $$| $$  $$$$  | $$  | $$  $$$| $$| $$__  $$   | $$  | $$__/
-| $$  | $$| $$\  $$$  | $$  | $$\  $ | $$| $$  | $$   | $$  | $$
-| $$  | $$| $$ \  $$ /$$$$$$| $$ \/  | $$| $$  | $$   | $$  | $$$$$$$$
-|__/  |__/|__/  \__/|______/|__/     |__/|__/  |__/   |__/  |________/
-######################################################################
-]]--
-local Anim_OnShow = function(self)
-	if not self.anim:IsPlaying() then
-		self.anim:Play()
-	end
-end
-
-local Anim_OnHide = function(self)
-	self.anim:Finish()
-end
-
-local Anim_OnPlay = function(self)
-	local parent = self.parent
-	parent:SetAlpha(1)
-	if self.hideOnFinished and not parent:IsShown() then
-		parent:Show()
-	end
-end
-
-local Anim_OnStop = function(self)
-	local parent = self.parent
-	if self.fadeOnFinished then
-		parent:SetAlpha(0)
-	end
-	if self.hideOnFinished and parent:IsShown() then
-		parent:Hide()
-	end
-	if self.savedFrameLevel or self.startscale then
-		parent:SetScale(1)
-		if self.startscale then
-			self.startscale = 1
-		end
-		if self.savedFrameLevel then
-			parent:SetFrameLevel(self.savedFrameLevel)
-		end
-	end
-end
-
-local Anim_OnFinished = function(self)
-	local parent = self.parent
-	local looped = self:GetLooping()
-	self:Stop()
-	if(looped and looped == "REPEAT" and parent:IsShown()) then
-		self:Play()
-	end
-end
-
-local Sprite_OnUpdate = function(self)
-	local order = self:GetOrder()
-	local parent = self.parent
-	local left, right;
-	if(self.isFadeFrame) then
-		parent:SetAlpha(0)
-		return
-	end
-	left = (order - 1) * 0.25;
-	right = left + 0.25;
-	parent:SetTexCoord(left,right,0,1)
-	if parent.overlay then
-		parent.overlay:SetTexCoord(left,right,0,1)
-		parent.overlay:SetVertexColor(1,1,1,FlickerAlpha[order])
-	end
-end
-
-local SmallSprite_OnUpdate = function(self)
-	local order = self:GetOrder()
-	local parent = self.parent
-	local left, right;
-	if(self.isFadeFrame) then
-		parent:SetAlpha(0)
-		return
-	end
-	left = (order - 1) * 0.125;
-	right = left + 0.125;
-	parent:SetTexCoord(left,right,0,1)
-	if parent.overlay then
-		parent.overlay:SetTexCoord(left,right,0,1)
-		parent.overlay:SetVertexColor(1,1,1,FlickerAlpha[order])
-	end
-end
-
-local PulseIn_OnUpdate = function(self)
-	local parent = self.parent
-	local step = self:GetProgress()
-	if(parent.savedFrameLevel) then
-		parent:SetFrameLevel(128)
-	end
-	parent:SetScale(1 + (1.05 * step))
-end
-
-local PulseOut_OnUpdate = function(self)
-	local parent = self.parent
-	local step = self:GetProgress()
-	if(parent.savedFrameLevel) then
-		parent:SetFrameLevel(128)
-	end
-	parent:SetScale(1 + (1.05 * (1 - step)))
-end
-
-local Kapow_OnPlay = function(self)
-	local parent = self.parent
-	if(not parent.startscale) then
-		parent.startscale = parent:GetScale()
-	end
-	parent:SetAlpha(1)
-	parent:SetScale(parent.startscale or 1)
-end
-
-local Kapow_OnFinished = function(self)
-	self.parent:SetAlpha(0)
-end
-
-local Kapow_OnUpdate = function(self)
-	local parent = self.parent
-	local step = self:GetProgress()
-	local scale = 1
-	if(parent.startscale) then
-		scale = scale * parent.startscale
-	end
-	parent:SetScale(scale + (1.05 * step))
-end
-
-local Kapow_OnUpdate2 = function(self)
-	local parent = self.parent
-	_G.UIFrameFadeOut(parent, 0.3, 1, 0)
-end
-
-local Slide_OnUpdate = function(self)
-	local parent = self.parent
-	local step = self:GetProgress()
-	parent:SetScale(1 + (1.05 * step))
-end
-
-local Slide_OnPlay = function(self)
-	local parent = self.parent
-	parent:SetScale(0.01)
-	parent:SetAlpha(1)
-end
-
-local Slide_FadeStart = function(self)
-	local parent = self.parent
-	_G.UIFrameFadeOut(parent, 0.3, 1, 0)
-end
-
-local Slide_FadeStop = function(self)
-	self.parent:SetAlpha(0)
-end
-
---[[ HELPER FUNCTION ]]--
-
-local function SetNewAnimation(frame, animType, subType)
-	local anim = frame:CreateAnimation(animType, subType)
-	anim.parent = frame.parent
-	return anim
-end
-
---[[ ANIMATION CLASS METHODS ]]--
-
-function Animate:SetTemplate(frame, animType, hideOnFinished, speed, special, scriptToParent)
-	if not animType then return end
-
-	frame.anim = frame:CreateAnimationGroup(animType)
-	frame.anim.parent = frame;
-	frame.anim.hideOnFinished = hideOnFinished
-	if animType ~= 'Flash' and animType ~= 'Kapow' then
-		frame.anim:SetScript("OnPlay", Anim_OnPlay)
-		frame.anim:SetScript("OnFinished", Anim_OnFinished)
-		frame.anim:SetScript("OnStop", Anim_OnStop)
-	end
-
-	if scriptToParent then
-		local frameParent = frame:GetParent();
-		if(frameParent.SetScript) then
-			frameParent.anim = frame.anim;
-			frameParent:SetScript("OnShow", Anim_OnShow)
-			frameParent:SetScript("OnHide", Anim_OnHide)
-		end
-	elseif(frame.SetScript) then
-		frame:SetScript("OnShow", Anim_OnShow)
-		frame:SetScript("OnHide", Anim_OnHide)
-	end
-
-	if animType == 'Flash'then
-		frame.anim.fadeOnFinished = true
-		if not speed then speed = 0.33 end
-
-		frame.anim[1] = SetNewAnimation(frame.anim, "Alpha", "FadeIn")
-		frame.anim[1]:SetChange(1)
-		frame.anim[1]:SetOrder(2)
-		frame.anim[1]:SetDuration(speed)
-
-		frame.anim[2] = SetNewAnimation(frame.anim, "Alpha", "FadeOut")
-		frame.anim[2]:SetChange(-1)
-		frame.anim[2]:SetOrder(1)
-		frame.anim[2]:SetDuration(speed)
-
-		if special then
-			frame.anim:SetLooping("REPEAT")
-		end
-	elseif animType == 'Orbit' then
-		frame.anim[1] = SetNewAnimation(frame.anim, "Rotation")
-		if special then
-			frame.anim[1]:SetDegrees(-360)
-		else
-			frame.anim[1]:SetDegrees(360)
-		end
-		frame.anim[1]:SetDuration(speed)
-		frame.anim:SetLooping("REPEAT")
-		frame.anim:Play()
-	elseif animType == 'Sprite' then
-		frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[1]:SetOrder(1)
-		frame.anim[1]:SetDuration(speed)
-		frame.anim[1]:SetScript("OnUpdate", Sprite_OnUpdate)
-
-		frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[2]:SetOrder(2)
-		frame.anim[2]:SetDuration(speed)
-		frame.anim[2]:SetScript("OnUpdate", Sprite_OnUpdate)
-
-		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[3]:SetOrder(3)
-		frame.anim[3]:SetDuration(speed)
-		frame.anim[3]:SetScript("OnUpdate", Sprite_OnUpdate)
-
-		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[4]:SetOrder(4)
-		frame.anim[4]:SetDuration(speed)
-		frame.anim[4]:SetScript("OnUpdate", Sprite_OnUpdate)
-
-		if special then
-			frame.anim[5] = SetNewAnimation(frame.anim, "Translation")
-			frame.anim[5]:SetOrder(5)
-			frame.anim[5]:SetDuration(special)
-			frame.anim[5].isFadeFrame = true;
-			frame.anim[5]:SetScript("OnUpdate", Sprite_OnUpdate)
-		end
-
-		frame.anim:SetLooping("REPEAT")
-	elseif animType == 'SmallSprite' then
-		frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[1]:SetOrder(1)
-		frame.anim[1]:SetDuration(speed)
-		frame.anim[1]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[2]:SetOrder(2)
-		frame.anim[2]:SetDuration(speed)
-		frame.anim[2]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[3]:SetOrder(3)
-		frame.anim[3]:SetDuration(speed)
-		frame.anim[3]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[4]:SetOrder(4)
-		frame.anim[4]:SetDuration(speed)
-		frame.anim[4]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[5] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[5]:SetOrder(5)
-		frame.anim[5]:SetDuration(speed)
-		frame.anim[5]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[6] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[6]:SetOrder(6)
-		frame.anim[6]:SetDuration(speed)
-		frame.anim[6]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[7] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[7]:SetOrder(7)
-		frame.anim[7]:SetDuration(speed)
-		frame.anim[7]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		frame.anim[8] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[8]:SetOrder(8)
-		frame.anim[8]:SetDuration(speed)
-		frame.anim[8]:SetScript("OnUpdate", SmallSprite_OnUpdate)
-
-		if special then
-			frame.anim[9] = SetNewAnimation(frame.anim, "Translation")
-			frame.anim[9]:SetOrder(9)
-			frame.anim[9]:SetDuration(special)
-			frame.anim[9].isFadeFrame = true;
-			frame.anim[9]:SetScript("OnUpdate", Sprite_OnUpdate)
-		end
-
-		frame.anim:SetLooping("REPEAT")
-	elseif animType == 'Pulse' then
-		frame.anim.savedFrameLevel = frame:GetFrameLevel()
-
-		frame.anim[1] = SetNewAnimation(frame.anim)
-		frame.anim[1]:SetDuration(0.2)
-		frame.anim[1]:SetEndDelay(0.1)
-		frame.anim[1]:SetOrder(1)
-		frame.anim[1]:SetScript("OnUpdate", PulseIn_OnUpdate)
-
-		frame.anim[2] = SetNewAnimation(frame.anim)
-		frame.anim[2]:SetDuration(0.6)
-		frame.anim[2]:SetOrder(2)
-		frame.anim[2]:SetScript("OnUpdate", PulseOut_OnUpdate)
-	elseif animType == 'Kapow' then
-		frame.anim:SetScript("OnPlay", Kapow_OnPlay)
-
-		frame.anim.startscale = frame:GetScale()
-
-		frame.anim[1] = SetNewAnimation(frame.anim, "Rotation")
-		frame.anim[1]:SetDuration(0.2)
-		frame.anim[1]:SetOrder(1)
-		frame.anim[1]:SetDegrees(360)
-		frame.anim[1]:SetScript("OnUpdate", Kapow_OnUpdate)
-
-		frame.anim[2] = SetNewAnimation(frame.anim)
-		frame.anim[2]:SetDuration(0.3)
-		frame.anim[2]:SetOrder(2)
-		frame.anim[2]:SetScript("OnUpdate", Kapow_OnUpdate2)
-	end
-end
-
---[[ ROTATE AND WOBBLE (kinda like twerking i guess...) ]]--
-
-function Animate:Orbit(frame, speed, reversed, hideOnFinished)
-	if not frame then return end
-	if not speed then speed = 1 end
-	self:SetTemplate(frame, 'Orbit', hideOnFinished, speed, reversed)
-end
-
-function Animate:Pulse(frame, hideOnFinished)
-	if not frame then return end
-	self:SetTemplate(frame, 'Pulse', hideOnFinished)
-end
-
-function Animate:Kapow(frame, hideOnFinished)
-	if not frame then return end
-	self:SetTemplate(frame, 'Kapow', hideOnFinished)
-end
-
---[[ ANIMATED SPRITES ]]--
-
-function Animate:Sprite(frame, speed, fadeTime, scriptToParent)
-	if not frame then return end
-	speed = speed or 0.08;
-	self:SetTemplate(frame, 'Sprite', false, speed, fadeTime, scriptToParent)
-end
-
-function Animate:SmallSprite(frame, speed, fadeTime, scriptToParent)
-	if not frame then return end
-	speed = speed or 0.08;
-	self:SetTemplate(frame, 'SmallSprite', false, speed, fadeTime, scriptToParent)
-end
-
-function Animate:StopSprite(frame)
-	if not frame then return end
-	frame.anim:Finish()
-end
-
---[[ FLASHING ]]--
-
-function Animate:Flash(frame, speed, looped)
-	if not frame.anim then
-		self:SetTemplate(frame, 'Flash', false, speed, looped)
-	end
-	if not frame.anim:IsPlaying() then
-		frame.anim:Play()
-	end
-end
-
-function Animate:StopFlash(frame)
-	if not frame.anim then return end
-	frame.anim:Finish()
-	frame.anim:Stop()
-end
-
---[[ SLIDING ]]--
-
-function Animate:Slide(frame, xDirection, yDirection, bounce, extendedTime)
-	if(not frame or (frame and frame.anim)) then return end
-
-	frame.anim = frame:CreateAnimationGroup("Slide")
-	frame.anim.hideOnFinished = true;
-	frame.anim.parent = frame;
-	frame.anim:SetScript("OnPlay", Anim_OnPlay)
-	frame.anim:SetScript("OnFinished", Anim_OnFinished)
-	frame.anim:SetScript("OnStop", Anim_OnStop)
-
-	frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
-	frame.anim[1]:SetDuration(0)
-	frame.anim[1]:SetOrder(1)
-
-	frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
-	frame.anim[2]:SetDuration(0.3)
-	frame.anim[2]:SetOrder(2)
-	frame.anim[2]:SetSmoothing("OUT")
-
-	if bounce then
-		frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[3]:SetDuration(extendedTime or 0.5)
-		frame.anim[3]:SetOrder(3)
-
-		frame.anim[4] = SetNewAnimation(frame.anim, "Translation")
-		frame.anim[4]:SetDuration(0.3)
-		frame.anim[4]:SetOrder(4)
-		frame.anim[4]:SetSmoothing("IN")
-		frame.anim[4]:SetOffset(xDirection, yDirection)
-	end
-end
-
-function Animate:RandomSlide(frame, raised)
-	if not frame then return end
-	if raised then
-		frame:SetFrameLevel(30)
-	else
-		frame:SetFrameLevel(20)
-	end
-	frame:SetPoint("CENTER", SV.UIParent, "CENTER", 0, -150)
-
-	frame.anim = frame:CreateAnimationGroup("RandomSlide")
-	frame.anim.parent = frame;
-	frame.anim[1] = SetNewAnimation(frame.anim, "Translation")
-	frame.anim[1]:SetOrder(1)
-	frame.anim[1]:SetDuration(0.1)
-	frame.anim[1]:SetScript("OnUpdate", Slide_OnUpdate)
-	frame.anim[1]:SetScript("OnPlay", Slide_OnPlay)
-
-	frame.anim[2] = SetNewAnimation(frame.anim, "Translation")
-	frame.anim[2]:SetOrder(2)
-	frame.anim[2]:SetDuration(1)
-
-	frame.anim[3] = SetNewAnimation(frame.anim, "Translation")
-	frame.anim[3]:SetOrder(3)
-	frame.anim[3]:SetDuration(0.3)
-	frame.anim[3]:SetSmoothing("OUT")
-	frame.anim[3]:SetScript("OnPlay", Slide_FadeStart)
-	frame.anim[3]:SetScript("OnStop", Slide_FadeStop)
-
-	frame.anim:SetScript("OnFinished", Slide_FadeStop)
-end
-
-function Animate:SlideIn(frame)
-	if not frame.anim then return end
-	frame:Show()
-	frame.anim:Play()
-end
-
-function Animate:SlideOut(frame)
-	if not frame.anim then return end
-	frame.anim:Finish()
-	frame.anim:Stop()
-end
-
-SV.Animate = Animate;
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/system/common.lua b/Interface/AddOns/SVUI/system/common.lua
deleted file mode 100644
index 34e7219..0000000
--- a/Interface/AddOns/SVUI/system/common.lua
+++ /dev/null
@@ -1,1242 +0,0 @@
---[[
-##############################################################################
-_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
- ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
-  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
-   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
-    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
-     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
-      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
-       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
-        ___\///////////___________\///___________\/////////_____\///////////_#
-##############################################################################
-S U P E R - V I L L A I N - U I   By: Munglunch                              #
-##############################################################################
-##########################################################
-LOCALIZED LUA FUNCTIONS
-##########################################################
-]]--
---[[ GLOBALS ]]--
-local _G = _G;
-local unpack    = _G.unpack;
-local select    = _G.select;
-local pairs     = _G.pairs;
-local ipairs    = _G.ipairs;
-local type      = _G.type;
-local error     = _G.error;
-local pcall     = _G.pcall;
-local tostring  = _G.tostring;
-local tonumber  = _G.tonumber;
-local table     = _G.table;
-local string     = _G.string;
-local math      = _G.math;
---[[ MATH METHODS ]]--
-local floor, abs, min, max = math.floor, math.abs, math.min, math.max;
-local parsefloat = math.parsefloat;
---[[ STRING METHODS ]]--
-local lower = string.lower;
---[[ TABLE METHODS ]]--
-local tremove, tcopy, twipe, tsort, tconcat, tdump = table.remove, table.copy, table.wipe, table.sort, table.concat, table.dump;
---[[
-##########################################################
-GET ADDON DATA
-##########################################################
-]]--
-local SV = select(2, ...)
-local L = SV.L
---[[
-##########################################################
-LOCAL VARS
-##########################################################
-]]--
-local SizeScaled, HeightScaled, WidthScaled, PointScaled, WrapOuter, FillInner
-local TemplateUpdateFrames = {};
-local FontUpdateFrames = {};
-local NewFrame = CreateFrame;
-local NewHook = hooksecurefunc;
-local STANDARD_TEXT_FONT = _G.STANDARD_TEXT_FONT;
-local SCREEN_MOD = 1;
-
-local function GetUsableScreen()
-    local rez = GetCVar("gxResolution")
-    local height = rez:match("%d+x(%d+)")
-    local width = rez:match("(%d+)x%d+")
-    local gxHeight = tonumber(height)
-    local gxWidth = tonumber(width)
-    local gxMod = (768 / gxHeight)
-    return gxWidth, gxHeight, gxMod
-end
---[[
-##########################################################
-UI SCALING
-##########################################################
-]]--
-function SV:UI_SCALE_CHANGED(event)
-    local scale, evalwidth
-    local gxWidth, gxHeight, gxMod = GetUsableScreen()
-
-    if(IsMacClient() and self.DisplaySettings and self.DisplaySettings.screenheight and self.DisplaySettings.screenwidth) then
-        if(gxHeight ~= self.DisplaySettings.screenheight or gxWidth ~= self.DisplaySettings.screenwidth) then
-            gxHeight = self.DisplaySettings.screenheight;
-            gxWidth = self.DisplaySettings.screenwidth
-        end
-    end
-
-    if self.db.general.autoScale then
-        scale = max(0.64, min(1.15, gxMod))
-    else
-        scale = max(0.64, min(1.15, GetCVar("uiScale") or UIParent:GetScale() or gxMod))
-    end
-
-    SCREEN_MOD = gxMod / scale;
-
-    self.ghettoMonitor = nil
-
-    if gxWidth < 1600 then
-        self.ghettoMonitor = true;
-    elseif gxWidth >= 3840 then
-        local width = gxWidth;
-        local height = gxHeight;
-        if(self.db.general.multiMonitor) then
-            if width >= 9840 then width = 3280; end
-            if width >= 7680 and width < 9840 then width = 2560; end
-            if width >= 5760 and width < 7680 then width = 1920; end
-            if width >= 5040 and width < 5760 then width = 1680; end
-            if width >= 4800 and width < 5760 and height == 900 then width = 1600; end
-            if width >= 4320 and width < 4800 then width = 1440; end
-            if width >= 4080 and width < 4320 then width = 1360; end
-            if width >= 3840 and width < 4080 then width = 1224; end
-            if width < 1600 then
-                self.ghettoMonitor = true;
-            end
-        else
-            if width >= 9840 then width = 9840; end
-            if width >= 7680 and width < 9840 then width = 7680; end
-            if width >= 5760 and width < 7680 then width = 5760; end
-            if width >= 5040 and width < 5760 then width = 5040; end
-            if width >= 4800 and width < 5040 then width = 4800; end
-            if width >= 4320 and width < 4800 then width = 4320; end
-            if width >= 4080 and width < 4320 then width = 4080; end
-            if width >= 3840 and width < 4080 then width = 3840; end
-        end
-
-        evalwidth = width;
-    end
-
-    if(parsefloat(UIParent:GetScale(),5) ~= parsefloat(scale,5) and (event == 'PLAYER_LOGIN')) then
-        SetCVar("useUiScale",1)
-        SetCVar("uiScale",scale)
-        WorldMapFrame.hasTaint = true;
-    end
-
-    if(event == 'PLAYER_LOGIN' or event == 'UI_SCALE_CHANGED') then
-        if IsMacClient() then
-            self.DisplaySettings.screenheight = floor(GetScreenHeight() * 100 + .5) / 100
-            self.DisplaySettings.screenwidth = floor(GetScreenWidth() * 100 + .5) / 100
-        end
-
-        if evalwidth then
-            local width = evalwidth
-            local height = gxHeight;
-            if not self.db.general.autoScale or height > 1200 then
-                height = UIParent:GetHeight();
-                local ratio = gxHeight / height;
-                width = evalwidth / ratio;
-            end
-            self.UIParent:SetSize(width, height);
-        else
-            self.UIParent:SetSize(UIParent:GetSize());
-        end
-
-        self.UIParent:ClearAllPoints()
-        self.UIParent:SetPoint("CENTER")
-
-        local change = abs((parsefloat(UIParent:GetScale(),5) * 100) - (parsefloat(scale,5) * 100))
-        if(event == 'UI_SCALE_CHANGED' and change > 1 and self.db.general.autoScale) then
-            self:StaticPopup_Show('FAILED_UISCALE')
-        elseif(event == 'UI_SCALE_CHANGED' and change > 1) then
-            self:StaticPopup_Show('RL_CLIENT')
-        end
-
-        self.UIParent:UnregisterEvent('PLAYER_LOGIN')
-
-        self.EffectiveScale = self.UIParent:GetEffectiveScale()
-        self.ActualHeight = self.UIParent:GetHeight()
-        self.ActualWidth = self.UIParent:GetWidth()
-    end
-end
-
-local function scaled(value)
-    if(not SCREEN_MOD) then
-        SV:UI_SCALE_CHANGED()
-    end
-    return SCREEN_MOD * floor(value / SCREEN_MOD + .5);
-end
-
-SV.Scale = scaled
---[[
-##########################################################
-APPENDED POSITIONING METHODS
-##########################################################
-]]--
-do
-    local PARAMS = {}
-
-    function SizeScaled(self, width, height)
-        if(type(width) == "number") then
-            local h = (height and type(height) == "number") and height or width
-            self:SetSize(scaled(width), scaled(h))
-        end
-    end
-
-    function WidthScaled(self, width)
-        if(type(width) == "number") then
-            self:SetWidth(scaled(width))
-        end
-    end
-
-    function HeightScaled(self, height)
-        if(type(height) == "number") then
-            self:SetHeight(scaled(height))
-        end
-    end
-
-    function PointScaled(self, ...)
-        local n = select('#', ...)
-        PARAMS = {...}
-        local arg
-        for i = 1, n do
-            arg = PARAMS[i]
-            if(arg and type(arg) == "number") then
-                PARAMS[i] = scaled(arg)
-            end
-        end
-        self:SetPoint(unpack(PARAMS))
-    end
-
-    function WrapOuter(self, parent, x, y)
-        x = type(x) == "number" and x or 1
-        y = y or x
-        local nx = scaled(x);
-        local ny = scaled(y);
-        parent = parent or self:GetParent()
-        if self:GetPoint() then
-            self:ClearAllPoints()
-        end
-        self:SetPoint("TOPLEFT", parent, "TOPLEFT", -nx, ny)
-        self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", nx, -ny)
-    end
-
-    function FillInner(self, parent, x, y)
-        x = type(x) == "number" and x or 1
-        y = y or x
-        local nx = scaled(x);
-        local ny = scaled(y);
-        parent = parent or self:GetParent()
-        if self:GetPoint() then
-            self:ClearAllPoints()
-        end
-        self:SetPoint("TOPLEFT", parent, "TOPLEFT", nx, -ny)
-        self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -nx, ny)
-    end
-end
---[[
-##########################################################
-APPENDED DESTROY METHODS
-##########################################################
-]]--
-local _purgatory = NewFrame("Frame", nil)
-_purgatory:Hide()
-
-local function Die(self)
-    if self.UnregisterAllEvents then
-        self:UnregisterAllEvents()
-        self:SetParent(_purgatory)
-    else
-        self:Hide()
-        self.Show = SV.fubar
-    end
-end
-
-local function RemoveTextures(self, option)
-    if(self.Panel) then return end
-    local region, layer, texture
-    for i = 1, self:GetNumRegions()do
-        region = select(i, self:GetRegions())
-        if(region and (region:GetObjectType() == "Texture")) then
-
-            layer = region:GetDrawLayer()
-            texture = region:GetTexture()
-
-            if(option) then
-                if(type(option) == "boolean") then
-                    if region.UnregisterAllEvents then
-                        region:UnregisterAllEvents()
-                        region:SetParent(_purgatory)
-                    else
-                        region.Show = region.Hide
-                    end
-                    region:Hide()
-                elseif(type(option) == "string" and ((layer == option) or (texture ~= option))) then
-                    region:SetTexture(0,0,0,0)
-                end
-            else
-                region:SetTexture(0,0,0,0)
-            end
-        end
-    end
-end
---[[
-##########################################################
-APPENDED FONT TEMPLATING METHODS
-##########################################################
-]]--
-local function SetFontTemplate(self, font, fontSize, fontStyle, fontJustifyH, fontJustifyV, noUpdate)
-    if not self then return end
-    local STANDARDFONTSIZE = SV.db.media.fonts and SV.db.media.fonts.size or 12
-    font = font or [[Interface\AddOns\SVUI\assets\fonts\Default.ttf]]
-    fontSize = fontSize or STANDARDFONTSIZE;
-    fontJustifyH = fontJustifyH or "CENTER";
-    fontJustifyV = fontJustifyV or "MIDDLE";
-    if not font then return end
-    self.font = font;
-    self.fontSize = fontSize;
-    self.fontStyle = fontStyle;
-    self.fontJustifyH = fontJustifyH;
-    self.fontJustifyV = fontJustifyV;
-    self:SetFont(font, fontSize, fontStyle)
-    if(fontStyle and fontStyle ~= "NONE") then
-        self:SetShadowColor(0, 0, 0, 0)
-    else
-        self:SetShadowColor(0, 0, 0, 0.2)
-    end
-    self:SetShadowOffset(1, -1)
-    self:SetJustifyH(fontJustifyH)
-    self:SetJustifyV(fontJustifyV)
-    self.useCommon = fontSize and (fontSize == STANDARDFONTSIZE);
-    if(not noUpdate) then
-        FontUpdateFrames[self] = true
-    end
-end
---[[
-##########################################################
-FONT UPDATE CALLBACK
-##########################################################
-]]--
-local function FontTemplateUpdates()
-    local STANDARDFONTSIZE = SV.db.media.fonts.size;
-    for i=1, #FontUpdateFrames do
-        local frame = FontUpdateFrames[i]
-        if frame then
-            local fontSize = frame.useCommon and STANDARDFONTSIZE or frame.fontSize
-            frame:SetFont(frame.font, fontSize, frame.fontStyle)
-        else
-            FontUpdateFrames[i] = nil
-        end
-    end
-end
-
-function SV:UpdateFontTemplates()
-    FontTemplateUpdates()
-end
-
-SV:NewCallback(FontTemplateUpdates)
---[[
-##########################################################
-XML TEMPLATE LOOKUP TABLE
-##########################################################
-]]--
-local XML_LOOKUP = {
-    ["Default"] = "SVUI_PanelTemplate_Default",
-    ["Transparent"] = "SVUI_PanelTemplate_Transparent",
-    ["Component"] = "SVUI_PanelTemplate_Component",
-    ["Headline"] = "SVUI_PanelTemplate_Headline",
-    ["Button"] = "SVUI_PanelTemplate_Button",
-    ["FramedTop"] = "SVUI_PanelTemplate_FramedTop",
-    ["FramedBottom"] = "SVUI_PanelTemplate_FramedBottom",
-    ["Bar"] = "SVUI_PanelTemplate_Bar",
-    ["Slot"] = "SVUI_PanelTemplate_Slot",
-    ["Inset"] = "SVUI_PanelTemplate_Inset",
-    ["Comic"] = "SVUI_PanelTemplate_Comic",
-    ["Model"] = "SVUI_PanelTemplate_Model",
-    ["Paper"] = "SVUI_PanelTemplate_Paper",
-    ["Container"] = "SVUI_PanelTemplate_Container",
-    ["Pattern"] = "SVUI_PanelTemplate_Pattern",
-    ["Halftone"] = "SVUI_PanelTemplate_Halftone",
-    ["Action"] = "SVUI_PanelTemplate_Action",
-    ["Blackout"] = "SVUI_PanelTemplate_Blackout",
-    ["UnitLarge"] = "SVUI_PanelTemplate_UnitLarge",
-    ["UnitSmall"] = "SVUI_PanelTemplate_UnitSmall"
-};
---[[
-##########################################################
-INTERNAL HANDLERS
-##########################################################
-]]--
-local HookPanelBorderColor = function(self,r,g,b,a)
-    if self.BorderLeft then
-        self.BorderLeft:SetVertexColor(r,g,b,a)
-        self.BorderRight:SetVertexColor(r,g,b,a)
-        self.BorderTop:SetVertexColor(r,g,b,a)
-        self.BorderBottom:SetVertexColor(r,g,b,a)
-    end
-    if self.Shadow then
-        local alpha = self.Shadow:GetAttribute("shadowAlpha") or 0.5
-        self.Shadow:SetBackdropBorderColor(r,g,b,alpha)
-    end
-end
-
-local HookBackdrop = function(self,...)
-    self.Panel:SetBackdrop(...)
-end
-
-local HookBackdropColor = function(self,...)
-    self.Panel:SetBackdropColor(...)
-end
-
-local HookBackdropBorderColor = function(self,...)
-    self.Panel:SetBackdropBorderColor(...)
-end
-
-local HookVertexColor = function(self,...)
-    self.Panel.Skin:SetVertexColor(...)
-end
-
-local HookCustomBackdrop = function(self)
-    local bgid = self.Panel:GetAttribute("panelID")
-    local newBgFile = SV.Media.bg[bgid]
-    local bd = {
-        bgFile = newBgFile,
-        edgeFile = [[Interface\BUTTONS\WHITE8X8]],
-        tile = false,
-        tileSize = 0,
-        edgeSize = 2,
-        insets =
-        {
-            left = 2,
-            right = 2,
-            top = 2,
-            bottom = 2,
-        },
-    }
-    self:SetBackdrop(bd)
-end
-
-local HookFrameLevel = function(self, level)
-    local adjustment = level - 1;
-    if(adjustment < 0) then adjustment = 0 end
-    self.Panel:SetFrameLevel(adjustment)
-end
-
-local Cooldown_ForceUpdate = function(self)
-    self.nextUpdate = 0;
-    self:Show()
-end
-
-local Cooldown_StopTimer = function(self)
-    self.enable = nil;
-    self:Hide()
-end
-
-local Cooldown_OnUpdate = function(self, elapsed)
-    if self.nextUpdate > 0 then
-        self.nextUpdate = self.nextUpdate - elapsed;
-        return
-    end
-    local expires = (self.duration - (GetTime() - self.start));
-    if expires > 0.05 then
-        if (self.fontScale * self:GetEffectiveScale() / UIParent:GetScale()) < 0.5 then
-            self.text:SetText('')
-            self.nextUpdate = 500
-        else
-            local timeLeft = 0;
-            local calc = 0;
-            if expires < 4 then
-                self.nextUpdate = 0.051
-                self.text:SetFormattedText("|cffff0000%.1f|r", expires)
-            elseif expires < 60 then
-                self.nextUpdate = 0.51
-                self.text:SetFormattedText("|cffffff00%d|r", floor(expires))
-            elseif expires < 3600 then
-                timeLeft = ceil(expires / 60);
-                calc = floor((expires / 60) + .5);
-                self.nextUpdate = calc > 1 and ((expires - calc) * 29.5) or (expires - 59.5);
-                self.text:SetFormattedText("|cffffffff%dm|r", timeLeft)
-            elseif expires < 86400 then
-                timeLeft = ceil(expires / 3600);
-                calc = floor((expires / 3600) + .5);
-                self.nextUpdate = calc > 1 and ((expires - calc) * 1799.5) or (expires - 3570);
-                self.text:SetFormattedText("|cff66ffff%dh|r", timeLeft)
-            else
-                timeLeft = ceil(expires / 86400);
-                calc = floor((expires / 86400) + .5);
-                self.nextUpdate = calc > 1 and ((expires - calc) * 43199.5) or (expires - 86400);
-                self.text:SetFormattedText("|cff6666ff%dd|r", timeLeft)
-            end
-        end
-    else
-        Cooldown_StopTimer(self)
-    end
-end
-
-local Cooldown_OnSizeChanged = function(self, width, height)
-    local frame = self.timer
-    local override = self.SizeOverride
-    local newSize = floor(width + .5) / 36;
-    override = override or frame:GetParent():GetParent().SizeOverride;
-    if override then
-        newSize = override / 20
-    end
-    if newSize == frame.fontScale then
-        return
-    end
-    frame.fontScale = newSize;
-    if newSize < 0.5 and not override then
-        frame:Hide()
-    else
-        frame:Show()
-        frame.text:SetFont([[Interface\AddOns\SVUI\assets\fonts\Numbers.ttf]], newSize * 15, 'OUTLINE')
-        if frame.enable then
-            Cooldown_ForceUpdate(frame)
-        end
-    end
-end
-
-local function CreateCooldownTimer(frame)
-    local timer = CreateFrame('Frame', nil, frame)
-    timer:Hide()
-    timer:SetAllPoints()
-    timer:SetScript('OnUpdate', Cooldown_OnUpdate)
-
-    local timeText = timer:CreateFontString(nil,'OVERLAY')
-    timeText:SetPoint('CENTER',1,1)
-    timeText:SetJustifyH("CENTER")
-    timer.text = timeText;
-
-    frame.timer = timer;
-    local width, height = frame:GetSize()
-    Cooldown_OnSizeChanged(frame, width, height)
-    frame:SetScript('OnSizeChanged', Cooldown_OnSizeChanged)
-
-    return frame.timer
-end
-
-local _hook_Cooldown_SetCooldown = function(self, start, duration, elapsed)
-    if start > 0 and duration > 2.5 then
-        local timer = self.timer or CreateCooldownTimer(self)
-        timer.start = start;
-        timer.duration = duration;
-        timer.enable = true;
-        timer.nextUpdate = 0;
-
-        if timer.fontScale >= 0.5 then
-            timer:Show()
-        end
-    else
-        local timer = self.timer;
-        if timer then
-            Cooldown_StopTimer(timer)
-        end
-    end
-    if self.timer then
-        if elapsed and elapsed > 0 then
-            self.timer:SetAlpha(0)
-        else
-            self.timer:SetAlpha(0.8)
-        end
-    end
-end
---[[
-##########################################################
-COOLDOWN HELPER
-##########################################################
-]]--
-local function CreateCooldown(frame)
-    if(SV.db.general and not SV.db.general.cooldown) then return end
-    local button = frame:GetName()
-    if(button) then
-        local cooldown = _G[button.."Cooldown"]
-        if(not cooldown or (not frame.Panel)) then return end
-        if(cooldown.HookedCooldown) then return end
-        cooldown:ClearAllPoints()
-        cooldown:FillInner(frame.Panel)
-        cooldown:SetSwipeColor(0, 0, 0, 1)
-        cooldown.HookedCooldown = true
-        cooldown:SetHideCountdownNumbers(true)
-
-        hooksecurefunc(cooldown, "SetCooldown", _hook_Cooldown_SetCooldown)
-    end
-end
---[[
-##########################################################
-TEMPLATE HELPERS
-##########################################################
-]]--
-local function CreatePanelTemplate(frame, templateName, underlay, noupdate, padding, xOffset, yOffset, defaultColor)
-    local xmlTemplate = XML_LOOKUP[templateName] or "SVUI_PanelTemplate_Default"
-    local borderColor = {0,0,0,1}
-
-    frame.Panel = NewFrame('Frame', nil, frame, xmlTemplate)
-
-    local level = frame:GetFrameLevel()
-    if(level == 0 and not InCombatLockdown()) then
-        frame:SetFrameLevel(1)
-        level = 1
-    end
-
-    local adjustment = level - 1;
-
-    if(adjustment < 0) then adjustment = 0 end
-
-    frame.Panel:SetFrameLevel(adjustment)
-
-    NewHook(frame, "SetFrameLevel", HookFrameLevel)
-
-    if(defaultColor) then
-        frame.Panel:SetAttribute("panelColor", defaultColor)
-    end
-    if(noupdate) then
-        frame.Panel:SetAttribute("panelSkipUpdate", noupdate)
-    end
-
-    local colorName     = frame.Panel:GetAttribute("panelColor")
-    local gradientName  = frame.Panel:GetAttribute("panelGradient")
-    local forcedOffset  = frame.Panel:GetAttribute("panelOffset")
-
-    xOffset = forcedOffset or xOffset or 1
-    yOffset = forcedOffset or yOffset or 1
-
-    frame.Panel:WrapOuter(frame, xOffset, yOffset)
-
-    padding = padding or frame.Panel:GetAttribute("panelPadding")
-
-    if(padding and frame.Panel.BorderLeft) then
-        frame.Panel.BorderLeft:SetWidth(padding)
-        frame.Panel.BorderRight:SetWidth(padding)
-        frame.Panel.BorderTop:SetHeight(padding)
-        frame.Panel.BorderBottom:SetHeight(padding)
-    end
-
-    if(frame.Panel.Shadow) then
-        frame.Panel.Shadow:SetPoint('TOPLEFT', frame.Panel, 'TOPLEFT', -3, 3)
-        frame.Panel.Shadow:SetPoint('BOTTOMRIGHT', frame.Panel, 'BOTTOMRIGHT', 3, -3)
-
-        local alpha = frame.Panel.Shadow:GetAttribute("shadowAlpha") or 0.5
-        frame.Panel.Shadow:SetBackdropBorderColor(0,0,0,alpha)
-
-        local level = frame.Panel.Shadow:GetFrameLevel() - 1
-        if(level >= 0) then
-            frame.Panel.Shadow:SetFrameLevel(level)
-        else
-            frame.Panel.Shadow:SetFrameLevel(0)
-        end
-    end
-
-    local bgColor = SV.Media.color[colorName] or {0.18,0.18,0.18,1}
-
-    if(not frame.Panel:GetAttribute("panelNoBackdrop")) then
-        if(underlay) then
-            frame.Panel:SetBackdropColor(bgColor[1],bgColor[2],bgColor[3],bgColor[4] or 1)
-            frame.Panel:SetBackdropBorderColor(0,0,0,1)
-        else
-            local bd = frame.Panel:GetBackdrop()
-            frame:SetBackdrop(bd)
-            frame:SetBackdropColor(bgColor[1],bgColor[2],bgColor[3],bgColor[4] or 1)
-            frame:SetBackdropBorderColor(0,0,0,1)
-
-            frame.Panel:SetBackdrop(nil)
-        end
-
-        if(templateName ~= 'Transparent') then
-            NewHook(frame.Panel, "SetBackdropBorderColor", HookPanelBorderColor)
-            NewHook(frame, "SetBackdropBorderColor", HookBackdropBorderColor)
-            if(underlay) then
-                NewHook(frame, "SetBackdrop", HookBackdrop)
-                NewHook(frame, "SetBackdropColor", HookBackdropColor)
-            end
-            frame.BackdropNeedsUpdate = true
-            if(templateName == 'Pattern' or templateName == 'Comic') then
-                frame.UpdateBackdrop = HookCustomBackdrop
-            end
-        end
-    end
-
-    if(frame.Panel.Skin) then
-        if(not underlay) then
-            frame.Panel.Skin:SetParent(frame)
-            frame.Panel.Skin:FillInner(frame, xOffset, yOffset)
-        else
-            frame.Panel.Skin:FillInner(frame.Panel, xOffset, yOffset)
-        end
-        if(gradientName and SV.Media.gradient[gradientName]) then
-            frame.Panel.Skin:SetGradient(unpack(SV.Media.gradient[gradientName]))
-        else
-            frame.Panel.Skin:SetVertexColor(bgColor[1], bgColor[2], bgColor[3], bgColor[4] or 1)
-        end
-
-        if((not frame.Panel:GetAttribute("panelSkipUpdate")) and frame.Panel:GetAttribute("panelTexUpdate")) then
-            frame.TextureNeedsUpdate = true
-            if(templateName == 'UnitLarge' or templateName == 'UnitSmall') then
-                frame.UpdateColor = HookVertexColor
-                frame.NoColorUpdate = true
-            end
-        end
-    end
-end
-
-local function CreateButtonPanel(frame, noChecked, brightChecked)
-
-    if(frame.Left) then
-        frame.Left:SetAlpha(0)
-    end
-
-    if(frame.Middle) then
-        frame.Middle:SetAlpha(0)
-    end
-
-    if(frame.Right) then
-        frame.Right:SetAlpha(0)
-    end
-
-    if(frame.SetNormalTexture) then
-        frame:SetNormalTexture("")
-    end
-
-    if(frame.SetDisabledTexture) then
-        frame:SetDisabledTexture("")
-    end
-
-    if(frame.SetCheckedTexture) then
-        frame:SetCheckedTexture("")
-    end
-
-    if(frame.SetHighlightTexture) then
-        if(not frame.hover) then
-            local hover = frame:CreateTexture(nil, "OVERLAY")
-            hover:FillInner(frame.Panel)
-            frame.hover = hover;
-        end
-        local color = SV.Media.color.highlight
-        frame.hover:SetTexture(color[1], color[2], color[3], 0.5)
-        frame:SetHighlightTexture(frame.hover)
-    end
-
-    if(frame.SetPushedTexture) then
-        if(not frame.pushed) then
-            local pushed = frame:CreateTexture(nil, "OVERLAY")
-            pushed:FillInner(frame.Panel)
-            frame.pushed = pushed;
-        end
-        frame.pushed:SetTexture(0.1, 0.8, 0.1, 0.3)
-        frame:SetPushedTexture(frame.pushed)
-    end
-
-    if(not noChecked and frame.SetCheckedTexture) then
-        if(not frame.checked) then
-            local checked = frame:CreateTexture(nil, "OVERLAY")
-            checked:FillInner(frame.Panel)
-            frame.checked = checked
-        end
-
-        if(not brightChecked) then
-            frame.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Template\DEFAULT]])
-            frame.checked:SetVertexColor(0, 0.5, 0, 0.2)
-        else
-            frame.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Bars\GLOSS]])
-            frame.checked:SetVertexColor(0, 1, 0, 1)
-        end
-
-        frame:SetCheckedTexture(frame.checked)
-    end
-
-    CreateCooldown(frame)
-end
---[[
-##########################################################
-TEMPLATE API
-##########################################################
-]]--
-local function SetBasicPanel(self, topX, topY, bottomX, bottomY, hasShadow)
-    local needsHooks = false;
-
-    if(hasShadow) then
-        if(not self.Panel) then
-            needsHooks = true
-
-            self.Panel = CreateFrame("Frame", nil, self)
-            self.Panel:SetPoint("TOPLEFT", self, "TOPLEFT", -2, 2)
-            self.Panel:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 2, -2)
-        end
-
-        self.Panel:SetBackdrop({
-            bgFile = [[Interface\BUTTONS\WHITE8X8]],
-            tile = false,
-            tileSize = 0,
-            edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
-            edgeSize = 3,
-            insets =
-            {
-                left = 0,
-                right = 0,
-                top = 0,
-                bottom = 0,
-            },
-        })
-        self.Panel:SetBackdropColor(0,0,0,0)
-        self.Panel:SetBackdropBorderColor(0,0,0)
-    else
-        if(not self.Panel) then
-            needsHooks = true
-
-            self.Panel = CreateFrame("Frame", nil, self)
-            self.Panel:SetPoint("TOPLEFT", self, "TOPLEFT", topX, topY)
-            self.Panel:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", bottomX, bottomY)
-        end
-
-        self.Panel:SetBackdrop({
-            bgFile = [[Interface\BUTTONS\WHITE8X8]],
-            tile = false,
-            tileSize = 0,
-            edgeFile = [[Interface\BUTTONS\WHITE8X8]],
-            edgeSize = 1,
-            insets =
-            {
-                left = 1,
-                right = 1,
-                top = 1,
-                bottom = 1,
-            },
-        })
-        self.Panel:SetBackdropColor(0,0,0,0.65)
-        self.Panel:SetBackdropBorderColor(0,0,0)
-    end
-
-    if(needsHooks) then
-        local level = self:GetFrameLevel()
-        if(level == 0 and not InCombatLockdown()) then
-            self:SetFrameLevel(1)
-            level = 1
-        end
-
-        local adjustment = level - 1;
-        if(adjustment < 0) then adjustment = 0 end
-
-        self.Panel:SetFrameLevel(adjustment)
-
-        NewHook(self, "SetFrameLevel", HookFrameLevel)
-        NewHook(self, "SetBackdrop", HookBackdrop)
-        NewHook(self, "SetBackdropColor", HookBackdropColor)
-        NewHook(self, "SetBackdropBorderColor", HookBackdropBorderColor)
-    end
-end
-
-local function SetPanelTemplate(self, templateName, noupdate, overridePadding, xOffset, yOffset, defaultColor)
-    if(not self or (self and self.Panel)) then return end
-    local padding = false
-    if(overridePadding and type(overridePadding) == "number") then
-        padding = overridePadding
-    end
-
-    CreatePanelTemplate(self, templateName, true, noupdate, padding, xOffset, yOffset, defaultColor)
-
-    if(not self.Panel:GetAttribute("panelSkipUpdate") and not self.__registered) then
-        TemplateUpdateFrames[self] = true
-        self.__registered = true
-    end
-end
-
-local function SetFixedPanelTemplate(self, templateName, noupdate, overridePadding, xOffset, yOffset, defaultColor)
-    if(not self or (self and self.Panel)) then return end
-    local padding = false
-    if(overridePadding and type(overridePadding) == "number") then
-        padding = overridePadding
-    end
-
-    CreatePanelTemplate(self, templateName, false, noupdate, padding, xOffset, yOffset, defaultColor)
-
-    if(not self.Panel:GetAttribute("panelSkipUpdate") and not self.__registered) then
-        TemplateUpdateFrames[self] = true
-        self.__registered = true
-    end
-end
-
-local function SetPanelColor(self, ...)
-    local arg1,arg2,arg3,arg4,arg5,arg6,arg7 = select(1, ...)
-    if(not self.Panel or not arg1) then return; end
-    if(self.Panel.Skin and self.Panel:GetAttribute("panelGradient")) then
-        if(type(arg1) == "string") then
-            if(arg1 == "VERTICAL" or arg1 == "HORIZONTAL") then
-                self.Panel.Skin:SetGradient(...)
-            elseif(SV.Media.gradient[arg1]) then
-                if self.__border then
-                    local d,r,g,b,r2,g2,b2 = unpack(SV.Media.gradient[arg1])
-                    --self.Panel.Skin:SetGradient(d,r,g,b,r2,g2,b2)
-                    self.__border[1]:SetTexture(r2,g2,b2)
-                    self.__border[2]:SetTexture(r2,g2,b2)
-                    self.__border[3]:SetTexture(r2,g2,b2)
-                    self.__border[4]:SetTexture(r2,g2,b2)
-                else
-                    self.Panel.Skin:SetGradient(unpack(SV.Media.gradient[arg1]))
-                    if(SV.Media.color[arg1]) then
-                        local t = SV.Media.color[arg1]
-                        local r,g,b,a = t[1], t[2], t[3], t[4] or 1;
-                        self:SetBackdropColor(r,g,b,a)
-                    end
-                end
-            end
-        end
-    elseif(type(arg1) == "string" and SV.Media.color[arg1]) then
-        local t = SV.Media.color[arg1]
-        local r,g,b,a = t[1], t[2], t[3], t[4] or 1;
-        if self.__border then
-            self.__border[1]:SetTexture(r,g,b)
-            self.__border[2]:SetTexture(r,g,b)
-            self.__border[3]:SetTexture(r,g,b)
-            self.__border[4]:SetTexture(r,g,b)
-        else
-            self:SetBackdropColor(r,g,b)
-        end
-    elseif(arg1 and type(arg1) == "number") then
-        self:SetBackdropColor(...)
-    end
-end
---[[
-##########################################################
-APPENDED BUTTON TEMPLATING METHODS
-##########################################################
-]]--
-local function SetButtonTemplate(self, invisible, overridePadding, xOffset, yOffset, keepNormal, defaultColor)
-    if(not self or (self and self.Panel)) then return end
-
-    local padding = 1
-    if(overridePadding and type(overridePadding) == "number") then
-        padding = overridePadding
-    end
-
-    local x,y = -1,-1
-    local underlay = false
-    if(xOffset or yOffset) then
-        x = xOffset or -1
-        y = yOffset or -1
-        underlay = true
-    end
-
-    if(invisible) then
-        CreatePanelTemplate(self, "Transparent", underlay, true, padding, x, y, defaultColor)
-        self:SetBackdropColor(0,0,0,0)
-        self:SetBackdropBorderColor(0,0,0,0)
-        if(self.Panel.BorderLeft) then
-            self.Panel.BorderLeft:SetVertexColor(0,0,0,0)
-            self.Panel.BorderRight:SetVertexColor(0,0,0,0)
-            self.Panel.BorderTop:SetVertexColor(0,0,0,0)
-            self.Panel.BorderBottom:SetVertexColor(0,0,0,0)
-        end
-    else
-        CreatePanelTemplate(self, "Button", underlay, true, padding, x, y, defaultColor)
-    end
-
-    if(self.Left) then
-        self.Left:SetAlpha(0)
-    end
-
-    if(self.Middle) then
-        self.Middle:SetAlpha(0)
-    end
-
-    if(self.Right) then
-        self.Right:SetAlpha(0)
-    end
-
-    if(self.SetNormalTexture and not keepNormal) then
-        self:SetNormalTexture("")
-    end
-
-    if(self.SetDisabledTexture) then
-        self:SetDisabledTexture("")
-    end
-
-    if(self.SetHighlightTexture) then
-        if(not self.hover) then
-            local hover = self:CreateTexture(nil, "HIGHLIGHT")
-            FillInner(hover, self.Panel)
-            self.hover = hover;
-        end
-        self.hover:SetTexture(0.1, 0.8, 0.8, 0.5)
-        self:SetHighlightTexture(self.hover)
-    end
-
-    if(self.SetPushedTexture) then
-        if(not self.pushed) then
-            local pushed = self:CreateTexture(nil, "OVERLAY")
-            FillInner(pushed, self.Panel)
-            self.pushed = pushed;
-        end
-
-        self.pushed:SetTexture(0.1, 0.8, 0.1, 0.3)
-
-        self:SetPushedTexture(self.pushed)
-    end
-
-    if(self.SetCheckedTexture) then
-        if(not self.checked) then
-            local checked = self:CreateTexture(nil, "OVERLAY")
-            FillInner(checked, self.Panel)
-            self.checked = checked;
-        end
-
-        self.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Template\DEFAULT]])
-        self.checked:SetVertexColor(0, 0.5, 0, 0.2)
-
-        self:SetCheckedTexture(self.checked)
-    end
-
-    CreateCooldown(self)
-end
-
-local function SetSlotTemplate(self, underlay, padding, x, y, shadowAlpha)
-    if(not self or (self and self.Panel)) then return end
-    padding = padding or 1
-    CreatePanelTemplate(self, "Slot", underlay, true, padding, x, y)
-    CreateButtonPanel(self, true)
-    if(shadowAlpha) then
-        self.Panel.Shadow:SetAttribute("shadowAlpha", shadowAlpha)
-    end
-end
-
-local function SetCheckboxTemplate(self, underlay, x, y)
-    if(not self or (self and self.Panel)) then return end
-
-    if(underlay) then
-        x = x or -7
-        y = y or -7
-    end
-
-    CreatePanelTemplate(self, "Slot", underlay, true, 1, x, y)
-    CreateButtonPanel(self, false, true)
-
-    NewHook(self, "SetChecked", function(self,checked)
-        local r,g,b = 0,0,0
-        if(checked == 1 or checked == true) then
-            r,g,b = self:GetCheckedTexture():GetVertexColor()
-        end
-        self:SetBackdropBorderColor(r,g,b)
-    end)
-end
-
-local function SetEditboxTemplate(self, x, y, fixed)
-    if(not self or (self and self.Panel)) then return end
-
-    if self.TopLeftTex then Die(self.TopLeftTex) end
-    if self.TopRightTex then Die(self.TopRightTex) end
-    if self.TopTex then Die(self.TopTex) end
-    if self.BottomLeftTex then Die(self.BottomLeftTex) end
-    if self.BottomRightTex then Die(self.BottomRightTex) end
-    if self.BottomTex then Die(self.BottomTex) end
-    if self.LeftTex then Die(self.LeftTex) end
-    if self.RightTex then Die(self.RightTex) end
-    if self.MiddleTex then Die(self.MiddleTex) end
-    local underlay = true
-    if(fixed ~= nil) then underlay = fixed end
-    CreatePanelTemplate(self, "Inset", underlay, true, 1, x, y)
-
-    local globalName = self:GetName();
-    if globalName then
-        if _G[globalName.."Left"] then Die(_G[globalName.."Left"]) end
-        if _G[globalName.."Middle"] then Die(_G[globalName.."Middle"]) end
-        if _G[globalName.."Right"] then Die(_G[globalName.."Right"]) end
-        if _G[globalName.."Mid"] then Die(_G[globalName.."Mid"]) end
-
-        if globalName:find("Silver") or globalName:find("Copper") or globalName:find("Gold") then
-            self.Panel:SetPoint("TOPLEFT", -3, 1)
-            if globalName:find("Silver") or globalName:find("Copper") then
-                self.Panel:SetPoint("BOTTOMRIGHT", -12, -2)
-            else
-                self.Panel:SetPoint("BOTTOMRIGHT", -2, -2)
-            end
-        end
-    end
-end
-
-local function SetFramedButtonTemplate(self, template, borderSize)
-    if(not self or (self and self.Panel)) then return end
-
-    borderSize = borderSize or 2
-
-    template = template or "FramedBottom"
-
-    CreatePanelTemplate(self, template, false, false, 0, -borderSize, -borderSize)
-
-    if(self.Left) then
-        self.Left:SetAlpha(0)
-    end
-
-    if(self.Middle) then
-        self.Middle:SetAlpha(0)
-    end
-
-    if(self.Right) then
-        self.Right:SetAlpha(0)
-    end
-
-    if(self.SetNormalTexture) then
-        self:SetNormalTexture("")
-    end
-
-    if(self.SetDisabledTexture) then
-        self:SetDisabledTexture("")
-    end
-
-    if(not self.__border) then
-        local t = SV.Media.color.default
-        local r,g,b = t[1], t[2], t[3]
-
-        local border = {}
-
-        border[1] = self:CreateTexture(nil,"BORDER")
-        border[1]:SetTexture(r,g,b)
-        border[1]:SetPoint("TOPLEFT", -1, 1)
-        border[1]:SetPoint("BOTTOMLEFT", -1, -1)
-        border[1]:SetWidth(borderSize)
-
-        local leftoutline = self:CreateTexture(nil,"BORDER")
-        leftoutline:SetTexture(0,0,0)
-        leftoutline:SetPoint("TOPLEFT", -2, 2)
-        leftoutline:SetPoint("BOTTOMLEFT", -2, -2)
-        leftoutline:SetWidth(1)
-
-        border[2] = self:CreateTexture(nil,"BORDER")
-        border[2]:SetTexture(r,g,b)
-        border[2]:SetPoint("TOPRIGHT", 1, 1)
-        border[2]:SetPoint("BOTTOMRIGHT", 1, -1)
-        border[2]:SetWidth(borderSize)
-
-        local rightoutline = self:CreateTexture(nil,"BORDER")
-        rightoutline:SetTexture(0,0,0)
-        rightoutline:SetPoint("TOPRIGHT", 2, 2)
-        rightoutline:SetPoint("BOTTOMRIGHT", 2, -2)
-        rightoutline:SetWidth(1)
-
-        border[3] = self:CreateTexture(nil,"BORDER")
-        border[3]:SetTexture(r,g,b)
-        border[3]:SetPoint("TOPLEFT", -1, 1)
-        border[3]:SetPoint("TOPRIGHT", 1, 1)
-        border[3]:SetHeight(borderSize)
-
-        local topoutline = self:CreateTexture(nil,"BORDER")
-        topoutline:SetTexture(0,0,0)
-        topoutline:SetPoint("TOPLEFT", -2, 2)
-        topoutline:SetPoint("TOPRIGHT", 2, 2)
-        topoutline:SetHeight(1)
-
-        border[4] = self:CreateTexture(nil,"BORDER")
-        border[4]:SetTexture(r,g,b)
-        border[4]:SetPoint("BOTTOMLEFT", -1, -1)
-        border[4]:SetPoint("BOTTOMRIGHT", 1, -1)
-        border[4]:SetHeight(borderSize)
-
-        local bottomoutline = self:CreateTexture(nil,"BORDER")
-        bottomoutline:SetTexture(0,0,0)
-        bottomoutline:SetPoint("BOTTOMLEFT", -2, -2)
-        bottomoutline:SetPoint("BOTTOMRIGHT", 2, -2)
-        bottomoutline:SetHeight(1)
-
-        self.__border = border
-    end
-
-    if(not self.hover) then
-        self.hover = self:CreateTexture(nil, "HIGHLIGHT")
-    end
-
-    local color = SV.Media.color.highlight
-    self.hover:SetTexture(color[1], color[2], color[3], 0.5)
-    self.hover:SetAllPoints()
-    if(self.SetHighlightTexture) then
-        self:SetHighlightTexture(self.hover)
-    end
-
-    if(not self.__registered) then
-        TemplateUpdateFrames[self] = true
-        self.__registered = true
-    end
-end
---[[
-##########################################################
-TEMPLATE UPDATE CALLBACK
-##########################################################
-]]--
-local function FrameTemplateUpdates()
-    for frame in pairs(TemplateUpdateFrames) do
-        if(frame) then
-            local panelID = frame.Panel:GetAttribute("panelID")
-            local colorID = frame.Panel:GetAttribute("panelColor")
-            local panelColor = SV.Media.color[colorID];
-            if(frame.BackdropNeedsUpdate) then
-                if(frame.UpdateBackdrop) then
-                    frame:UpdateBackdrop()
-                end
-                if(panelColor) then
-                    frame:SetBackdropColor(panelColor[1], panelColor[2], panelColor[3], panelColor[4] or 1)
-                end
-                frame:SetBackdropBorderColor(0,0,0,1)
-            end
-            if(frame.TextureNeedsUpdate and frame.Panel.Skin) then
-                local tex = SV.Media.bg[panelID]
-                if(tex) then
-                    frame.Panel.Skin:SetTexture(tex)
-                end
-                if(not frame.NoColorUpdate) then
-                    local gradient = frame.Panel:GetAttribute("panelGradient")
-                    if(gradient and SV.Media.gradient[gradient]) then
-                        local g = SV.Media.gradient[gradient]
-                        frame.Panel.Skin:SetGradient(g[1], g[2], g[3], g[4], g[5], g[6], g[7])
-                    elseif(panelColor) then
-                        frame.Panel.Skin:SetVertexColor(panelColor[1], panelColor[2], panelColor[3], panelColor[4] or 1)
-                    end
-                end
-            end
-        end
-    end
-end
-
-SV:NewCallback(FrameTemplateUpdates)
---[[
-##########################################################
-ENUMERATION
-##########################################################
-]]--
-local function AppendMethods(OBJECT)
-    local META = getmetatable(OBJECT).__index
-    if not OBJECT.Size then META.Size = SizeScaled end
-    if not OBJECT.Width then META.Width = WidthScaled end
-    if not OBJECT.Height then META.Height = HeightScaled end
-    if not OBJECT.Point then META.Point = PointScaled end
-    if not OBJECT.WrapOuter then META.WrapOuter = WrapOuter end
-    if not OBJECT.FillInner then META.FillInner = FillInner end
-    if not OBJECT.Die then META.Die = Die end
-    if not OBJECT.RemoveTextures then META.RemoveTextures = RemoveTextures end
-    if not OBJECT.SetBasicPanel then META.SetBasicPanel = SetBasicPanel end
-    if not OBJECT.SetPanelTemplate then META.SetPanelTemplate = SetPanelTemplate end
-    if not OBJECT.SetFixedPanelTemplate then META.SetFixedPanelTemplate = SetFixedPanelTemplate end
-    if not OBJECT.SetPanelColor then META.SetPanelColor = SetPanelColor end
-    if not OBJECT.SetButtonTemplate then META.SetButtonTemplate = SetButtonTemplate end
-    if not OBJECT.SetSlotTemplate then META.SetSlotTemplate = SetSlotTemplate end
-    if not OBJECT.SetCheckboxTemplate then META.SetCheckboxTemplate = SetCheckboxTemplate end
-    if not OBJECT.SetEditboxTemplate then META.SetEditboxTemplate = SetEditboxTemplate end
-    if not OBJECT.SetFramedButtonTemplate then META.SetFramedButtonTemplate = SetFramedButtonTemplate end
-    if not OBJECT.SetFontTemplate then META.SetFontTemplate = SetFontTemplate end
-end
-
-local HANDLER, OBJECT = {["Frame"] = true}, NewFrame("Frame")
-AppendMethods(OBJECT)
-AppendMethods(OBJECT:CreateTexture())
-AppendMethods(OBJECT:CreateFontString())
-
-OBJECT = EnumerateFrames()
-while OBJECT do
-    local objType = OBJECT:GetObjectType()
-    if not HANDLER[objType] then
-		AppendMethods(OBJECT)
-		HANDLER[objType] = true
-	end
-	OBJECT = EnumerateFrames(OBJECT)
-end
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/system/configs.lua b/Interface/AddOns/SVUI/system/configs.lua
index a0ca53a..edfc62a 100644
--- a/Interface/AddOns/SVUI/system/configs.lua
+++ b/Interface/AddOns/SVUI/system/configs.lua
@@ -2409,12 +2409,9 @@ SV.configs["SVUnit"] = {
 			["style"] = "3D",
 		},
 	},
-	["raid"] = {
+	["raid10"] = {
 		["enable"] = true,
 		["gridAllowed"] = true,
-		["visibility"] = "[group:raid] show; hide",
-	},
-	["raid10"] = {
 		["rangeCheck"] = true,
 		["threatEnabled"] = true,
 		["visibility"] = "[group:raid] show; hide",
@@ -2562,6 +2559,8 @@ SV.configs["SVUnit"] = {
 		},
 	},
 	["raid25"] = {
+		["enable"] = true,
+		["gridAllowed"] = true,
 		["rangeCheck"] = true,
 		["threatEnabled"] = true,
 		["visibility"] = "[group:raid] show; hide",
@@ -2708,6 +2707,8 @@ SV.configs["SVUnit"] = {
 		},
 	},
 	["raid40"] = {
+		["enable"] = true,
+		["gridAllowed"] = true,
 		["rangeCheck"] = true,
 		["threatEnabled"] = true,
 		["visibility"] = "[group:raid] show; hide",
@@ -2855,7 +2856,8 @@ SV.configs["SVUnit"] = {
 		},
 	},
 	["raidpet"] = {
-		["enable"] = false,
+		["enable"] = false,
+		["gridAllowed"] = true,
 		["rangeCheck"] = true,
 		["threatEnabled"] = true,
 		["visibility"] = "[group:raid] show; hide",
diff --git a/Interface/AddOns/SVUI/system/credits.lua b/Interface/AddOns/SVUI/system/credits.lua
index e9285d7..51781e3 100644
--- a/Interface/AddOns/SVUI/system/credits.lua
+++ b/Interface/AddOns/SVUI/system/credits.lua
@@ -28,8 +28,6 @@ local L = SV.L;
 --[[ CODING CREDITS ]]--

 local contributors = {
-	"Elv",
-	"Tukz",
 	"Azilroka",
 	"Sortokk",
 	"Kkthnx",
@@ -64,6 +62,9 @@ local donations = {
 	"Moondoggy",
 	"Necroo",
 	"Chief Pullin",
+	"lkj61",
+	"BloodEagle",
+	"Egbert",
 	"Other Silent Partners.. (Let me know if I have forgotten you)"
 };

@@ -128,7 +129,7 @@ end

 --[[ BUILD STRING ]]--

-local creditHeader = "|cffff9900SUPERVILLAIN CREDITS:|r\n|cff4f4f4f---------------------------------------------|r\n|cffff9900CREATED BY:|r  Munglunch\n|cff4f4f4f---------------------------------------------|r\n|cffff9900CODE GRANTS BY:|r  Elv, Tukz, Azilroka, Sortokk\n|cff4f4f4f---------------------------------------------|r\n";
+local creditHeader = "|cffff9900SUPERVILLAIN CREDITS:|r\n|cff4f4f4f---------------------------------------------|r\n|cffff9900CREATED BY:|r  Munglunch\n|cff4f4f4f---------------------------------------------|r\n|cffff9900CODE GRANTS BY:|r  Azilroka, Sortokk, Kkthnx\n|cff4f4f4f---------------------------------------------|r\n";

 local creditThanks1 = "|cffff9900SPECIAL THANKS TO:  |r|cfff81422Cairenn|r |cff2288cc(@WowInterface.com)|r  ..the most patient and accomodating person I know!\n\n";

diff --git a/Interface/AddOns/SVUI/system/framework.lua b/Interface/AddOns/SVUI/system/framework.lua
new file mode 100644
index 0000000..b3076d3
--- /dev/null
+++ b/Interface/AddOns/SVUI/system/framework.lua
@@ -0,0 +1,1240 @@
+--[[
+##############################################################################
+_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
+ ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
+  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
+   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
+    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
+     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
+      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
+       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
+        ___\///////////___________\///___________\/////////_____\///////////_#
+##############################################################################
+S U P E R - V I L L A I N - U I   By: Munglunch                              #
+##############################################################################
+##########################################################
+LOCALIZED LUA FUNCTIONS
+##########################################################
+]]--
+--[[ GLOBALS ]]--
+local _G = _G;
+local unpack    = _G.unpack;
+local select    = _G.select;
+local pairs     = _G.pairs;
+local ipairs    = _G.ipairs;
+local type      = _G.type;
+local error     = _G.error;
+local pcall     = _G.pcall;
+local tostring  = _G.tostring;
+local tonumber  = _G.tonumber;
+local table     = _G.table;
+local string     = _G.string;
+local math      = _G.math;
+--[[ MATH METHODS ]]--
+local floor, abs, min, max = math.floor, math.abs, math.min, math.max;
+local parsefloat, ceil = math.parsefloat, math.ceil;
+--[[ STRING METHODS ]]--
+local lower = string.lower;
+--[[ TABLE METHODS ]]--
+local tremove, tcopy, twipe, tsort, tconcat, tdump = table.remove, table.copy, table.wipe, table.sort, table.concat, table.dump;
+--[[
+##########################################################
+GET ADDON DATA
+##########################################################
+]]--
+local SV = select(2, ...)
+local L = SV.L
+--[[
+##########################################################
+LOCAL VARS
+##########################################################
+]]--
+local SizeScaled, HeightScaled, WidthScaled, PointScaled, WrapOuter, FillInner
+local TemplateUpdateFrames = {};
+local FontUpdateFrames = {};
+local NewFrame = CreateFrame;
+local NewHook = hooksecurefunc;
+local STANDARD_TEXT_FONT = _G.STANDARD_TEXT_FONT;
+local SCREEN_MOD = 1;
+
+local function GetUsableScreen()
+    local rez = GetCVar("gxResolution")
+    local height = rez:match("%d+x(%d+)")
+    local width = rez:match("(%d+)x%d+")
+    local gxHeight = tonumber(height)
+    local gxWidth = tonumber(width)
+    local gxMod = (768 / gxHeight)
+    return gxWidth, gxHeight, gxMod
+end
+--[[
+##########################################################
+UI SCALING
+##########################################################
+]]--
+function SV:UI_SCALE_CHANGED(event)
+    local scale, evalwidth
+    local gxWidth, gxHeight, gxMod = GetUsableScreen()
+
+    if(IsMacClient() and self.DisplaySettings and self.DisplaySettings.screenheight and self.DisplaySettings.screenwidth) then
+        if(gxHeight ~= self.DisplaySettings.screenheight or gxWidth ~= self.DisplaySettings.screenwidth) then
+            gxHeight = self.DisplaySettings.screenheight;
+            gxWidth = self.DisplaySettings.screenwidth
+        end
+    end
+
+    if self.db.general.autoScale then
+        scale = max(0.64, min(1.15, gxMod))
+    else
+        scale = max(0.64, min(1.15, GetCVar("uiScale") or UIParent:GetScale() or gxMod))
+    end
+
+    SCREEN_MOD = gxMod / scale;
+
+    self.ghettoMonitor = nil
+
+    if gxWidth < 1600 then
+        self.ghettoMonitor = true;
+    elseif gxWidth >= 3840 then
+        local width = gxWidth;
+        local height = gxHeight;
+        if(self.db.general.multiMonitor) then
+            if width >= 9840 then width = 3280; end
+            if width >= 7680 and width < 9840 then width = 2560; end
+            if width >= 5760 and width < 7680 then width = 1920; end
+            if width >= 5040 and width < 5760 then width = 1680; end
+            if width >= 4800 and width < 5760 and height == 900 then width = 1600; end
+            if width >= 4320 and width < 4800 then width = 1440; end
+            if width >= 4080 and width < 4320 then width = 1360; end
+            if width >= 3840 and width < 4080 then width = 1224; end
+            if width < 1600 then
+                self.ghettoMonitor = true;
+            end
+        else
+            if width >= 9840 then width = 9840; end
+            if width >= 7680 and width < 9840 then width = 7680; end
+            if width >= 5760 and width < 7680 then width = 5760; end
+            if width >= 5040 and width < 5760 then width = 5040; end
+            if width >= 4800 and width < 5040 then width = 4800; end
+            if width >= 4320 and width < 4800 then width = 4320; end
+            if width >= 4080 and width < 4320 then width = 4080; end
+            if width >= 3840 and width < 4080 then width = 3840; end
+        end
+
+        evalwidth = width;
+    end
+
+    if(parsefloat(UIParent:GetScale(),5) ~= parsefloat(scale,5) and (event == 'PLAYER_LOGIN')) then
+        SetCVar("useUiScale",1)
+        SetCVar("uiScale",scale)
+        WorldMapFrame.hasTaint = true;
+    end
+
+    if(event == 'PLAYER_LOGIN' or event == 'UI_SCALE_CHANGED') then
+        if IsMacClient() then
+            self.DisplaySettings.screenheight = floor(GetScreenHeight() * 100 + .5) / 100
+            self.DisplaySettings.screenwidth = floor(GetScreenWidth() * 100 + .5) / 100
+        end
+
+        if evalwidth then
+            local width = evalwidth
+            local height = gxHeight;
+            if not self.db.general.autoScale or height > 1200 then
+                height = UIParent:GetHeight();
+                local ratio = gxHeight / height;
+                width = evalwidth / ratio;
+            end
+            self.UIParent:SetSize(width, height);
+        else
+            self.UIParent:SetSize(UIParent:GetSize());
+        end
+
+        self.UIParent:ClearAllPoints()
+        self.UIParent:SetPoint("CENTER")
+
+        local change = abs((parsefloat(UIParent:GetScale(),5) * 100) - (parsefloat(scale,5) * 100))
+        if(event == 'UI_SCALE_CHANGED' and change > 1 and self.db.general.autoScale) then
+            self:StaticPopup_Show('FAILED_UISCALE')
+        elseif(event == 'UI_SCALE_CHANGED' and change > 1) then
+            self:StaticPopup_Show('RL_CLIENT')
+        end
+
+        self.UIParent:UnregisterEvent('PLAYER_LOGIN')
+
+        self.EffectiveScale = self.UIParent:GetEffectiveScale()
+        self.ActualHeight = self.UIParent:GetHeight()
+        self.ActualWidth = self.UIParent:GetWidth()
+    end
+end
+
+local function scaled(value)
+    if(not SCREEN_MOD) then
+        SV:UI_SCALE_CHANGED()
+    end
+    return SCREEN_MOD * floor(value / SCREEN_MOD + .5);
+end
+
+SV.Scale = scaled
+--[[
+##########################################################
+APPENDED POSITIONING METHODS
+##########################################################
+]]--
+do
+    local PARAMS = {}
+
+    function SizeScaled(self, width, height)
+        if(type(width) == "number") then
+            local h = (height and type(height) == "number") and height or width
+            self:SetSize(scaled(width), scaled(h))
+        end
+    end
+
+    function WidthScaled(self, width)
+        if(type(width) == "number") then
+            self:SetWidth(scaled(width))
+        end
+    end
+
+    function HeightScaled(self, height)
+        if(type(height) == "number") then
+            self:SetHeight(scaled(height))
+        end
+    end
+
+    function PointScaled(self, ...)
+        local n = select('#', ...)
+        PARAMS = {...}
+        local arg
+        for i = 1, n do
+            arg = PARAMS[i]
+            if(arg and type(arg) == "number") then
+                PARAMS[i] = scaled(arg)
+            end
+        end
+        self:SetPoint(unpack(PARAMS))
+    end
+
+    function WrapOuter(self, parent, x, y)
+        x = type(x) == "number" and x or 1
+        y = y or x
+        local nx = scaled(x);
+        local ny = scaled(y);
+        parent = parent or self:GetParent()
+        if self:GetPoint() then
+            self:ClearAllPoints()
+        end
+        self:SetPoint("TOPLEFT", parent, "TOPLEFT", -nx, ny)
+        self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", nx, -ny)
+    end
+
+    function FillInner(self, parent, x, y)
+        x = type(x) == "number" and x or 1
+        y = y or x
+        local nx = scaled(x);
+        local ny = scaled(y);
+        parent = parent or self:GetParent()
+        if self:GetPoint() then
+            self:ClearAllPoints()
+        end
+        self:SetPoint("TOPLEFT", parent, "TOPLEFT", nx, -ny)
+        self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -nx, ny)
+    end
+end
+--[[
+##########################################################
+APPENDED DESTROY METHODS
+##########################################################
+]]--
+local _purgatory = NewFrame("Frame", nil)
+_purgatory:Hide()
+
+local function Die(self)
+    if self.UnregisterAllEvents then
+        self:UnregisterAllEvents()
+        self:SetParent(_purgatory)
+    else
+        self:Hide()
+        self.Show = SV.fubar
+    end
+end
+
+local function RemoveTextures(self, option)
+    if(self.Panel) then return end
+    local region, layer, texture
+    for i = 1, self:GetNumRegions()do
+        region = select(i, self:GetRegions())
+        if(region and (region:GetObjectType() == "Texture")) then
+
+            layer = region:GetDrawLayer()
+            texture = region:GetTexture()
+
+            if(option) then
+                if(type(option) == "boolean") then
+                    if region.UnregisterAllEvents then
+                        region:UnregisterAllEvents()
+                        region:SetParent(_purgatory)
+                    else
+                        region.Show = region.Hide
+                    end
+                    region:Hide()
+                elseif(type(option) == "string" and ((layer == option) or (texture ~= option))) then
+                    region:SetTexture(0,0,0,0)
+                end
+            else
+                region:SetTexture(0,0,0,0)
+            end
+        end
+    end
+end
+--[[
+##########################################################
+APPENDED FONT TEMPLATING METHODS
+##########################################################
+]]--
+local function SetFontTemplate(self, font, fontSize, fontStyle, fontJustifyH, fontJustifyV, noUpdate)
+    if not self then return end
+    local STANDARDFONTSIZE = SV.db.media.fonts and SV.db.media.fonts.size or 12
+    font = font or [[Interface\AddOns\SVUI\assets\fonts\Default.ttf]]
+    fontSize = fontSize or STANDARDFONTSIZE;
+    fontJustifyH = fontJustifyH or "CENTER";
+    fontJustifyV = fontJustifyV or "MIDDLE";
+    if not font then return end
+    self.font = font;
+    self.fontSize = fontSize;
+    self.fontStyle = fontStyle;
+    self.fontJustifyH = fontJustifyH;
+    self.fontJustifyV = fontJustifyV;
+    self:SetFont(font, fontSize, fontStyle)
+    if(fontStyle and fontStyle ~= "NONE") then
+        self:SetShadowColor(0, 0, 0, 0)
+    else
+        self:SetShadowColor(0, 0, 0, 0.2)
+    end
+    self:SetShadowOffset(1, -1)
+    self:SetJustifyH(fontJustifyH)
+    self:SetJustifyV(fontJustifyV)
+    self.useCommon = fontSize and (fontSize == STANDARDFONTSIZE);
+    if(not noUpdate) then
+        FontUpdateFrames[self] = true
+    end
+end
+--[[
+##########################################################
+FONT UPDATE CALLBACK
+##########################################################
+]]--
+local function FontTemplateUpdates()
+    local STANDARDFONTSIZE = SV.db.media.fonts.size;
+    for i=1, #FontUpdateFrames do
+        local frame = FontUpdateFrames[i]
+        if frame then
+            local fontSize = frame.useCommon and STANDARDFONTSIZE or frame.fontSize
+            frame:SetFont(frame.font, fontSize, frame.fontStyle)
+        else
+            FontUpdateFrames[i] = nil
+        end
+    end
+end
+
+function SV:UpdateFontTemplates()
+    FontTemplateUpdates()
+end
+
+SV:NewCallback(FontTemplateUpdates)
+--[[
+##########################################################
+XML TEMPLATE LOOKUP TABLE
+##########################################################
+]]--
+local XML_LOOKUP = {
+    ["Default"] = "SVUI_PanelTemplate_Default",
+    ["Transparent"] = "SVUI_PanelTemplate_Transparent",
+    ["Component"] = "SVUI_PanelTemplate_Component",
+    ["Headline"] = "SVUI_PanelTemplate_Headline",
+    ["Button"] = "SVUI_PanelTemplate_Button",
+    ["FramedTop"] = "SVUI_PanelTemplate_FramedTop",
+    ["FramedBottom"] = "SVUI_PanelTemplate_FramedBottom",
+    ["Bar"] = "SVUI_PanelTemplate_Bar",
+    ["Slot"] = "SVUI_PanelTemplate_Slot",
+    ["Inset"] = "SVUI_PanelTemplate_Inset",
+    ["Comic"] = "SVUI_PanelTemplate_Comic",
+    ["Model"] = "SVUI_PanelTemplate_Model",
+    ["Paper"] = "SVUI_PanelTemplate_Paper",
+    ["Container"] = "SVUI_PanelTemplate_Container",
+    ["Pattern"] = "SVUI_PanelTemplate_Pattern",
+    ["Halftone"] = "SVUI_PanelTemplate_Halftone",
+    ["Action"] = "SVUI_PanelTemplate_Action",
+    ["Blackout"] = "SVUI_PanelTemplate_Blackout",
+    ["UnitLarge"] = "SVUI_PanelTemplate_UnitLarge",
+    ["UnitSmall"] = "SVUI_PanelTemplate_UnitSmall"
+};
+--[[
+##########################################################
+INTERNAL HANDLERS
+##########################################################
+]]--
+local HookPanelBorderColor = function(self,r,g,b,a)
+    if self.BorderLeft then
+        self.BorderLeft:SetVertexColor(r,g,b,a)
+        self.BorderRight:SetVertexColor(r,g,b,a)
+        self.BorderTop:SetVertexColor(r,g,b,a)
+        self.BorderBottom:SetVertexColor(r,g,b,a)
+    end
+    if self.Shadow then
+        local alpha = self.Shadow:GetAttribute("shadowAlpha") or 0.5
+        self.Shadow:SetBackdropBorderColor(r,g,b,alpha)
+    end
+end
+
+local HookBackdrop = function(self,...)
+    self.Panel:SetBackdrop(...)
+end
+
+local HookBackdropColor = function(self,...)
+    self.Panel:SetBackdropColor(...)
+end
+
+local HookBackdropBorderColor = function(self,...)
+    self.Panel:SetBackdropBorderColor(...)
+end
+
+local HookVertexColor = function(self,...)
+    self.Panel.Skin:SetVertexColor(...)
+end
+
+local HookCustomBackdrop = function(self)
+    local bgid = self.Panel:GetAttribute("panelID")
+    local newBgFile = SV.Media.bg[bgid]
+    local bd = {
+        bgFile = newBgFile,
+        edgeFile = [[Interface\BUTTONS\WHITE8X8]],
+        tile = false,
+        tileSize = 0,
+        edgeSize = 2,
+        insets =
+        {
+            left = 2,
+            right = 2,
+            top = 2,
+            bottom = 2,
+        },
+    }
+    self:SetBackdrop(bd)
+end
+
+local HookFrameLevel = function(self, level)
+    local adjustment = level - 1;
+    if(adjustment < 0) then adjustment = 0 end
+    self.Panel:SetFrameLevel(adjustment)
+end
+
+local Cooldown_ForceUpdate = function(self)
+    self.nextUpdate = 0;
+    self:Show()
+end
+
+local Cooldown_StopTimer = function(self)
+    self.enable = nil;
+    self:Hide()
+end
+
+local Cooldown_OnUpdate = function(self, elapsed)
+    if self.nextUpdate > 0 then
+        self.nextUpdate = self.nextUpdate - elapsed;
+        return
+    end
+    local expires = (self.duration - (GetTime() - self.start));
+    if expires > 0.05 then
+        if (self.fontScale * self:GetEffectiveScale() / UIParent:GetScale()) < 0.5 then
+            self.text:SetText('')
+            self.nextUpdate = 500
+        else
+            local timeLeft = 0;
+            local calc = 0;
+            if expires < 4 then
+                self.nextUpdate = 0.051
+                self.text:SetFormattedText("|cffff0000%.1f|r", expires)
+            elseif expires < 60 then
+                self.nextUpdate = 0.51
+                self.text:SetFormattedText("|cffffff00%d|r", floor(expires))
+            elseif expires < 3600 then
+                timeLeft = ceil(expires / 60);
+                calc = floor((expires / 60) + .5);
+                self.nextUpdate = calc > 1 and ((expires - calc) * 29.5) or (expires - 59.5);
+                self.text:SetFormattedText("|cffffffff%dm|r", timeLeft)
+            elseif expires < 86400 then
+                timeLeft = ceil(expires / 3600);
+                calc = floor((expires / 3600) + .5);
+                self.nextUpdate = calc > 1 and ((expires - calc) * 1799.5) or (expires - 3570);
+                self.text:SetFormattedText("|cff66ffff%dh|r", timeLeft)
+            else
+                timeLeft = ceil(expires / 86400);
+                calc = floor((expires / 86400) + .5);
+                self.nextUpdate = calc > 1 and ((expires - calc) * 43199.5) or (expires - 86400);
+                self.text:SetFormattedText("|cff6666ff%dd|r", timeLeft)
+            end
+        end
+    else
+        Cooldown_StopTimer(self)
+    end
+end
+
+local Cooldown_OnSizeChanged = function(self, width, height)
+    local frame = self.timer
+    local override = self.SizeOverride
+    local newSize = floor(width + .5) / 36;
+    override = override or frame:GetParent():GetParent().SizeOverride;
+    if override then
+        newSize = override / 20
+    end
+    if newSize == frame.fontScale then
+        return
+    end
+    frame.fontScale = newSize;
+    if newSize < 0.5 and not override then
+        frame:Hide()
+    else
+        frame:Show()
+        frame.text:SetFont([[Interface\AddOns\SVUI\assets\fonts\Numbers.ttf]], newSize * 15, 'OUTLINE')
+        if frame.enable then
+            Cooldown_ForceUpdate(frame)
+        end
+    end
+end
+
+local function CreateCooldownTimer(frame)
+    local timer = CreateFrame('Frame', nil, frame)
+    timer:Hide()
+    timer:SetAllPoints()
+    timer:SetScript('OnUpdate', Cooldown_OnUpdate)
+
+    local timeText = timer:CreateFontString(nil,'OVERLAY')
+    timeText:SetPoint('CENTER',1,1)
+    timeText:SetJustifyH("CENTER")
+    timer.text = timeText;
+
+    frame.timer = timer;
+    local width, height = frame:GetSize()
+    Cooldown_OnSizeChanged(frame, width, height)
+    frame:SetScript('OnSizeChanged', Cooldown_OnSizeChanged)
+
+    return frame.timer
+end
+
+local _hook_Cooldown_SetCooldown = function(self, start, duration, elapsed)
+    if start > 0 and duration > 2.5 then
+        local timer = self.timer or CreateCooldownTimer(self)
+        timer.start = start;
+        timer.duration = duration;
+        timer.enable = true;
+        timer.nextUpdate = 0;
+
+        if timer.fontScale >= 0.5 then
+            timer:Show()
+        end
+    else
+        local timer = self.timer;
+        if timer then
+            Cooldown_StopTimer(timer)
+        end
+    end
+    if self.timer then
+        if elapsed and elapsed > 0 then
+            self.timer:SetAlpha(0)
+        else
+            self.timer:SetAlpha(0.8)
+        end
+    end
+end
+--[[
+##########################################################
+COOLDOWN HELPER
+##########################################################
+]]--
+local function CreateCooldown(button)
+    local cooldown = button:GetName() and _G[button:GetName().."Cooldown"]
+    if(cooldown) then
+        cooldown:ClearAllPoints()
+        cooldown:FillInner()
+        cooldown:SetSwipeColor(0, 0, 0, 1)
+        --cooldown:SetHideCountdownNumbers(true)
+
+        if(not cooldown.HookedCooldown) then
+            hooksecurefunc(cooldown, "SetCooldown", _hook_Cooldown_SetCooldown)
+            cooldown.HookedCooldown = true
+        end
+    end
+end
+--[[
+##########################################################
+TEMPLATE HELPERS
+##########################################################
+]]--
+local function CreatePanelTemplate(frame, templateName, underlay, noupdate, padding, xOffset, yOffset, defaultColor)
+    local xmlTemplate = XML_LOOKUP[templateName] or "SVUI_PanelTemplate_Default"
+    local borderColor = {0,0,0,1}
+
+    frame.Panel = NewFrame('Frame', nil, frame, xmlTemplate)
+
+    local level = frame:GetFrameLevel()
+    if(level == 0 and not InCombatLockdown()) then
+        frame:SetFrameLevel(1)
+        level = 1
+    end
+
+    local adjustment = level - 1;
+
+    if(adjustment < 0) then adjustment = 0 end
+
+    frame.Panel:SetFrameLevel(adjustment)
+
+    NewHook(frame, "SetFrameLevel", HookFrameLevel)
+
+    if(defaultColor) then
+        frame.Panel:SetAttribute("panelColor", defaultColor)
+    end
+    if(noupdate) then
+        frame.Panel:SetAttribute("panelSkipUpdate", noupdate)
+    end
+
+    local colorName     = frame.Panel:GetAttribute("panelColor")
+    local gradientName  = frame.Panel:GetAttribute("panelGradient")
+    local forcedOffset  = frame.Panel:GetAttribute("panelOffset")
+
+    xOffset = forcedOffset or xOffset or 1
+    yOffset = forcedOffset or yOffset or 1
+
+    frame.Panel:WrapOuter(frame, xOffset, yOffset)
+
+    padding = padding or frame.Panel:GetAttribute("panelPadding")
+
+    if(padding and frame.Panel.BorderLeft) then
+        frame.Panel.BorderLeft:SetWidth(padding)
+        frame.Panel.BorderRight:SetWidth(padding)
+        frame.Panel.BorderTop:SetHeight(padding)
+        frame.Panel.BorderBottom:SetHeight(padding)
+    end
+
+    if(frame.Panel.Shadow) then
+        frame.Panel.Shadow:SetPoint('TOPLEFT', frame.Panel, 'TOPLEFT', -3, 3)
+        frame.Panel.Shadow:SetPoint('BOTTOMRIGHT', frame.Panel, 'BOTTOMRIGHT', 3, -3)
+
+        local alpha = frame.Panel.Shadow:GetAttribute("shadowAlpha") or 0.5
+        frame.Panel.Shadow:SetBackdropBorderColor(0,0,0,alpha)
+
+        local level = frame.Panel.Shadow:GetFrameLevel() - 1
+        if(level >= 0) then
+            frame.Panel.Shadow:SetFrameLevel(level)
+        else
+            frame.Panel.Shadow:SetFrameLevel(0)
+        end
+    end
+
+    local bgColor = SV.Media.color[colorName] or {0.18,0.18,0.18,1}
+
+    if(not frame.Panel:GetAttribute("panelNoBackdrop")) then
+        if(underlay) then
+            frame.Panel:SetBackdropColor(bgColor[1],bgColor[2],bgColor[3],bgColor[4] or 1)
+            frame.Panel:SetBackdropBorderColor(0,0,0,1)
+        else
+            local bd = frame.Panel:GetBackdrop()
+            frame:SetBackdrop(bd)
+            frame:SetBackdropColor(bgColor[1],bgColor[2],bgColor[3],bgColor[4] or 1)
+            frame:SetBackdropBorderColor(0,0,0,1)
+
+            frame.Panel:SetBackdrop(nil)
+        end
+
+        if(templateName ~= 'Transparent') then
+            NewHook(frame.Panel, "SetBackdropBorderColor", HookPanelBorderColor)
+            NewHook(frame, "SetBackdropBorderColor", HookBackdropBorderColor)
+            if(underlay) then
+                NewHook(frame, "SetBackdrop", HookBackdrop)
+                NewHook(frame, "SetBackdropColor", HookBackdropColor)
+            end
+            frame.BackdropNeedsUpdate = true
+            if(templateName == 'Pattern' or templateName == 'Comic') then
+                frame.UpdateBackdrop = HookCustomBackdrop
+            end
+        end
+    end
+
+    if(frame.Panel.Skin) then
+        if(not underlay) then
+            frame.Panel.Skin:SetParent(frame)
+            frame.Panel.Skin:FillInner(frame, xOffset, yOffset)
+        else
+            frame.Panel.Skin:FillInner(frame.Panel, xOffset, yOffset)
+        end
+        if(gradientName and SV.Media.gradient[gradientName]) then
+            frame.Panel.Skin:SetGradient(unpack(SV.Media.gradient[gradientName]))
+        else
+            frame.Panel.Skin:SetVertexColor(bgColor[1], bgColor[2], bgColor[3], bgColor[4] or 1)
+        end
+
+        if((not frame.Panel:GetAttribute("panelSkipUpdate")) and frame.Panel:GetAttribute("panelTexUpdate")) then
+            frame.TextureNeedsUpdate = true
+            if(templateName == 'UnitLarge' or templateName == 'UnitSmall') then
+                frame.UpdateColor = HookVertexColor
+                frame.NoColorUpdate = true
+            end
+        end
+    end
+end
+
+local function CreateButtonPanel(frame, noChecked, brightChecked)
+
+    if(frame.Left) then
+        frame.Left:SetAlpha(0)
+    end
+
+    if(frame.Middle) then
+        frame.Middle:SetAlpha(0)
+    end
+
+    if(frame.Right) then
+        frame.Right:SetAlpha(0)
+    end
+
+    if(frame.SetNormalTexture) then
+        frame:SetNormalTexture("")
+    end
+
+    if(frame.SetDisabledTexture) then
+        frame:SetDisabledTexture("")
+    end
+
+    if(frame.SetCheckedTexture) then
+        frame:SetCheckedTexture("")
+    end
+
+    if(frame.SetHighlightTexture) then
+        if(not frame.hover) then
+            local hover = frame:CreateTexture(nil, "OVERLAY")
+            hover:FillInner(frame.Panel)
+            frame.hover = hover;
+        end
+        local color = SV.Media.color.highlight
+        frame.hover:SetTexture(color[1], color[2], color[3], 0.5)
+        frame:SetHighlightTexture(frame.hover)
+    end
+
+    if(frame.SetPushedTexture) then
+        if(not frame.pushed) then
+            local pushed = frame:CreateTexture(nil, "OVERLAY")
+            pushed:FillInner(frame.Panel)
+            frame.pushed = pushed;
+        end
+        frame.pushed:SetTexture(0.1, 0.8, 0.1, 0.3)
+        frame:SetPushedTexture(frame.pushed)
+    end
+
+    if(not noChecked and frame.SetCheckedTexture) then
+        if(not frame.checked) then
+            local checked = frame:CreateTexture(nil, "OVERLAY")
+            checked:FillInner(frame.Panel)
+            frame.checked = checked
+        end
+
+        if(not brightChecked) then
+            frame.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Template\DEFAULT]])
+            frame.checked:SetVertexColor(0, 0.5, 0, 0.2)
+        else
+            frame.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Bars\GLOSS]])
+            frame.checked:SetVertexColor(0, 1, 0, 1)
+        end
+
+        frame:SetCheckedTexture(frame.checked)
+    end
+
+    CreateCooldown(frame)
+end
+--[[
+##########################################################
+TEMPLATE API
+##########################################################
+]]--
+local function SetBasicPanel(self, topX, topY, bottomX, bottomY, hasShadow)
+    local needsHooks = false;
+
+    if(hasShadow) then
+        if(not self.Panel) then
+            needsHooks = true
+
+            self.Panel = CreateFrame("Frame", nil, self)
+            self.Panel:SetPoint("TOPLEFT", self, "TOPLEFT", -2, 2)
+            self.Panel:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 2, -2)
+        end
+
+        self.Panel:SetBackdrop({
+            bgFile = [[Interface\BUTTONS\WHITE8X8]],
+            tile = false,
+            tileSize = 0,
+            edgeFile = [[Interface\AddOns\SVUI\assets\artwork\Template\GLOW]],
+            edgeSize = 3,
+            insets =
+            {
+                left = 0,
+                right = 0,
+                top = 0,
+                bottom = 0,
+            },
+        })
+        self.Panel:SetBackdropColor(0,0,0,0)
+        self.Panel:SetBackdropBorderColor(0,0,0)
+    else
+        if(not self.Panel) then
+            needsHooks = true
+
+            self.Panel = CreateFrame("Frame", nil, self)
+            self.Panel:SetPoint("TOPLEFT", self, "TOPLEFT", topX, topY)
+            self.Panel:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", bottomX, bottomY)
+        end
+
+        self.Panel:SetBackdrop({
+            bgFile = [[Interface\BUTTONS\WHITE8X8]],
+            tile = false,
+            tileSize = 0,
+            edgeFile = [[Interface\BUTTONS\WHITE8X8]],
+            edgeSize = 1,
+            insets =
+            {
+                left = 1,
+                right = 1,
+                top = 1,
+                bottom = 1,
+            },
+        })
+        self.Panel:SetBackdropColor(0,0,0,0.65)
+        self.Panel:SetBackdropBorderColor(0,0,0)
+    end
+
+    if(needsHooks) then
+        local level = self:GetFrameLevel()
+        if(level == 0 and not InCombatLockdown()) then
+            self:SetFrameLevel(1)
+            level = 1
+        end
+
+        local adjustment = level - 1;
+        if(adjustment < 0) then adjustment = 0 end
+
+        self.Panel:SetFrameLevel(adjustment)
+
+        NewHook(self, "SetFrameLevel", HookFrameLevel)
+        NewHook(self, "SetBackdrop", HookBackdrop)
+        NewHook(self, "SetBackdropColor", HookBackdropColor)
+        NewHook(self, "SetBackdropBorderColor", HookBackdropBorderColor)
+    end
+end
+
+local function SetPanelTemplate(self, templateName, noupdate, overridePadding, xOffset, yOffset, defaultColor)
+    if(not self or (self and self.Panel)) then return end
+    local padding = false
+    if(overridePadding and type(overridePadding) == "number") then
+        padding = overridePadding
+    end
+
+    CreatePanelTemplate(self, templateName, true, noupdate, padding, xOffset, yOffset, defaultColor)
+
+    if(not self.Panel:GetAttribute("panelSkipUpdate") and not self.__registered) then
+        TemplateUpdateFrames[self] = true
+        self.__registered = true
+    end
+end
+
+local function SetFixedPanelTemplate(self, templateName, noupdate, overridePadding, xOffset, yOffset, defaultColor)
+    if(not self or (self and self.Panel)) then return end
+    local padding = false
+    if(overridePadding and type(overridePadding) == "number") then
+        padding = overridePadding
+    end
+
+    CreatePanelTemplate(self, templateName, false, noupdate, padding, xOffset, yOffset, defaultColor)
+
+    if(not self.Panel:GetAttribute("panelSkipUpdate") and not self.__registered) then
+        TemplateUpdateFrames[self] = true
+        self.__registered = true
+    end
+end
+
+local function SetPanelColor(self, ...)
+    local arg1,arg2,arg3,arg4,arg5,arg6,arg7 = select(1, ...)
+    if(not self.Panel or not arg1) then return; end
+    if(self.Panel.Skin and self.Panel:GetAttribute("panelGradient")) then
+        if(type(arg1) == "string") then
+            if(arg1 == "VERTICAL" or arg1 == "HORIZONTAL") then
+                self.Panel.Skin:SetGradient(...)
+            elseif(SV.Media.gradient[arg1]) then
+                if self.__border then
+                    local d,r,g,b,r2,g2,b2 = unpack(SV.Media.gradient[arg1])
+                    --self.Panel.Skin:SetGradient(d,r,g,b,r2,g2,b2)
+                    self.__border[1]:SetTexture(r2,g2,b2)
+                    self.__border[2]:SetTexture(r2,g2,b2)
+                    self.__border[3]:SetTexture(r2,g2,b2)
+                    self.__border[4]:SetTexture(r2,g2,b2)
+                else
+                    self.Panel.Skin:SetGradient(unpack(SV.Media.gradient[arg1]))
+                    if(SV.Media.color[arg1]) then
+                        local t = SV.Media.color[arg1]
+                        local r,g,b,a = t[1], t[2], t[3], t[4] or 1;
+                        self:SetBackdropColor(r,g,b,a)
+                    end
+                end
+            end
+        end
+    elseif(type(arg1) == "string" and SV.Media.color[arg1]) then
+        local t = SV.Media.color[arg1]
+        local r,g,b,a = t[1], t[2], t[3], t[4] or 1;
+        if self.__border then
+            self.__border[1]:SetTexture(r,g,b)
+            self.__border[2]:SetTexture(r,g,b)
+            self.__border[3]:SetTexture(r,g,b)
+            self.__border[4]:SetTexture(r,g,b)
+        else
+            self:SetBackdropColor(r,g,b)
+        end
+    elseif(arg1 and type(arg1) == "number") then
+        self:SetBackdropColor(...)
+    end
+end
+--[[
+##########################################################
+APPENDED BUTTON TEMPLATING METHODS
+##########################################################
+]]--
+local function SetButtonTemplate(self, invisible, overridePadding, xOffset, yOffset, keepNormal, defaultColor)
+    if(not self or (self and self.Panel)) then return end
+
+    local padding = 1
+    if(overridePadding and type(overridePadding) == "number") then
+        padding = overridePadding
+    end
+
+    local x,y = -1,-1
+    local underlay = false
+    if(xOffset or yOffset) then
+        x = xOffset or -1
+        y = yOffset or -1
+        underlay = true
+    end
+
+    if(invisible) then
+        CreatePanelTemplate(self, "Transparent", underlay, true, padding, x, y, defaultColor)
+        self:SetBackdropColor(0,0,0,0)
+        self:SetBackdropBorderColor(0,0,0,0)
+        if(self.Panel.BorderLeft) then
+            self.Panel.BorderLeft:SetVertexColor(0,0,0,0)
+            self.Panel.BorderRight:SetVertexColor(0,0,0,0)
+            self.Panel.BorderTop:SetVertexColor(0,0,0,0)
+            self.Panel.BorderBottom:SetVertexColor(0,0,0,0)
+        end
+    else
+        CreatePanelTemplate(self, "Button", underlay, true, padding, x, y, defaultColor)
+    end
+
+    if(self.Left) then
+        self.Left:SetAlpha(0)
+    end
+
+    if(self.Middle) then
+        self.Middle:SetAlpha(0)
+    end
+
+    if(self.Right) then
+        self.Right:SetAlpha(0)
+    end
+
+    if(self.SetNormalTexture and not keepNormal) then
+        self:SetNormalTexture("")
+    end
+
+    if(self.SetDisabledTexture) then
+        self:SetDisabledTexture("")
+    end
+
+    if(self.SetHighlightTexture) then
+        if(not self.hover) then
+            local hover = self:CreateTexture(nil, "HIGHLIGHT")
+            FillInner(hover, self.Panel)
+            self.hover = hover;
+        end
+        self.hover:SetTexture(0.1, 0.8, 0.8, 0.5)
+        self:SetHighlightTexture(self.hover)
+    end
+
+    if(self.SetPushedTexture) then
+        if(not self.pushed) then
+            local pushed = self:CreateTexture(nil, "OVERLAY")
+            FillInner(pushed, self.Panel)
+            self.pushed = pushed;
+        end
+
+        self.pushed:SetTexture(0.1, 0.8, 0.1, 0.3)
+
+        self:SetPushedTexture(self.pushed)
+    end
+
+    if(self.SetCheckedTexture) then
+        if(not self.checked) then
+            local checked = self:CreateTexture(nil, "OVERLAY")
+            FillInner(checked, self.Panel)
+            self.checked = checked;
+        end
+
+        self.checked:SetTexture([[Interface\AddOns\SVUI\assets\artwork\Template\DEFAULT]])
+        self.checked:SetVertexColor(0, 0.5, 0, 0.2)
+
+        self:SetCheckedTexture(self.checked)
+    end
+
+    CreateCooldown(self)
+end
+
+local function SetSlotTemplate(self, underlay, padding, x, y, shadowAlpha)
+    if(not self or (self and self.Panel)) then return end
+    padding = padding or 1
+    CreatePanelTemplate(self, "Slot", underlay, true, padding, x, y)
+    CreateButtonPanel(self, true)
+    if(shadowAlpha) then
+        self.Panel.Shadow:SetAttribute("shadowAlpha", shadowAlpha)
+    end
+end
+
+local function SetCheckboxTemplate(self, underlay, x, y)
+    if(not self or (self and self.Panel)) then return end
+
+    if(underlay) then
+        x = x or -7
+        y = y or -7
+    end
+
+    CreatePanelTemplate(self, "Slot", underlay, true, 1, x, y)
+    CreateButtonPanel(self, false, true)
+
+    NewHook(self, "SetChecked", function(self,checked)
+        local r,g,b = 0,0,0
+        if(checked == 1 or checked == true) then
+            r,g,b = self:GetCheckedTexture():GetVertexColor()
+        end
+        self:SetBackdropBorderColor(r,g,b)
+    end)
+end
+
+local function SetEditboxTemplate(self, x, y, fixed)
+    if(not self or (self and self.Panel)) then return end
+
+    if self.TopLeftTex then Die(self.TopLeftTex) end
+    if self.TopRightTex then Die(self.TopRightTex) end
+    if self.TopTex then Die(self.TopTex) end
+    if self.BottomLeftTex then Die(self.BottomLeftTex) end
+    if self.BottomRightTex then Die(self.BottomRightTex) end
+    if self.BottomTex then Die(self.BottomTex) end
+    if self.LeftTex then Die(self.LeftTex) end
+    if self.RightTex then Die(self.RightTex) end
+    if self.MiddleTex then Die(self.MiddleTex) end
+    local underlay = true
+    if(fixed ~= nil) then underlay = fixed end
+    CreatePanelTemplate(self, "Inset", underlay, true, 1, x, y)
+
+    local globalName = self:GetName();
+    if globalName then
+        if _G[globalName.."Left"] then Die(_G[globalName.."Left"]) end
+        if _G[globalName.."Middle"] then Die(_G[globalName.."Middle"]) end
+        if _G[globalName.."Right"] then Die(_G[globalName.."Right"]) end
+        if _G[globalName.."Mid"] then Die(_G[globalName.."Mid"]) end
+
+        if globalName:find("Silver") or globalName:find("Copper") or globalName:find("Gold") then
+            self.Panel:SetPoint("TOPLEFT", -3, 1)
+            if globalName:find("Silver") or globalName:find("Copper") then
+                self.Panel:SetPoint("BOTTOMRIGHT", -12, -2)
+            else
+                self.Panel:SetPoint("BOTTOMRIGHT", -2, -2)
+            end
+        end
+    end
+end
+
+local function SetFramedButtonTemplate(self, template, borderSize)
+    if(not self or (self and self.Panel)) then return end
+
+    borderSize = borderSize or 2
+
+    template = template or "FramedBottom"
+
+    CreatePanelTemplate(self, template, false, false, 0, -borderSize, -borderSize)
+
+    if(self.Left) then
+        self.Left:SetAlpha(0)
+    end
+
+    if(self.Middle) then
+        self.Middle:SetAlpha(0)
+    end
+
+    if(self.Right) then
+        self.Right:SetAlpha(0)
+    end
+
+    if(self.SetNormalTexture) then
+        self:SetNormalTexture("")
+    end
+
+    if(self.SetDisabledTexture) then
+        self:SetDisabledTexture("")
+    end
+
+    if(not self.__border) then
+        local t = SV.Media.color.default
+        local r,g,b = t[1], t[2], t[3]
+
+        local border = {}
+
+        border[1] = self:CreateTexture(nil,"BORDER")
+        border[1]:SetTexture(r,g,b)
+        border[1]:SetPoint("TOPLEFT", -1, 1)
+        border[1]:SetPoint("BOTTOMLEFT", -1, -1)
+        border[1]:SetWidth(borderSize)
+
+        local leftoutline = self:CreateTexture(nil,"BORDER")
+        leftoutline:SetTexture(0,0,0)
+        leftoutline:SetPoint("TOPLEFT", -2, 2)
+        leftoutline:SetPoint("BOTTOMLEFT", -2, -2)
+        leftoutline:SetWidth(1)
+
+        border[2] = self:CreateTexture(nil,"BORDER")
+        border[2]:SetTexture(r,g,b)
+        border[2]:SetPoint("TOPRIGHT", 1, 1)
+        border[2]:SetPoint("BOTTOMRIGHT", 1, -1)
+        border[2]:SetWidth(borderSize)
+
+        local rightoutline = self:CreateTexture(nil,"BORDER")
+        rightoutline:SetTexture(0,0,0)
+        rightoutline:SetPoint("TOPRIGHT", 2, 2)
+        rightoutline:SetPoint("BOTTOMRIGHT", 2, -2)
+        rightoutline:SetWidth(1)
+
+        border[3] = self:CreateTexture(nil,"BORDER")
+        border[3]:SetTexture(r,g,b)
+        border[3]:SetPoint("TOPLEFT", -1, 1)
+        border[3]:SetPoint("TOPRIGHT", 1, 1)
+        border[3]:SetHeight(borderSize)
+
+        local topoutline = self:CreateTexture(nil,"BORDER")
+        topoutline:SetTexture(0,0,0)
+        topoutline:SetPoint("TOPLEFT", -2, 2)
+        topoutline:SetPoint("TOPRIGHT", 2, 2)
+        topoutline:SetHeight(1)
+
+        border[4] = self:CreateTexture(nil,"BORDER")
+        border[4]:SetTexture(r,g,b)
+        border[4]:SetPoint("BOTTOMLEFT", -1, -1)
+        border[4]:SetPoint("BOTTOMRIGHT", 1, -1)
+        border[4]:SetHeight(borderSize)
+
+        local bottomoutline = self:CreateTexture(nil,"BORDER")
+        bottomoutline:SetTexture(0,0,0)
+        bottomoutline:SetPoint("BOTTOMLEFT", -2, -2)
+        bottomoutline:SetPoint("BOTTOMRIGHT", 2, -2)
+        bottomoutline:SetHeight(1)
+
+        self.__border = border
+    end
+
+    if(not self.hover) then
+        self.hover = self:CreateTexture(nil, "HIGHLIGHT")
+    end
+
+    local color = SV.Media.color.highlight
+    self.hover:SetTexture(color[1], color[2], color[3], 0.5)
+    self.hover:SetAllPoints()
+    if(self.SetHighlightTexture) then
+        self:SetHighlightTexture(self.hover)
+    end
+
+    if(not self.__registered) then
+        TemplateUpdateFrames[self] = true
+        self.__registered = true
+    end
+end
+--[[
+##########################################################
+TEMPLATE UPDATE CALLBACK
+##########################################################
+]]--
+local function FrameTemplateUpdates()
+    for frame in pairs(TemplateUpdateFrames) do
+        if(frame) then
+            local panelID = frame.Panel:GetAttribute("panelID")
+            local colorID = frame.Panel:GetAttribute("panelColor")
+            local panelColor = SV.Media.color[colorID];
+            if(frame.BackdropNeedsUpdate) then
+                if(frame.UpdateBackdrop) then
+                    frame:UpdateBackdrop()
+                end
+                if(panelColor) then
+                    frame:SetBackdropColor(panelColor[1], panelColor[2], panelColor[3], panelColor[4] or 1)
+                end
+                frame:SetBackdropBorderColor(0,0,0,1)
+            end
+            if(frame.TextureNeedsUpdate and frame.Panel.Skin) then
+                local tex = SV.Media.bg[panelID]
+                if(tex) then
+                    frame.Panel.Skin:SetTexture(tex)
+                end
+                if(not frame.NoColorUpdate) then
+                    local gradient = frame.Panel:GetAttribute("panelGradient")
+                    if(gradient and SV.Media.gradient[gradient]) then
+                        local g = SV.Media.gradient[gradient]
+                        frame.Panel.Skin:SetGradient(g[1], g[2], g[3], g[4], g[5], g[6], g[7])
+                    elseif(panelColor) then
+                        frame.Panel.Skin:SetVertexColor(panelColor[1], panelColor[2], panelColor[3], panelColor[4] or 1)
+                    end
+                end
+            end
+        end
+    end
+end
+
+SV:NewCallback(FrameTemplateUpdates)
+--[[
+##########################################################
+ENUMERATION
+##########################################################
+]]--
+local function AppendMethods(OBJECT)
+    local META = getmetatable(OBJECT).__index
+    if not OBJECT.Size then META.Size = SizeScaled end
+    if not OBJECT.Width then META.Width = WidthScaled end
+    if not OBJECT.Height then META.Height = HeightScaled end
+    if not OBJECT.Point then META.Point = PointScaled end
+    if not OBJECT.WrapOuter then META.WrapOuter = WrapOuter end
+    if not OBJECT.FillInner then META.FillInner = FillInner end
+    if not OBJECT.Die then META.Die = Die end
+    if not OBJECT.RemoveTextures then META.RemoveTextures = RemoveTextures end
+    if not OBJECT.SetBasicPanel then META.SetBasicPanel = SetBasicPanel end
+    if not OBJECT.SetPanelTemplate then META.SetPanelTemplate = SetPanelTemplate end
+    if not OBJECT.SetFixedPanelTemplate then META.SetFixedPanelTemplate = SetFixedPanelTemplate end
+    if not OBJECT.SetPanelColor then META.SetPanelColor = SetPanelColor end
+    if not OBJECT.SetButtonTemplate then META.SetButtonTemplate = SetButtonTemplate end
+    if not OBJECT.SetSlotTemplate then META.SetSlotTemplate = SetSlotTemplate end
+    if not OBJECT.SetCheckboxTemplate then META.SetCheckboxTemplate = SetCheckboxTemplate end
+    if not OBJECT.SetEditboxTemplate then META.SetEditboxTemplate = SetEditboxTemplate end
+    if not OBJECT.SetFramedButtonTemplate then META.SetFramedButtonTemplate = SetFramedButtonTemplate end
+    if not OBJECT.SetFontTemplate then META.SetFontTemplate = SetFontTemplate end
+end
+
+local HANDLER, OBJECT = {["Frame"] = true}, NewFrame("Frame")
+AppendMethods(OBJECT)
+AppendMethods(OBJECT:CreateTexture())
+AppendMethods(OBJECT:CreateFontString())
+
+OBJECT = EnumerateFrames()
+while OBJECT do
+    local objType = OBJECT:GetObjectType()
+    if not HANDLER[objType] then
+		AppendMethods(OBJECT)
+		HANDLER[objType] = true
+	end
+	OBJECT = EnumerateFrames(OBJECT)
+end
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/system/timers.lua b/Interface/AddOns/SVUI/system/timers.lua
deleted file mode 100644
index df74793..0000000
--- a/Interface/AddOns/SVUI/system/timers.lua
+++ /dev/null
@@ -1,272 +0,0 @@
---[[
-##############################################################################
-_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
- ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
-  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
-   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
-    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
-     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
-      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
-       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
-        ___\///////////___________\///___________\/////////_____\///////////_#
-##############################################################################
-S U P E R - V I L L A I N - U I   By: Munglunch                              #
-##############################################################################
-##########################################################
-LOCALIZED LUA FUNCTIONS
-##########################################################
-]]--
---[[ GLOBALS ]]--
-local _G = _G;
-local unpack 	= _G.unpack;
-local select 	= _G.select;
-local type 		= _G.type;
-local pairs     = _G.pairs;
-local tinsert 	= _G.tinsert;
-local string 	= _G.string;
-local math 		= _G.math;
-local table 	= _G.table;
---[[ STRING METHODS ]]--
-local format = string.format;
---[[ MATH METHODS ]]--
-local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;
---[[ TABLE METHODS ]]--
-local tremove = table.remove;
---[[
-##########################################################
-GET ADDON DATA
-##########################################################
-]]--
-local SV = select(2, ...)
-local L = SV.L;
---[[
-##########################################################
-LOCAL VARS
-##########################################################
-]]--
-local TIMERFONT = [[Interface\AddOns\SVUI\assets\fonts\Numbers.ttf]];
---[[
-##########################################################
-TIMERS
-##########################################################
-ExecuteTimer: Create a timer that runs once and CANNOT be stopped
-ExecuteLoop: Create a timer that loops continuously and CAN be removed
-
-NEW IN WOD: local timerloop = C_Timer.NewTicker(duration, callback, [iterations])
-]]--
-local Timers = CreateFrame("Frame");
-Timers.TimerCount = 0;
-Timers.Queue = {};
-
-local ExeTimerManager_OnUpdate = function(self, elapsed)
-	if(self.TimerCount > 0) then
-		for id,_ in pairs(self.Queue) do
-			local callback = self.Queue[id]
-			if(callback.f) then
-				if callback.t > elapsed then
-					local newTime = callback.t - elapsed
-					self.Queue[id].t = newTime
-				else
-					callback.f()
-					if(callback.x) then
-						self.Queue[id].t = callback.x
-					else
-						self.Queue[id] = nil
-						self.TimerCount = self.TimerCount - 1;
-					end
-				end
-			end
-		end
-	end
-end
-
-function Timers:ExecuteTimer(timeOutFunction, duration, idCheck)
-	if(type(duration) == "number" and type(timeOutFunction) == "function") then
-		if(idCheck and self.Queue[idCheck]) then
-			self.Queue[idCheck].t = duration
-			return idCheck
-		else
-			self.TimerCount = self.TimerCount + 1
-			local id = "LOOP" .. self.TimerCount;
-			self.Queue[id] = {t = duration, f = timeOutFunction}
-			return id
-		end
-	end
-	return false
-end
-
-function Timers:ExecuteLoop(timeOutFunction, duration, idCheck)
-	if(type(duration) == "number" and type(timeOutFunction) == "function") then
-		if(idCheck and self.Queue[idCheck]) then
-			self.Queue[idCheck].x = duration
-			self.Queue[idCheck].t = duration
-			return idCheck
-		else
-			self.TimerCount = self.TimerCount + 1
-			local id = "LOOP" .. self.TimerCount;
-			self.Queue[id] = {x = duration, t = duration, f = timeOutFunction}
-			return id
-		end
-	end
-	return false
-end
-
-function Timers:RemoveLoop(id)
-	if(self.Queue[id]) then
-		self.Queue[id] = nil
-		self.TimerCount = self.TimerCount - 1;
-	end
-end
-
-function Timers:ClearAllTimers()
-	self:SetScript("OnUpdate", nil)
-	self.Queue = {}
-	self:SetScript("OnUpdate", ExeTimerManager_OnUpdate)
-end
-
-local Timers_EventHandler = function(self, event)
-	if(event == "PLAYER_REGEN_DISABLED") then
-		self:SetScript("OnUpdate", nil)
-	else
-		self:SetScript("OnUpdate", ExeTimerManager_OnUpdate)
-	end
-end
-
-Timers:RegisterEvent('PLAYER_REGEN_ENABLED')
-Timers:RegisterEvent('PLAYER_REGEN_DISABLED')
-Timers:SetScript("OnEvent", Timers_EventHandler)
-Timers:SetScript("OnUpdate", ExeTimerManager_OnUpdate)
---[[
-##########################################################
-COOLDOWN FUNCTIONS
-##########################################################
-]]--
-local Cooldown_ForceUpdate = function(self)
-	self.nextUpdate = 0;
-	self:Show()
-end
-
-local Cooldown_StopTimer = function(self)
-	self.enable = nil;
-	self:Hide()
-end
-
-local Cooldown_OnUpdate = function(self, elapsed)
-	if self.nextUpdate > 0 then
-		self.nextUpdate = self.nextUpdate - elapsed;
-		return
-	end
-	local expires = (self.duration - (GetTime() - self.start));
-	if expires > 0.05 then
-		if (self.fontScale * self:GetEffectiveScale() / UIParent:GetScale()) < 0.5 then
-			self.text:SetText('')
-			self.nextUpdate = 500
-		else
-			local timeLeft = 0;
-			local calc = 0;
-			if expires < 4 then
-				self.nextUpdate = 0.051
-				self.text:SetFormattedText("|cffff0000%.1f|r", expires)
-			elseif expires < 60 then
-				self.nextUpdate = 0.51
-				self.text:SetFormattedText("|cffffff00%d|r", floor(expires))
-			elseif expires < 3600 then
-				timeLeft = ceil(expires / 60);
-				calc = floor((expires / 60) + .5);
-				self.nextUpdate = calc > 1 and ((expires - calc) * 29.5) or (expires - 59.5);
-				self.text:SetFormattedText("|cffffffff%dm|r", timeLeft)
-			elseif expires < 86400 then
-				timeLeft = ceil(expires / 3600);
-				calc = floor((expires / 3600) + .5);
-				self.nextUpdate = calc > 1 and ((expires - calc) * 1799.5) or (expires - 3570);
-				self.text:SetFormattedText("|cff66ffff%dh|r", timeLeft)
-			else
-				timeLeft = ceil(expires / 86400);
-				calc = floor((expires / 86400) + .5);
-				self.nextUpdate = calc > 1 and ((expires - calc) * 43199.5) or (expires - 86400);
-				self.text:SetFormattedText("|cff6666ff%dd|r", timeLeft)
-			end
-		end
-	else
-		Cooldown_StopTimer(self)
-	end
-end
-
-local function ModifyCoolSize(self, width, height, override)
-	local newSize = floor(width + .5) / 36;
-	override = override or self:GetParent():GetParent().SizeOverride;
-	if override then
-		newSize = override / 20
-	end
-	if newSize == self.fontScale then
-		return
-	end
-	self.fontScale = newSize;
-	if newSize < 0.5 and not override then
-		self:Hide()
-	else
-		self:Show()
-		self.text:SetFont(TIMERFONT, newSize * 15, 'OUTLINE')
-		if self.enable then
-			Cooldown_ForceUpdate(self)
-		end
-	end
-end
-
-local Cool_OnSize = function(self, width, height)
-	ModifyCoolSize(self.timer, width, height, self.SizeOverride)
-end
-
-local function CreateCoolTimer(self)
-	local timer = CreateFrame('Frame', nil, self)
-	timer:Hide()
-	timer:SetAllPoints()
-	timer:SetScript('OnUpdate', Cooldown_OnUpdate)
-
-	local timeText = timer:CreateFontString(nil,'OVERLAY')
-	timeText:SetPoint('CENTER',1,1)
-	timeText:SetJustifyH("CENTER")
-	timer.text = timeText;
-
-	self.timer = timer;
-	local width, height = self:GetSize()
-	ModifyCoolSize(self.timer, width, height, self.SizeOverride)
-	self:SetScript('OnSizeChanged', Cool_OnSize)
-
-	return self.timer
-end
-
-local Cooldown_OnLoad = function(self, start, duration, elapsed)
-	if start > 0 and duration > 2.5 then
-		local timer = self.timer or CreateCoolTimer(self)
-		timer.start = start;
-		timer.duration = duration;
-		timer.enable = true;
-		timer.nextUpdate = 0;
-
-		if timer.fontScale >= 0.5 then
-			timer:Show()
-		end
-	else
-		local timer = self.timer;
-		if timer then
-			Cooldown_StopTimer(timer)
-		end
-	end
-	if self.timer then
-		if elapsed and elapsed > 0 then
-			self.timer:SetAlpha(0)
-		else
-			self.timer:SetAlpha(0.8)
-		end
-	end
-end
-
-function Timers:AddCooldown(origin)
-	if(origin.HookedCooldown or not SV.db.general.cooldown) then return end
-	hooksecurefunc(origin, "SetCooldown", Cooldown_OnLoad)
-	origin.HookedCooldown = true
-	origin:SetHideCountdownNumbers(true)
-end
-
-SV.Timers = Timers;
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI/xml/widgets.xml b/Interface/AddOns/SVUI/xml/widgets.xml
index 4604030..31322cd 100644
--- a/Interface/AddOns/SVUI/xml/widgets.xml
+++ b/Interface/AddOns/SVUI/xml/widgets.xml
@@ -1151,7 +1151,7 @@

     <Frame name="SVUI_PanelTemplate_UnitSmall" virtual="true">
         <Attributes>
-            <Attribute name="panelID" type="string" value="unitlarge" />
+            <Attribute name="panelID" type="string" value="unitsmall" />
             <Attribute name="panelPadding" type="number" value="0" />
             <Attribute name="panelColor" type="string" value="special" />
             <Attribute name="panelGradient" type="boolean" value="false" />
diff --git a/Interface/AddOns/SVUI_ConfigOMatic/License.txt b/Interface/AddOns/SVUI_ConfigOMatic/License.txt
index 0e4e584..2631024 100644
--- a/Interface/AddOns/SVUI_ConfigOMatic/License.txt
+++ b/Interface/AddOns/SVUI_ConfigOMatic/License.txt
@@ -14,8 +14,6 @@

 SVUI_ConfigOMatic License Copyright 2014 http://wowinterface.com

-(Adapted and inspired by ElvUI) Copyright 2014 http://www.tukui.org
-
 The contents of this addon, excluding third-party resources, are
 copyrighted to their authors with all rights reserved.

@@ -32,7 +30,4 @@ Authors of this addon hereby grant you the following rights:
 All rights not explicitly addressed in this license are reserved by
 the copyright holders.

-You can write Munglunch at Wowinterface.com for reporting abuse / bugs.
-
-You can contact Elv at Tukui.org for details regarding
-grants allowed for this license.
\ No newline at end of file
+You can write Munglunch at Wowinterface.com for reporting abuse / bugs.
\ No newline at end of file
diff --git a/Interface/AddOns/SVUI_ConfigOMatic/components/units/grid.lua b/Interface/AddOns/SVUI_ConfigOMatic/components/units/grid.lua
index 437b795..85a97b7 100644
--- a/Interface/AddOns/SVUI_ConfigOMatic/components/units/grid.lua
+++ b/Interface/AddOns/SVUI_ConfigOMatic/components/units/grid.lua
@@ -49,7 +49,7 @@ SV.Options.args.SVUnit.args.grid = {
 			order = 1,
 			type = "execute",
 			name = L["Display Frames"],
-			func = function()MOD:UpdateGroupConfig(_G["SVUI_Raid"], _G["SVUI_Raid"].forceShow ~= true or nil, "raid40")end,
+			func = function()MOD:ViewGroupFrames(_G["SVUI_Raid40"], _G["SVUI_Raid40"].forceShow ~= true or nil)end,
 		},
 		gridCommon = {
 			order = 2,
@@ -112,7 +112,7 @@ SV.Options.args.SVUnit.args.grid = {
 					name = L['Party Grid'],
 					desc = L['If grid-mode is enabled, these units will be changed.'],
 					get = function(key) return SV.db.SVUnit.party.gridAllowed end,
-					set = function(key, value) SV.db.SVUnit.party.gridAllowed = value; MOD:SetPartyGroup() end,
+					set = function(key, value) SV.db.SVUnit.party.gridAllowed = value; MOD:SetGroupFrame("party") end,
 				},
 				partypets = {
 					type = 'toggle',
@@ -120,7 +120,7 @@ SV.Options.args.SVUnit.args.grid = {
 					name = L['Party Pets Grid'],
 					desc = L['If grid-mode is enabled, these units will be changed.'],
 					get = function(key) return SV.db.SVUnit.party.petsGroup.gridAllowed end,
-					set = function(key, value) SV.db.SVUnit.party.petsGroup.gridAllowed = value; MOD:SetPartyGroup() end,
+					set = function(key, value) SV.db.SVUnit.party.petsGroup.gridAllowed = value; MOD:SetGroupFrame("party") end,
 				},
 				partytargets = {
 					type = 'toggle',
@@ -128,23 +128,39 @@ SV.Options.args.SVUnit.args.grid = {
 					name = L['Party Targets Grid'],
 					desc = L['If grid-mode is enabled, these units will be changed.'],
 					get = function(key) return SV.db.SVUnit.party.targetsGroup.gridAllowed end,
-					set = function(key, value) SV.db.SVUnit.party.targetsGroup.gridAllowed = value; MOD:SetPartyGroup() end,
+					set = function(key, value) SV.db.SVUnit.party.targetsGroup.gridAllowed = value; MOD:SetGroupFrame("party") end,
 				},
-				raid = {
+				raid10 = {
 					type = 'toggle',
 					order = 4,
-					name = L['Raid Grid'],
+					name = L['Raid 10 Grid'],
 					desc = L['If grid-mode is enabled, these units will be changed.'],
-					get = function(key) return SV.db.SVUnit.raid.gridAllowed end,
-					set = function(key, value) SV.db.SVUnit.raid.gridAllowed = value; MOD:SetRaidGroup("raid10"); MOD:SetRaidGroup("raid25"); MOD:SetRaidGroup("raid40") end,
+					get = function(key) return SV.db.SVUnit.raid10.gridAllowed end,
+					set = function(key, value) SV.db.SVUnit.raid10.gridAllowed = value; MOD:SetGroupFrame("raid10") end,
 				},
-				raidpet = {
+				raid25 = {
 					type = 'toggle',
 					order = 5,
+					name = L['Raid 25 Grid'],
+					desc = L['If grid-mode is enabled, these units will be changed.'],
+					get = function(key) return SV.db.SVUnit.raid25.gridAllowed end,
+					set = function(key, value) SV.db.SVUnit.raid25.gridAllowed = value; MOD:SetGroupFrame("raid25") end,
+				},
+				raid40 = {
+					type = 'toggle',
+					order = 6,
+					name = L['Raid 40 Grid'],
+					desc = L['If grid-mode is enabled, these units will be changed.'],
+					get = function(key) return SV.db.SVUnit.raid40.gridAllowed end,
+					set = function(key, value) SV.db.SVUnit.raid40.gridAllowed = value; MOD:SetGroupFrame("raid40") end,
+				},
+				raidpet = {
+					type = 'toggle',
+					order = 4,
 					name = L['Raid Pet Grid'],
 					desc = L['If grid-mode is enabled, these units will be changed.'],
 					get = function(key) return SV.db.SVUnit.raidpet.gridAllowed end,
-					set = function(key, value) SV.db.SVUnit.raidpet.gridAllowed = value; MOD:SetRaidPetGroup() end,
+					set = function(key, value) SV.db.SVUnit.raidpet.gridAllowed = value; MOD:SetGroupFrame("raidpet") end,
 				},
 			}
 		},
diff --git a/Interface/AddOns/SVUI_ConfigOMatic/components/units/other.lua b/Interface/AddOns/SVUI_ConfigOMatic/components/units/other.lua
index 8a6b9c6..983463e 100644
--- a/Interface/AddOns/SVUI_ConfigOMatic/components/units/other.lua
+++ b/Interface/AddOns/SVUI_ConfigOMatic/components/units/other.lua
@@ -48,7 +48,7 @@ SV.Options.args.SVUnit.args.boss = {
 	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "boss");MOD:SetEnemyFrames("boss", MAX_BOSS_FRAMES)end,
 	args = {
 		enable = {type = "toggle", order = 1, name = L["Enable"]},
-		displayFrames = {type = "execute", order = 2, name = L["Display Frames"], desc = L["Force the frames to show, they will act as if they are the player frame."], func = function()MOD:SwapElement("boss", 4)end},
+		displayFrames = {type = "execute", order = 2, name = L["Display Frames"], desc = L["Force the frames to show, they will act as if they are the player frame."], func = function()MOD:ViewEnemyFrames("boss", 4)end},
 		resetSettings = {type = "execute", order = 3, name = L["Restore Defaults"], func = function(l, m)MOD:ResetUnitOptions("boss")SV.Mentalo:Reset("Boss Frames")end},
 		tabGroups = {
 			order = 3,
@@ -117,7 +117,7 @@ SV.Options.args.SVUnit.args.arena = {
 	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "arena");MOD:SetEnemyFrames("arena", 5)end,
 	args = {
 		enable = {type = "toggle", order = 1, name = L["Enable"]},
-		displayFrames = {type = "execute", order = 2, name = L["Display Frames"], desc = L["Force the frames to show, they will act as if they are the player frame."], func = function()MOD:SwapElement("arena", 5)end},
+		displayFrames = {type = "execute", order = 2, name = L["Display Frames"], desc = L["Force the frames to show, they will act as if they are the player frame."], func = function()MOD:ViewEnemyFrames("arena", 5)end},
 		resetSettings = {type = "execute", order = 3, name = L["Restore Defaults"], func = function(l, m)MOD:ResetUnitOptions("arena")SV.Mentalo:Reset("Arena Frames")end},
 		tabGroups = {
 			order = 3,
@@ -285,7 +285,7 @@ SV.Options.args.SVUnit.args.tank = {
 	order = 1200,
 	childGroups = "tab",
 	get = function(l)return SV.db.SVUnit["tank"][l[#l]]end,
-	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "tank");MOD:SetTankAssistFrame("tank")end,
+	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "tank");MOD:SetGroupFrame("tank")end,
 	args = {
 		enable = {type = "toggle", order = 1, name = L["Enable"]},
 		resetSettings = {type = "execute", order = 2, name = L["Restore Defaults"], func = function(l, m)MOD:ResetUnitOptions("tank")end},
@@ -310,7 +310,7 @@ SV.Options.args.SVUnit.args.tank = {
 					name = L["Tank Target"],
 					guiInline = true,
 					get = function(l)return SV.db.SVUnit["tank"]["targetsGroup"][l[#l]]end,
-					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "tank", "targetsGroup");MOD:SetTankAssistFrame("tank")end,
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "tank", "targetsGroup");MOD:SetGroupFrame("tank")end,
 					args = {
 						enable = {type = "toggle", name = L["Enable"], order = 1},
 						width = {order = 2, name = L["Width"], type = "range", min = 10, max = 500, step = 1},
@@ -335,7 +335,7 @@ SV.Options.args.SVUnit.args.assist = {
 	order = 1300,
 	childGroups = "tab",
 	get = function(l)return SV.db.SVUnit["assist"][l[#l]]end,
-	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "assist");MOD:SetTankAssistFrame("assist")end,
+	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "assist");MOD:SetGroupFrame("assist")end,
 	args = {
 		enable = {type = "toggle", order = 1, name = L["Enable"]},
 		resetSettings = {type = "execute", order = 2, name = L["Restore Defaults"], func = function(l, m)MOD:ResetUnitOptions("assist")end},
@@ -360,7 +360,7 @@ SV.Options.args.SVUnit.args.assist = {
 					name = L["Assist Target"],
 					guiInline = true,
 					get = function(l)return SV.db.SVUnit["assist"]["targetsGroup"][l[#l]]end,
-					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "assist", "targetsGroup");MOD:SetTankAssistFrame("assist")end,
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "assist", "targetsGroup");MOD:SetGroupFrame("assist")end,
 					args = {
 						enable = {type = "toggle", name = L["Enable"], order = 1},
 						width = {order = 2, name = L["Width"], type = "range", min = 10, max = 500, step = 1},
diff --git a/Interface/AddOns/SVUI_ConfigOMatic/components/units/party.lua b/Interface/AddOns/SVUI_ConfigOMatic/components/units/party.lua
index 9b99e0d..2ca39ac 100644
--- a/Interface/AddOns/SVUI_ConfigOMatic/components/units/party.lua
+++ b/Interface/AddOns/SVUI_ConfigOMatic/components/units/party.lua
@@ -42,7 +42,7 @@ SV.Options.args.SVUnit.args.party = {
 	childGroups = "tab",
 	get = function(l)return
 	SV.db.SVUnit['party'][l[#l]]end,
-	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetPartyGroup('party')end,
+	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party')end,
 	args = {
 		enable = {
 			type = 'toggle',
@@ -54,7 +54,7 @@ SV.Options.args.SVUnit.args.party = {
 			type = 'execute',
 			name = L['Display Frames'],
 			func = function()
-				MOD:UpdateGroupConfig(SVUI_Party, SVUI_Party.forceShow ~= true or nil)
+				MOD:ViewGroupFrames(SVUI_Party, SVUI_Party.forceShow ~= true or nil)
 			end,
 		},
 		resetSettings = {
@@ -74,21 +74,13 @@ SV.Options.args.SVUnit.args.party = {
 					type = 'group',
 					name = L['General'],
 					args = {
-						showPlayer = {
-							order = 1,
-							type = 'toggle',
-							name = L['Display Player'],
-							desc = L['When true, always show player in party frames'],
-							get = function(l)return SV.db.SVUnit.party.showPlayer end,
-							set = function(l, m) MOD:ChangeDBVar(m, l[#l], "party"); MOD:SetPartyGroup("party", true) end,
-						},
 						hideonnpc = {
 							type = 'toggle',
 							order = 2,
 							name = L['Text Toggle On NPC'],
 							desc = L['Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point.'],
 							get = function(l)return SV.db.SVUnit['party']['power'].hideonnpc end,
-							set = function(l, m)SV.db.SVUnit['party']['power'].hideonnpc = m;MOD:SetPartyGroup('party')end,
+							set = function(l, m)SV.db.SVUnit['party']['power'].hideonnpc = m;MOD:SetGroupFrame('party')end,
 						},
 						rangeCheck = {
 							order = 3,
@@ -129,7 +121,7 @@ SV.Options.args.SVUnit.args.party = {
 							name = L['Size and Positions'],
 							type = 'group',
 							guiInline = true,
-							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetPartyGroup('party', true)end,
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party', nil, nil, true)end,
 							args = {
 								width = {
 									order = 1,
@@ -138,7 +130,7 @@ SV.Options.args.SVUnit.args.party = {
 									min = 10,
 									max = 500,
 									step = 1,
-									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetPartyGroup('party')end,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party')end,
 								},
 								height = {
 									order = 2,
@@ -147,7 +139,7 @@ SV.Options.args.SVUnit.args.party = {
 									min = 10,
 									max = 500,
 									step = 1,
-									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetPartyGroup('party')end,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party')end,
 								},
 								spacer = {
 									order = 3,
@@ -171,16 +163,48 @@ SV.Options.args.SVUnit.args.party = {
 										LEFT_UP = format(L['%s and then %s'], L['Left'], L['Up']),
 									},
 								},
-								wrapXOffset = {
+								groupCount = {
 									order = 5,
 									type = 'range',
+									name = L['Number of Groups'],
+									min = 1,
+									max = 8,
+									step = 1,
+									set = function(l, m)
+										MOD:ChangeDBVar(m, l[#l], "party");
+										MOD:SetGroupFrame('party')
+										if SVUI_Party.isForced then
+											MOD:ViewGroupFrames(SVUI_Party)
+											MOD:ViewGroupFrames(SVUI_Party, true)
+										end
+									end,
+								},
+								gRowCol = {
+									order = 6,
+									type = 'range',
+									name = L['Groups Per Row/Column'],
+									min = 1,
+									max = 8,
+									step = 1,
+									set = function(l, m)
+										MOD:ChangeDBVar(m, l[#l], "party");
+										MOD:SetGroupFrame('party')
+										if SVUI_Party.isForced then
+											MOD:ViewGroupFrames(SVUI_Party)
+											MOD:ViewGroupFrames(SVUI_Party, true)
+										end
+									end,
+								},
+								wrapXOffset = {
+									order = 7,
+									type = 'range',
 									name = L['Horizontal Spacing'],
 									min = 0,
 									max = 50,
 									step = 1,
 								},
 								wrapYOffset = {
-									order = 6,
+									order = 8,
 									type = 'range',
 									name = L['Vertical Spacing'],
 									min = 0,
@@ -189,12 +213,35 @@ SV.Options.args.SVUnit.args.party = {
 								},
 							},
 						},
+						visibilityGroup = {
+							order = 200,
+							name = L['Visibility'],
+							type = 'group',
+							guiInline = true,
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party', nil, nil, true)end,
+							args = {
+								showPlayer = {
+									order = 1,
+									type = 'toggle',
+									name = L['Display Player'],
+									desc = L['When true, the header includes the player when not in a raid.'],
+								},
+								visibility = {
+									order = 2,
+									type = 'input',
+									name = L['Visibility'],
+									desc = L['The following macro must be true in order for the group to be shown, in addition to any filter that may already be set.'],
+									width = 'full',
+									desc = L['TEXT_FORMAT_DESC'],
+								},
+							},
+						},
 						sortingGroup = {
 							order = 300,
 							type = 'group',
 							guiInline = true,
 							name = L['Grouping & Sorting'],
-							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetPartyGroup('party', true)end,
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party");MOD:SetGroupFrame('party', nil, nil, true)end,
 							args = {
 								sortMethod = {
 									order = 1,
@@ -227,13 +274,26 @@ SV.Options.args.SVUnit.args.party = {
 									width = 'full',
 									name = ' ',
 								},
-								invertGroupingOrder = {
+								customSorting = {
 									order = 4,
+									name = L['Custom Sorting'],
+									desc = L['Enabling this allows unique sorting.'],
+									type = 'toggle',
+								},
+								invertGroupingOrder = {
+									order = 5,
 									name = L['Invert Grouping Order'],
 									desc = L['Enabling this inverts the sorting order.'],
 									disabled = function()return not SV.db.SVUnit['party'].customSorting end,
 									type = 'toggle',
 								},
+								startFromCenter = {
+									order = 6,
+									name = L['Start Near Center'],
+									desc = L['The initial group will start near the center and grow out.'],
+									disabled = function()return not SV.db.SVUnit['party'].customSorting end,
+									type = 'toggle',
+								},
 							},
 						},

@@ -245,7 +305,7 @@ SV.Options.args.SVUnit.args.party = {
 					name = L['Aura Watch'],
 					get = function(l)return
 					SV.db.SVUnit['party']['auraWatch'][l[#l]]end,
-					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "auraWatch");MOD:SetPartyGroup('party')end,
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "auraWatch");MOD:SetGroupFrame('party')end,
 					args = {
 						enable = {
 							type = 'toggle',
@@ -270,19 +330,19 @@ SV.Options.args.SVUnit.args.party = {

 					},
 				},
-				misc = ns:SetMiscConfigGroup(true, MOD.SetPartyGroup, 'party'),
-				health = ns:SetHealthConfigGroup(true, MOD.SetPartyGroup, 'party'),
-				power = ns:SetPowerConfigGroup(false, MOD.SetPartyGroup, 'party'),
-				name = ns:SetNameConfigGroup(MOD.SetPartyGroup, 'party'),
-				portrait = ns:SetPortraitConfigGroup(MOD.SetPartyGroup, 'party'),
-				buffs = ns:SetAuraConfigGroup(true, 'buffs', true, MOD.SetPartyGroup, 'party'),
-				debuffs = ns:SetAuraConfigGroup(true, 'debuffs', true, MOD.SetPartyGroup, 'party'),
+				misc = ns:SetMiscConfigGroup(true, MOD.SetGroupFrame, 'party'),
+				health = ns:SetHealthConfigGroup(true, MOD.SetGroupFrame, 'party'),
+				power = ns:SetPowerConfigGroup(false, MOD.SetGroupFrame, 'party'),
+				name = ns:SetNameConfigGroup(MOD.SetGroupFrame, 'party'),
+				portrait = ns:SetPortraitConfigGroup(MOD.SetGroupFrame, 'party'),
+				buffs = ns:SetAuraConfigGroup(true, 'buffs', true, MOD.SetGroupFrame, 'party'),
+				debuffs = ns:SetAuraConfigGroup(true, 'debuffs', true, MOD.SetGroupFrame, 'party'),
 				petsGroup = {
 					order = 800,
 					type = 'group',
 					name = L['Party Pets'],
 					get = function(l)return SV.db.SVUnit['party']['petsGroup'][l[#l]]end,
-					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "petsGroup");MOD:SetPartyGroup('party')end,
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "petsGroup");MOD:SetGroupFrame('party')end,
 					args = {
 						enable = {
 							type = 'toggle',
@@ -353,7 +413,7 @@ SV.Options.args.SVUnit.args.party = {
 					name = L['Party Targets'],
 					get = function(l)return
 					SV.db.SVUnit['party']['targetsGroup'][l[#l]]end,
-					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "targetsGroup");MOD:SetPartyGroup('party')end,
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "party", "targetsGroup");MOD:SetGroupFrame('party')end,
 					args = {
 						enable = {
 							type = 'toggle',
@@ -418,7 +478,7 @@ SV.Options.args.SVUnit.args.party = {
 						}
 					},
 				},
-				icons = ns:SetIconConfigGroup(MOD.SetPartyGroup, 'party')
+				icons = ns:SetIconConfigGroup(MOD.SetGroupFrame, 'party')
 			}
 		}
 	},
diff --git a/Interface/AddOns/SVUI_ConfigOMatic/components/units/raid.lua b/Interface/AddOns/SVUI_ConfigOMatic/components/units/raid.lua
index 34dcef4..035abbf 100644
--- a/Interface/AddOns/SVUI_ConfigOMatic/components/units/raid.lua
+++ b/Interface/AddOns/SVUI_ConfigOMatic/components/units/raid.lua
@@ -35,48 +35,34 @@ local MOD = SV.SVUnit
 if(not MOD) then return end
 local _, ns = ...

-local RaidCategories = {
-	[10] = "Raid (10)",
-	[25] = "Raid (15,20,25)",
-	[40] = "Raid (40)",
-}
-
 local subOrder = 11;
-for w=10,40,15 do
-	local raidToken = ("raid%d"):format(w)
-	local raidGlobal = ("SVUI_Raid%d"):format(w)
+for w=10,40,15 do
 	subOrder = subOrder + 1
-	SV.Options.args.SVUnit.args[raidToken] = {
-		name = RaidCategories[w],
+	SV.Options.args.SVUnit.args["raid" .. w] = {
+		name = L["Raid-" .. w .. " Frames"],
 		type = "group",
 		order = subOrder,
 		childGroups = "tab",
-		get = function(l) return SV.db.SVUnit[raidToken][l[#l]] end,
-		set = function(l, m) MOD:ChangeDBVar(m, l[#l], raidToken); MOD:SetRaidGroup(raidToken) end,
+		get = function(l) return SV.db.SVUnit["raid" .. w][l[#l]] end,
+		set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w)end,
 		args = {
 			enable =
 			{
 				type = "toggle",
 				order = 1,
-				name = L["Enable"],
-				get = function(l) return SV.db.SVUnit.raid.enable end,
-				set = function(l, m) SV.db.SVUnit.raid.enable = m; MOD:SetRaidGroup(raidToken) end,
+				name = L["Enable"],
 			},
 			configureToggle = {
 				order = 2,
 				type = "execute",
 				name = L["Display Frames"],
-				func = function()
-					local setForced = (_G[raidGlobal].forceShow ~= true) or nil;
-					local token = setForced and raidToken or nil
-					MOD:UpdateGroupConfig(_G[raidGlobal], setForced, token)
-				end,
+				func = function()MOD:ViewGroupFrames(_G["SVUI_Raid" .. w], _G["SVUI_Raid" .. w].forceShow ~= true or nil)end,
 			},
 			resetSettings = {
 				type = "execute",
 				order = 3,
 				name = L["Restore Defaults"],
-				func = function(l, m)MOD:ResetUnitOptions(raidToken) SV.Mentalo:Reset("Raid Frames") end,
+				func = function(l, m)MOD:ResetUnitOptions("raid" .. w)SV.Mentalo:Reset("Raid 1-" .. w .. " Frames")end,
 			},
 			tabGroups = {
 				order = 3,
@@ -89,49 +75,40 @@ for w=10,40,15 do
 						type = "group",
 						name = L["General Settings"],
 						args = {
-							showPlayer =
-							{
-								order = 1,
-								type = "toggle",
-								name = L["Display Player"],
-								desc = L["When true, always show player in raid frames."],
-								get = function(l)return SV.db.SVUnit[raidToken].showPlayer end,
-								set = function(l, m) MOD:ChangeDBVar(m, l[#l], raidToken); MOD:SetRaidGroup(raidToken, true) end,
-							},
 							hideonnpc =
 							{
 								type = "toggle",
-								order = 2,
+								order = 1,
 								name = L["Text Toggle On NPC"],
 								desc = L["Power text will be hidden on NPC targets, in addition the name text will be repositioned to the power texts anchor point."],
-								get = function(l)return SV.db.SVUnit[raidToken]["power"].hideonnpc end,
-								set = function(l, m) SV.db.SVUnit[raidToken]["power"].hideonnpc = m; MOD:SetRaidGroup(raidToken)end,
+								get = function(l)return SV.db.SVUnit["raid" .. w]["power"].hideonnpc end,
+								set = function(l, m)SV.db.SVUnit["raid" .. w]["power"].hideonnpc = m;MOD:SetGroupFrame("raid" .. w)end,
 							},
 							rangeCheck = {
-								order = 3,
+								order = 2,
 								name = L["Range Check"],
 								desc = L["Check if you are in range to cast spells on this specific unit."],
 								type = "toggle",
 							},
 							gps = {
-								order = 4,
+								order = 3,
 								name = "GPS Tracking",
 								desc = "Show an arrow giving the direction and distance to the frames unit.",
 								type = "toggle",
 							},
 							predict = {
-								order = 5,
+								order = 4,
 								name = L["Heal Prediction"],
 								desc = L["Show a incomming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals."],
 								type = "toggle",
 							},
 							threatEnabled = {
 								type = "toggle",
-								order = 6,
+								order = 5,
 								name = L["Show Threat"],
 							},
 							colorOverride = {
-								order = 7,
+								order = 6,
 								name = L["Class Color Override"],
 								desc = L["Override the default class color setting."],
 								type = "select",
@@ -147,7 +124,7 @@ for w=10,40,15 do
 								name = L["Size and Positions"],
 								type = "group",
 								guiInline = true,
-								set = function(l, m)MOD:ChangeDBVar(m, l[#l], raidToken);MOD:SetRaidGroup(raidToken, true)end,
+								set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w, nil, nil, true)end,
 								args =
 								{
 									width =
@@ -158,7 +135,7 @@ for w=10,40,15 do
 										min = 10,
 										max = 500,
 										step = 1,
-										set = function(l, m)MOD:ChangeDBVar(m, l[#l], raidToken);MOD:SetRaidGroup(raidToken)end,
+										set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w)end,
 									},
 									height =
 									{
@@ -168,7 +145,7 @@ for w=10,40,15 do
 										min = 10,
 										max = 500,
 										step = 1,
-										set = function(l, m)MOD:ChangeDBVar(m, l[#l], raidToken);MOD:SetRaidGroup(raidToken)end,
+										set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w)end,
 									},
 									spacer =
 									{
@@ -194,27 +171,44 @@ for w=10,40,15 do
 											LEFT_DOWN = format(L["%s and then %s"], L["Left"], L["Down"]),
 											LEFT_UP = format(L["%s and then %s"], L["Left"], L["Up"]),
 										},
-									},
-									gRowCol =
+									},
+									groupCount =
 									{
 										order = 5,
 										type = "range",
+										name = L["Number of Groups"],
+										min = 1,
+										max = 8,
+										step = 1,
+										set = function(l, m)
+											MOD:ChangeDBVar(m, l[#l], "raid" .. w);
+											MOD:SetGroupFrame("raid" .. w)
+											if _G["SVUI_Raid" .. w].isForced then
+												MOD:ViewGroupFrames(_G["SVUI_Raid" .. w])
+												MOD:ViewGroupFrames(_G["SVUI_Raid" .. w], true)
+											end
+										end,
+									},
+									gRowCol =
+									{
+										order = 6,
+										type = "range",
 										name = L["Groups Per Row / Column"],
 										min = 1,
 										max = 8,
 										step = 1,
 										set = function(l, m)
-											MOD:ChangeDBVar(m, l[#l], raidToken);
-											MOD:SetRaidGroup(raidToken)
-											if(_G[raidGlobal] and _G[raidGlobal].isForced) then
-												MOD:UpdateGroupConfig(_G[raidGlobal])
-												MOD:UpdateGroupConfig(_G[raidGlobal], true)
+											MOD:ChangeDBVar(m, l[#l], "raid" .. w);
+											MOD:SetGroupFrame("raid" .. w)
+											if _G["SVUI_Raid" .. w].isForced then
+												MOD:ViewGroupFrames(_G["SVUI_Raid" .. w])
+												MOD:ViewGroupFrames(_G["SVUI_Raid" .. w], true)
 											end
 										end,
 									},
 									wrapXOffset =
 									{
-										order = 6,
+										order = 7,
 										type = "range",
 										name = L["Horizontal Spacing"],
 										min = 0,
@@ -223,7 +217,7 @@ for w=10,40,15 do
 									},
 									wrapYOffset =
 									{
-										order = 7,
+										order = 8,
 										type = "range",
 										name = L["Vertical Spacing"],
 										min = 0,
@@ -231,13 +225,39 @@ for w=10,40,15 do
 										step = 1,
 									},
 								},
-							},
+							},
+							visibilityGroup = {
+								order = 200,
+								name = L["Visibility"],
+								type = "group",
+								guiInline = true,
+								set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w, nil, nil, true)end,
+								args =
+								{
+									showPlayer =
+									{
+										order = 1,
+										type = "toggle",
+										name = L["Display Player"],
+										desc = L["When true, the header includes the player when not in a raid."],
+									},
+									visibility =
+									{
+										order = 2,
+										type = "input",
+										name = L["Visibility"],
+										desc = L["The following macro must be true in order for the group to be shown, in addition to any filter that may already be set."],
+										width = "full",
+										desc = L["TEXT_FORMAT_DESC"],
+									},
+								},
+							},
 							sortingGroup = {
 								order = 300,
 								type = "group",
 								guiInline = true,
 								name = L["Sorting"],
-								set = function(l, m)MOD:ChangeDBVar(m, l[#l], raidToken);MOD:SetRaidGroup(raidToken, true)end,
+								set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w);MOD:SetGroupFrame("raid" .. w, nil, nil, true)end,
 								args =
 								{
 									sortMethod =
@@ -276,25 +296,40 @@ for w=10,40,15 do
 										type = "description",
 										width = "full",
 										name = " ",
-									},
-									invertGroupingOrder =
+									},
+									customSorting =
 									{
 										order = 4,
+										name = L["Raid-Wide Sorting"],
+										desc = L["Enabling this allows raid-wide sorting however you will not be able to distinguish between groups."],
+										type = "toggle",
+									},
+									invertGroupingOrder =
+									{
+										order = 5,
 										name = L["Invert Grouping Order"],
 										desc = L["Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from."],
-										disabled = function()return not SV.db.SVUnit[raidToken].customSorting end,
+										disabled = function()return not SV.db.SVUnit["raid" .. w].customSorting end,
+										type = "toggle",
+									},
+									startFromCenter =
+									{
+										order = 6,
+										name = L["Start Near Center"],
+										desc = L["The initial group will start near the center and grow out."],
+										disabled = function()return not SV.db.SVUnit["raid" .. w].customSorting end,
 										type = "toggle",
-									},
+									},
 								},
 							}
 						}
 					},
-					misc = ns:SetMiscConfigGroup(true, MOD.SetRaidGroup, raidToken),
-					health = ns:SetHealthConfigGroup(true, MOD.SetRaidGroup, raidToken),
-					power = ns:SetPowerConfigGroup(false, MOD.SetRaidGroup, raidToken),
-					name = ns:SetNameConfigGroup(MOD.SetRaidGroup, raidToken),
-					buffs = ns:SetAuraConfigGroup(true, "buffs", true, MOD.SetRaidGroup, raidToken),
-					debuffs = ns:SetAuraConfigGroup(true, "debuffs", true, MOD.SetRaidGroup, raidToken),
+					misc = ns:SetMiscConfigGroup(true, MOD.SetGroupFrame, "raid" .. w),
+					health = ns:SetHealthConfigGroup(true, MOD.SetGroupFrame, "raid" .. w),
+					power = ns:SetPowerConfigGroup(false, MOD.SetGroupFrame, "raid" .. w),
+					name = ns:SetNameConfigGroup(MOD.SetGroupFrame, "raid" .. w),
+					buffs = ns:SetAuraConfigGroup(true, "buffs", true, MOD.SetGroupFrame, "raid" .. w),
+					debuffs = ns:SetAuraConfigGroup(true, "debuffs", true, MOD.SetGroupFrame, "raid" .. w),
 					auraWatch = {
 						order = 600,
 						type = "group",
@@ -304,8 +339,8 @@ for w=10,40,15 do
 								type = "toggle",
 								name = L["Enable"],
 								order = 1,
-								get = function(l)return SV.db.SVUnit[raidToken].auraWatch.enable end,
-								set = function(l, m)MOD:ChangeDBVar(m, "enable", raidToken, "auraWatch");MOD:SetRaidGroup(raidToken)end,
+								get = function(l)return SV.db.SVUnit["raid" .. w].auraWatch.enable end,
+								set = function(l, m)MOD:ChangeDBVar(m, "enable", "raid" .. w, "auraWatch");MOD:SetGroupFrame("raid" .. w)end,
 							},
 							size = {
 								type = "range",
@@ -315,8 +350,8 @@ for w=10,40,15 do
 								min = 4,
 								max = 15,
 								step = 1,
-								get = function(l)return SV.db.SVUnit[raidToken].auraWatch.size end,
-								set = function(l, m)MOD:ChangeDBVar(m, "size", raidToken, "auraWatch");MOD:SetRaidGroup(raidToken)end,
+								get = function(l)return SV.db.SVUnit["raid" .. w].auraWatch.size end,
+								set = function(l, m)MOD:ChangeDBVar(m, "size", "raid" .. w, "auraWatch");MOD:SetGroupFrame("raid" .. w)end,
 							},
 							configureButton = {
 								type = "execute",
@@ -332,8 +367,8 @@ for w=10,40,15 do
 						type = "group",
 						name = L["RaidDebuff Indicator"],
 						get = function(l)return
-						SV.db.SVUnit[raidToken]["rdebuffs"][l[#l]]end,
-						set = function(l, m)MOD:ChangeDBVar(m, l[#l], raidToken, "rdebuffs");MOD:SetRaidGroup(raidToken)end,
+						SV.db.SVUnit["raid" .. w]["rdebuffs"][l[#l]]end,
+						set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raid" .. w, "rdebuffs");MOD:SetGroupFrame("raid" .. w)end,
 						args = {
 							enable = {
 								type = "toggle",
@@ -380,7 +415,7 @@ for w=10,40,15 do
 							},
 						},
 					},
-					icons = ns:SetIconConfigGroup(MOD.SetRaidGroup, raidToken),
+					icons = ns:SetIconConfigGroup(MOD.SetGroupFrame, "raid" .. w),
 				},
 			},
 		},
@@ -388,108 +423,108 @@ for w=10,40,15 do
 end

 subOrder = subOrder + 1
-SV.Options.args.SVUnit.args.raidpet = {
+SV.Options.args.SVUnit.args.raidpet ={
 	order = subOrder,
 	type = 'group',
 	name = L['Raid Pet Frames'],
 	childGroups = "tab",
 	get = function(l)return
 	SV.db.SVUnit['raidpet'][l[#l]]end,
-	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet')end,
-	args = {
-		enable = {
+	set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet')end,
+	args ={
+		enable ={
 			type = 'toggle',
 			order = 1,
 			name = L['Enable'],
 		},
-		configureToggle = {
+		configureToggle ={
 			order = 2,
 			type = 'execute',
 			name = L['Display Frames'],
-			func = function()MOD:UpdateGroupConfig(SVUI_Raidpet, SVUI_Raidpet.forceShow ~= true or nil)end,
+			func = function()MOD:ViewGroupFrames(SVUI_Raidpet, SVUI_Raidpet.forceShow ~= true or nil)end,
 		},
-		resetSettings = {
+		resetSettings ={
 			type = 'execute',
 			order = 3,
 			name = L['Restore Defaults'],
-			func = function(l, m)MOD:ResetUnitOptions('raidpet')SV.Mentalo:Reset('Raid Pet Frames')MOD:SetRaidPetGroup('raidpet', true)end,
+			func = function(l, m)MOD:ResetUnitOptions('raidpet')SV.Mentalo:Reset('Raid Pet Frames')MOD:SetGroupFrame('raidpet', nil, nil, true)end,
 		},
-		tabGroups= {
+		tabGroups={
 			order=3,
 			type='group',
 			name=L['Unit Options'],
 			childGroups="tree",
-			args= {
-				commonGroup= {
+			args={
+				commonGroup={
 					order=1,
 					type='group',
 					name=L['General Settings'],
-					args= {
-						rangeCheck = {
+					args={
+						rangeCheck ={
 							order = 3,
 							name = L["Range Check"],
 							desc = L["Check if you are in range to cast spells on this specific unit."],
 							type = "toggle",
 						},
-						predict = {
+						predict ={
 							order = 4,
 							name = L['Heal Prediction'],
 							desc = L['Show a incomming heal prediction bar on the unitframe. Also display a slightly different colored bar for incoming overheals.'],
 							type = 'toggle',
 						},
-						threatEnabled = {
+						threatEnabled ={
 							type = 'toggle',
 							order = 5,
 							name = L['Show Threat'],
 						},
-						colorOverride = {
+						colorOverride ={
 							order = 6,
 							name = L['Class Color Override'],
 							desc = L['Override the default class color setting.'],
 							type = 'select',
-							values = {
+							values ={
 								['USE_DEFAULT'] = L['Use Default'],
 								['FORCE_ON'] = L['Force On'],
 								['FORCE_OFF'] = L['Force Off'],
 							},
 						},
-						positionsGroup = {
+						positionsGroup ={
 							order = 100,
 							name = L['Size and Positions'],
 							type = 'group',
 							guiInline = true,
-							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet', true)end,
-							args = {
-								width = {
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet', nil, nil, true)end,
+							args ={
+								width ={
 									order = 1,
 									name = L['Width'],
 									type = 'range',
 									min = 10,
 									max = 500,
 									step = 1,
-									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet')end,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet')end,
 								},
-								height = {
+								height ={
 									order = 2,
 									name = L['Height'],
 									type = 'range',
 									min = 10,
 									max = 500,
 									step = 1,
-									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet')end,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet')end,
 								},
-								spacer = {
+								spacer ={
 									order = 3,
 									name = '',
 									type = 'description',
 									width = 'full',
 								},
-								showBy = {
+								showBy ={
 									order = 4,
 									name = L['Growth Direction'],
 									desc = L['Growth direction from the first unitframe.'],
 									type = 'select',
-									values = {
+									values ={
 										DOWN_RIGHT = format(L['%s and then %s'], L['Down'], L['Right']),
 										DOWN_LEFT = format(L['%s and then %s'], L['Down'], L['Left']),
 										UP_RIGHT = format(L['%s and then %s'], L['Up'], L['Right']),
@@ -500,26 +535,36 @@ SV.Options.args.SVUnit.args.raidpet = {
 										LEFT_UP = format(L['%s and then %s'], L['Left'], L['Up']),
 									},
 								},
-								gRowCol = {
-									order = 5,
+								groupCount ={
+									order = 7,
+									type = 'range',
+									name = L['Number of Groups'],
+									min = 1,
+									max = 8,
+									step = 1,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet')if
+									SVUI_Raidpet.isForced then MOD:ViewGroupFrames(SVUI_Raidpet)MOD:ViewGroupFrames(SVUI_Raidpet, true)end end,
+								},
+								gRowCol ={
+									order = 8,
 									type = 'range',
 									name = L['Groups Per Row/Column'],
 									min = 1,
 									max = 8,
 									step = 1,
-									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet')if
-									SVUI_Raidpet.isForced then MOD:UpdateGroupConfig(SVUI_Raidpet)MOD:UpdateGroupConfig(SVUI_Raidpet, true)end end,
+									set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet')if
+									SVUI_Raidpet.isForced then MOD:ViewGroupFrames(SVUI_Raidpet)MOD:ViewGroupFrames(SVUI_Raidpet, true)end end,
 								},
-								wrapXOffset = {
-									order = 6,
+								wrapXOffset ={
+									order = 9,
 									type = 'range',
 									name = L['Horizontal Spacing'],
 									min = 0,
 									max = 50,
 									step = 1,
 								},
-								wrapYOffset = {
-									order = 7,
+								wrapYOffset ={
+									order = 10,
 									type = 'range',
 									name = L['Vertical Spacing'],
 									min = 0,
@@ -528,14 +573,14 @@ SV.Options.args.SVUnit.args.raidpet = {
 								},
 							},
 						},
-						visibilityGroup = {
+						visibilityGroup ={
 							order = 200,
 							name = L['Visibility'],
 							type = 'group',
 							guiInline = true,
-							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet', true)end,
-							args = {
-								visibility = {
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet', nil, nil, true)end,
+							args ={
+								visibility ={
 									order = 2,
 									type = 'input',
 									name = L['Visibility'],
@@ -545,67 +590,80 @@ SV.Options.args.SVUnit.args.raidpet = {
 								},
 							},
 						},
-						sortingGroup = {
+						sortingGroup ={
 							order = 300,
 							type = 'group',
 							guiInline = true,
 							name = L['Grouping & Sorting'],
-							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetRaidPetGroup('raidpet', true)end,
-							args = {
-								sortMethod = {
+							set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet");MOD:SetGroupFrame('raidpet', nil, nil, true)end,
+							args ={
+								sortMethod ={
 									order = 1,
 									name = L['Group By'],
 									desc = L['Set the order that the group will sort.'],
 									type = 'select',
-									values = {
+									values ={
 										['NAME'] = L['Owners Name'],
 										['PETNAME'] = L['Pet Name'],
 										['GROUP'] = GROUP,
 									},
 								},
-								sortDir = {
+								sortDir ={
 									order = 2,
 									name = L['Sort Direction'],
 									desc = L['Defines the sort order of the selected sort method.'],
 									type = 'select',
-									values = {
+									values ={
 										['ASC'] = L['Ascending'],
 										['DESC'] = L['Descending'],
 									},
 								},
-								spacer = {
+								spacer ={
 									order = 3,
 									type = 'description',
 									width = 'full',
 									name = ' ',
 								},
-								invertGroupingOrder = {
+								customSorting ={
 									order = 4,
+									name = L['Raid-Wide Sorting'],
+									desc = L['Enabling this allows raid-wide sorting however you will not be able to distinguish between groups.'],
+									type = 'toggle',
+								},
+								invertGroupingOrder ={
+									order = 5,
 									name = L['Invert Grouping Order'],
 									desc = L['Enabling this inverts the grouping order when the raid is not full, this will reverse the direction it starts from.'],
 									disabled = function()return not SV.db.SVUnit['raidpet'].customSorting end,
 									type = 'toggle',
 								},
+								startFromCenter ={
+									order = 6,
+									name = L['Start Near Center'],
+									desc = L['The initial group will start near the center and grow out.'],
+									disabled = function()return not SV.db.SVUnit['raidpet'].customSorting end,
+									type = 'toggle',
+								},
 							},
 						}
 					}
 				},
-				misc = ns:SetMiscConfigGroup(true, MOD.SetRaidPetGroup, 'raidpet'),
-				health = ns:SetHealthConfigGroup(true, MOD.SetRaidPetGroup, 'raidpet'),
-				name = ns:SetNameConfigGroup(MOD.SetRaidPetGroup, 'raidpet'),
-				buffs = ns:SetAuraConfigGroup(true, 'buffs', true, MOD.SetRaidPetGroup, 'raidpet'),
-				debuffs = ns:SetAuraConfigGroup(true, 'debuffs', true, MOD.SetRaidPetGroup, 'raidpet'),
-				auraWatch = {
+				misc = ns:SetMiscConfigGroup(true, MOD.SetGroupFrame, 'raidpet'),
+				health = ns:SetHealthConfigGroup(true, MOD.SetGroupFrame, 'raidpet'),
+				name = ns:SetNameConfigGroup(MOD.SetGroupFrame, 'raidpet'),
+				buffs = ns:SetAuraConfigGroup(true, 'buffs', true, MOD.SetGroupFrame, 'raidpet'),
+				debuffs = ns:SetAuraConfigGroup(true, 'debuffs', true, MOD.SetGroupFrame, 'raidpet'),
+				auraWatch ={
 					order = 600,
 					type = 'group',
 					name = L['Aura Watch'],
-					args = {
+					args ={
 						enable = {
 							type = "toggle",
 							name = L["Enable"],
 							order = 1,
 							get = function(l)return SV.db.SVUnit["raidpet"].auraWatch.enable end,
-							set = function(l, m)MOD:ChangeDBVar(m, "enable", "raidpet", "auraWatch");MOD:SetRaidPetGroup('raidpet')end,
+							set = function(l, m)MOD:ChangeDBVar(m, "enable", "raidpet", "auraWatch");MOD:SetGroupFrame("raidpet")end,
 						},
 						size = {
 							type = "range",
@@ -616,9 +674,9 @@ SV.Options.args.SVUnit.args.raidpet = {
 							max = 15,
 							step = 1,
 							get = function(l)return SV.db.SVUnit["raidpet"].auraWatch.size end,
-							set = function(l, m)MOD:ChangeDBVar(m, "size", "raidpet", "auraWatch");MOD:SetRaidPetGroup('raidpet')end,
+							set = function(l, m)MOD:ChangeDBVar(m, "size", "raidpet", "auraWatch");MOD:SetGroupFrame("raidpet")end,
 						},
-						configureButton = {
+						configureButton ={
 							type = 'execute',
 							name = L['Configure Auras'],
 							func = function()ns:SetToFilterConfig('BuffWatch')end,
@@ -626,20 +684,20 @@ SV.Options.args.SVUnit.args.raidpet = {
 						},
 					},
 				},
-				rdebuffs = {
+				rdebuffs ={
 					order = 700,
 					type = 'group',
 					name = L['RaidDebuff Indicator'],
 					get = function(l)return
 					SV.db.SVUnit['raidpet']['rdebuffs'][l[#l]]end,
-					set = function(l, m) MOD:ChangeDBVar(m, l[#l], "raidpet", "rdebuffs"); MOD:SetRaidPetGroup('raidpet')end,
-					args = {
-						enable = {
+					set = function(l, m)MOD:ChangeDBVar(m, l[#l], "raidpet", "rdebuffs");MOD:SetGroupFrame('raidpet')end,
+					args ={
+						enable ={
 							type = 'toggle',
 							name = L['Enable'],
 							order = 1,
 						},
-						size = {
+						size ={
 							type = 'range',
 							name = L['Size'],
 							order = 2,
@@ -647,7 +705,7 @@ SV.Options.args.SVUnit.args.raidpet = {
 							max = 35,
 							step = 1,
 						},
-						xOffset = {
+						xOffset ={
 							order = 3,
 							type = 'range',
 							name = L['xOffset'],
@@ -655,7 +713,7 @@ SV.Options.args.SVUnit.args.raidpet = {
 							max = 300,
 							step = 1,
 						},
-						yOffset = {
+						yOffset ={
 							order = 4,
 							type = 'range',
 							name = L['yOffset'],
@@ -663,7 +721,7 @@ SV.Options.args.SVUnit.args.raidpet = {
 							max = 300,
 							step = 1,
 						},
-						configureButton = {
+						configureButton ={
 							type = 'execute',
 							name = L['Configure Auras'],
 							func = function()ns:SetToFilterConfig('Raid')end,
@@ -671,7 +729,7 @@ SV.Options.args.SVUnit.args.raidpet = {
 						},
 					},
 				},
-				icons = ns:SetIconConfigGroup(MOD.SetRaidPetGroup, 'raidpet'),
+				icons = ns:SetIconConfigGroup(MOD.SetGroupFrame, 'raidpet'),
 			},
 		},
 	},
diff --git a/Interface/AddOns/SVUI_StyleOMatic/License.txt b/Interface/AddOns/SVUI_StyleOMatic/License.txt
index 25cfd6f..9b55de1 100644
--- a/Interface/AddOns/SVUI_StyleOMatic/License.txt
+++ b/Interface/AddOns/SVUI_StyleOMatic/License.txt
@@ -14,7 +14,7 @@

 SVUI_StyleOMatic SVUI License Copyright 2014 http://wowinterface.com

-(Adapted with permissions from AddOnSkins for ElvUI) Copyright 2014 Azilroka http://www.tukui.org
+(Adapted with permissions from AddOnSkins) Copyright 2014 Azilroka http://www.tukui.org

 The contents of this addon, excluding third-party resources, are
 copyrighted to their authors with all rights reserved.
diff --git a/Interface/AddOns/SVUI_StyleOMatic/components/blizzard/system.lua b/Interface/AddOns/SVUI_StyleOMatic/components/blizzard/system.lua
index 44a6456..020d00d 100644
--- a/Interface/AddOns/SVUI_StyleOMatic/components/blizzard/system.lua
+++ b/Interface/AddOns/SVUI_StyleOMatic/components/blizzard/system.lua
@@ -176,6 +176,7 @@ local SystemFrameList15 = {
 	"NamesPanelGuilds",
 	"NamesPanelGuildTitles",
 	"NamesPanelTitles",
+	"NamesPanelMinus",
 	"NamesPanelNonCombatCreature",
 	"NamesPanelEnemyPlayerNames",
 	"NamesPanelEnemyPets",
@@ -185,6 +186,7 @@ local SystemFrameList15 = {
 	"NamesPanelUnitNameplatesEnemies",
 	"NamesPanelUnitNameplatesEnemyGuardians",
 	"NamesPanelUnitNameplatesEnemyTotems",
+	"NamesPanelUnitNameplatesEnemyMinus",
 	"CombatTextPanelTargetDamage",
 	"CombatTextPanelPeriodicDamage",
 	"CombatTextPanelPetDamage",
@@ -206,6 +208,7 @@ local SystemFrameList15 = {
 	"CombatTextPanelPeriodicEnergyGains",
 	"CombatTextPanelHonorGains",
 	"CombatTextPanelAuras",
+	"CombatTextPanelPetBattle",
 	"BuffsPanelBuffDurations",
 	"BuffsPanelDispellableDebuffs",
 	"BuffsPanelCastableBuffs",
@@ -279,6 +282,7 @@ local SystemFrameList16 ={
 local SystemFrameList17 = {
 	"Advanced_MaxFPSCheckBox",
 	"Advanced_MaxFPSBKCheckBox",
+	"Advanced_DesktopGamma",
 	"Advanced_UseUIScale",
 	"AudioOptionsSoundPanelEnableSound",
 	"AudioOptionsSoundPanelSoundEffects",
@@ -296,6 +300,7 @@ local SystemFrameList17 = {
 	"AudioOptionsVoicePanelEnableVoice",
 	"AudioOptionsVoicePanelEnableMicrophone",
 	"AudioOptionsVoicePanelPushToTalkSound",
+	"AudioOptionsVoicePanelDialogVolume",
 	"AudioOptionsSoundPanelPetBattleMusic",
 	"NetworkOptionsPanelOptimizeSpeed",
 	"NetworkOptionsPanelUseIPv6",