Quantcast

friends changes

Munglunch [05-13-15 - 21:41]
friends changes
Filename
SVUI_!Core/system/_reports/friends.lua
SVUI_!Core/system/utilities.lua
diff --git a/SVUI_!Core/system/_reports/friends.lua b/SVUI_!Core/system/_reports/friends.lua
index d176ce2..90b87a7 100644
--- a/SVUI_!Core/system/_reports/friends.lua
+++ b/SVUI_!Core/system/_reports/friends.lua
@@ -3,7 +3,7 @@
 S V U I   By: Munglunch
 ##############################################################################

-##########################################################
+##########################################################
 LOCALIZED LUA FUNCTIONS
 ##########################################################
 ]]--
@@ -32,61 +32,27 @@ local gmatch, gsub = string.gmatch, string.gsub;
 local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;  -- Basic
 --[[ TABLE METHODS ]]--
 local wipe, sort = table.wipe, table.sort;
-
-local SetItemRef          	= _G.SetItemRef;
-local GetNumFriends         = _G.GetNumFriends;
-local BNGetNumFriends       = _G.BNGetNumFriends;
-local GetFriendInfo         = _G.GetFriendInfo;
-local BNGetFriendInfo       = _G.BNGetFriendInfo;
-local BNGetToonInfo         = _G.BNGetToonInfo;
-local GetRealmName          = _G.GetRealmName;
-local GetRealZoneText       = _G.GetRealZoneText;
-local InviteUnit            = _G.InviteUnit;
-local BNInviteFriend        = _G.BNInviteFriend;
-local BNSetCustomMessage    = _G.BNSetCustomMessage;
-local BNGetInfo          	= _G.BNGetInfo;
-local IsChatDND             = _G.IsChatDND;
-local IsChatAFK             = _G.IsChatAFK;
-local UnitInRaid            = _G.UnitInRaid;
-local UnitInParty           = _G.UnitInParty;
-local SendChatMessage       = _G.SendChatMessage;
-
-local AFK       = _G.AFK;
-local DND       = _G.DND;
-local GetQuestDifficultyColor 		= _G.GetQuestDifficultyColor;
-local LOCALIZED_CLASS_NAMES_MALE 	= _G.LOCALIZED_CLASS_NAMES_MALE;
-local LOCALIZED_CLASS_NAMES_FEMALE 	= _G.LOCALIZED_CLASS_NAMES_FEMALE;
-local WORLD_OF_WARCRAFT 			= _G.WORLD_OF_WARCRAFT;
-local BATTLENET_OPTIONS_LABEL 		= _G.BATTLENET_OPTIONS_LABEL;
-local BNET_CLIENT_WOW  				= _G.BNET_CLIENT_WOW;
-local BNET_CLIENT_SC2  				= _G.BNET_CLIENT_SC2;
-local BNET_CLIENT_D3  				= _G.BNET_CLIENT_D3;
-local BNET_CLIENT_WTCG  			= _G.BNET_CLIENT_WTCG;
-local RAID_CLASS_COLORS 			= _G.RAID_CLASS_COLORS
---[[
-##########################################################
+--[[
+##########################################################
 GET ADDON DATA
 ##########################################################
 ]]--
 local SV = select(2, ...)
 local L = SV.L
 local Reports = SV.Reports;
---[[
-##########################################################
+--[[
+##########################################################
 FRIENDS STATS
 ##########################################################
 ]]--
 local HEX_COLOR = "22FFFF";
 local TEXT_PATTERN1 = "%s: |cff%s%d|r";
 local TEXT_PATTERN2 = "|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r";
-local TEXT_PATTERN3 = "|cff%02x%02x%02x%d|r %s%s%s";
-local totalOnlineString = join("", FRIENDS_LIST_ONLINE, ": %s/%s");
-local statusTable = { "|cffFFFFFF[|r|cffFF0000"..L['AFK'].."|r|cffFFFFFF]|r", "|cffFFFFFF[|r|cffFF0000"..L['DND'].."|r|cffFFFFFF]|r", "" };
-local groupedTable = { "|cffaaaaaa*|r", "" };
-local friendTable, BNTable, BNTableWoW, BNTableD3, BNTableSC, BNTableWTCG = {}, {}, {}, {}, {}, {};
-local tableList = {[BNET_CLIENT_WOW] = BNTableWoW, [BNET_CLIENT_D3] = BNTableD3, [BNET_CLIENT_SC2] = BNTableSC, [BNET_CLIENT_WTCG] = BNTableWTCG};
-local friendOnline, friendOffline = gsub(ERR_FRIEND_ONLINE_SS,"\124Hplayer:%%s\124h%[%%s%]\124h",""), gsub(ERR_FRIEND_OFFLINE_S,"%%s","");
-local dataValid = false;
+local TEXT_PATTERN3 = "|cff%02x%02x%02x%d|r %s %s%s";
+local TEXT_PATTERN4 = FRIENDS_LIST_ONLINE .. ": %s/%s";
+local friendOnline, friendOffline = gsub(ERR_FRIEND_ONLINE_SS, "\124Hplayer:%%s\124h%[%%s%]\124h", ""), gsub(ERR_FRIEND_OFFLINE_S, "%%s", "");
+local FRIENDS_LIST_DIRTY = false;
+local FRIENDSLIST = {};

 SV.SystemAlert.SET_BN_BROADCAST={
 	text = BN_BROADCAST_TOOLTIP,
@@ -124,7 +90,7 @@ local menuList = {

 local function inviteClick(self, name)
 	menuFrame:Hide()
-
+
 	if type(name) ~= 'number' then
 		InviteUnit(name)
 	else
@@ -133,83 +99,13 @@ local function inviteClick(self, name)
 end

 local function whisperClick(self, name, battleNet)
-	menuFrame:Hide()
-
+	menuFrame:Hide()
+
 	if battleNet then
 		ChatFrame_SendSmartTell(name)
 	else
-		SetItemRef( "player:"..name, ("|Hplayer:%1$s|h[%1$s]|h"):format(name), "LeftButton" )
-	end
-end
-
-local function BuildFriendTable(total)
-	wipe(friendTable)
-	local name, level, class, area, connected, status, note
-	for i = 1, total do
-		name, level, class, area, connected, status, note = GetFriendInfo(i)
-
-		if status == "<"..AFK..">" then
-			status = "|cffFFFFFF[|r|cffFF0000"..L['AFK'].."|r|cffFFFFFF]|r"
-		elseif status == "<"..DND..">" then
-			status = "|cffFFFFFF[|r|cffFF0000"..L['DND'].."|r|cffFFFFFF]|r"
-		end
-
-		if connected then
-			for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do if class == v then class = k end end
-			for k,v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do if class == v then class = k end end
-			friendTable[i] = { name, level, class, area, connected, status, note }
-		end
-	end
-	sort(friendTable, function(a, b)
-		if a[1] and b[1] then
-			return a[1] < b[1]
-		end
-	end)
-end
-
-local function Sort(a, b)
-	if a[2] and b[2] and a[3] and b[3] then
-		if a[2] == b[2] then return a[3] < b[3] end
-		return a[2] < b[2]
-	end
-end
-
-local function BuildBNTable(total)
-	wipe(BNTable)
-	wipe(BNTableWoW)
-	wipe(BNTableD3)
-	wipe(BNTableSC)
-	wipe(BNTableWTCG)
-
-	local _, presenceID, presenceName, battleTag, isBattleTagPresence, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText, isRIDFriend, messageTime, canSoR
-	local toonName, client, realmName, realmID, faction, race, class, zoneName, level, gameText, broadcastText, broadcastTime
-	for i = 1, total do
-	--  presenceID, presenceName, battleTag, isBattleTagPresence, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText, isRIDFriend, broadcastTime, canSoR
-		presenceID, presenceName, battleTag, isBattleTagPresence, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText, isRIDFriend, messageTime, canSoR = BNGetFriendInfo(i)
-	--  unknown, toonName, client, realmName, realmID, faction, race, class, unknown, zoneName, level, gameText, broadcastText, broadcastTime, unknown, presenceID
-		_, _, _, realmName, realmID, faction, race, class, _, zoneName, level, gameText, broadcastText, broadcastTime, _, _ = BNGetToonInfo(presenceID);
-
-		if isOnline then
-			for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do if class == v then class = k end end
-			BNTable[i] = { presenceID, presenceName, battleTag, toonName, toonID, client, isOnline, isAFK, isDND, noteText, realmName, faction, race, class, zoneName, level }
-
-			if client == BNET_CLIENT_SC2 then
-				BNTableSC[#BNTableSC + 1] = { presenceID, presenceName, toonName, toonID, client, isOnline, isAFK, isDND, noteText, realmName, faction, race, class, zoneName, level }
-			elseif client == BNET_CLIENT_D3 then
-				BNTableD3[#BNTableD3 + 1] = { presenceID, presenceName, toonName, toonID, client, isOnline, isAFK, isDND, noteText, realmName, faction, race, class, zoneName, level }
-			elseif client == BNET_CLIENT_WTCG then
-				BNTableWTCG[#BNTableWTCG + 1] = { presenceID, presenceName, toonName, toonID, client, isOnline, isAFK, isDND, noteText, realmName, faction, race, class, zoneName, level }
-			else
-				BNTableWoW[#BNTableWoW + 1] = { presenceID, presenceName, toonName, toonID, client, isOnline, isAFK, isDND, noteText, realmName, faction, race, class, zoneName, level }
-			end
-		end
+		SetItemRef( "player:"..name, ("|Hplayer:%1$s|h[%1$s]|h"):format(name), "LeftButton" )
 	end
-
-	--sort(BNTable, Sort)
-	sort(BNTableWoW, Sort)
-	sort(BNTableSC, Sort)
-	sort(BNTableD3, Sort)
-	sort(BNTableWTCG, Sort)
 end

 local REPORT_NAME = "Friends";
@@ -239,7 +135,7 @@ Report.OnEvent = function(self, event, ...)
 		local message = select(1, ...)
 		if not (find(message, friendOnline) or find(message, friendOffline)) then return end
 	end
-	dataValid = false
+	FRIENDS_LIST_DIRTY = false
 	local amt = onlineFriends + numBNetOnline
 	self.text:SetFormattedText(TEXT_PATTERN1, L['Friends'], HEX_COLOR, amt)
 end
@@ -250,49 +146,51 @@ Report.OnClick = function(self, button)
 	if button == "RightButton" then
 		local menuCountWhispers = 0
 		local menuCountInvites = 0
-		local classc, levelc, info
-
+		local classc, levelc, friend
+
 		menuList[2].menuList = {}
 		menuList[3].menuList = {}
-
-		if #friendTable > 0 then
-			for i = 1, #friendTable do
-				info = friendTable[i]
-				if (info[5]) then
+
+		local currentFaction = UnitFactionGroup("player");
+		local friendsTable = FRIENDSLIST['General'];
+		if #friendsTable > 0 then
+			for i = 1, #friendsTable do
+				friend = friendsTable[i]
+				if (friend.ONLINE) then
 					menuCountInvites = menuCountInvites + 1
 					menuCountWhispers = menuCountWhispers + 1
-
-					classc, levelc = RAID_CLASS_COLORS[info[3]], GetQuestDifficultyColor(info[2])
-					classc = classc or GetQuestDifficultyColor(info[2]);
-
-					menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,info[2],classc.r*255,classc.g*255,classc.b*255,info[1]), arg1 = info[1],notCheckable=true, func = inviteClick}
-					menuList[3].menuList[menuCountWhispers] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,info[2],classc.r*255,classc.g*255,classc.b*255,info[1]), arg1 = info[1],notCheckable=true, func = whisperClick}
+
+					classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)
+					classc = classc or levelc;
+
+					menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,friend.LVL,classc.r*255,classc.g*255,classc.b*255,friend.NAME), arg1 = friend.NAME,notCheckable=true, func = inviteClick}
+					menuList[3].menuList[menuCountWhispers] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,friend.LVL,classc.r*255,classc.g*255,classc.b*255,friend.NAME), arg1 = friend.NAME,notCheckable=true, func = whisperClick}
 				end
 			end
 		end
-		if #BNTable > 0 then
-			local realID, grouped
-			for i = 1, #BNTable do
-				info = BNTable[i]
-				if (info[5]) then
-					realID = info[2]
-					menuCountWhispers = menuCountWhispers + 1
-					menuList[3].menuList[menuCountWhispers] = {text = realID, arg1 = realID, arg2 = true, notCheckable=true, func = whisperClick}

-					if info[6] == BNET_CLIENT_WOW and UnitFactionGroup("player") == info[12] then
-						classc, levelc = RAID_CLASS_COLORS[info[14]], GetQuestDifficultyColor(info[16])
-						classc = classc or GetQuestDifficultyColor(info[16])
+		for client, list in pairs(FRIENDSLIST) do
+			if((client ~= 'General') and (#list > 0)) then
+				for i = 1, #list do
+					friend = list[i]
+					if (friend.ONLINE) then
+						local realID = friend.BNET_NAME
+						menuCountWhispers = menuCountWhispers + 1
+						menuList[3].menuList[menuCountWhispers] = {text = realID, arg1 = realID, arg2 = true, notCheckable=true, func = whisperClick}
+
+						if((BNET_CLIENT_WOW == friend.CLIENT) and (currentFaction == friend.FACTION)) then
+							classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)
+							classc = classc or levelc
+							menuCountInvites = menuCountInvites + 1

-						if UnitInParty(info[4]) or UnitInRaid(info[4]) then grouped = 1 else grouped = 2 end
-						menuCountInvites = menuCountInvites + 1
-
-						menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,info[16],classc.r*255,classc.g*255,classc.b*255,info[4]), arg1 = info[5], notCheckable=true, func = inviteClick}
+							menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,levelc.r*255,levelc.g*255,levelc.b*255,friend.CLASS,classc.r*255,classc.g*255,classc.b*255,friend.NAME), arg1 = friend.CLIENT, notCheckable=true, func = inviteClick}
+						end
 					end
 				end
 			end
 		end

-		EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
+		EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
 	else
 		ToggleFriendsFrame()
 	end
@@ -300,83 +198,94 @@ end

 Report.OnEnter = function(self)
 	Reports:SetDataTip(self)
-	local grouped
+	local groupString = "";
 	local numberOfFriends, onlineFriends = GetNumFriends()
 	local totalBNet, numBNetOnline = BNGetNumFriends()
-
 	local totalonline = onlineFriends + numBNetOnline
-
+
 	-- no friends online, quick exit
 	if totalonline == 0 then return end

-	if not dataValid then
-		-- only retrieve information for all on-line members when we actually view the tooltip
+	if(not FRIENDS_LIST_DIRTY) then
+		FRIENDSLIST = SV:GetFriendsCache(numberOfFriends, totalBNet);
 		if numberOfFriends > 0 then BuildFriendTable(numberOfFriends) end
 		if totalBNet > 0 then BuildBNTable(totalBNet) end
-		dataValid = true
+		FRIENDS_LIST_DIRTY = true
 	end

 	local totalfriends = numberOfFriends + totalBNet
-	local zonec, classc, levelc, realmc, info
-	Reports.ToolTip:AddDoubleLine(L['Friends List'], format(totalOnlineString, totalonline, totalfriends), 0.4,0.78,1, 0.4,0.78,1)
+	local zonec, classc, levelc, realmc, friend
+	Reports.ToolTip:AddDoubleLine(L['Friends List'], format(TEXT_PATTERN4, totalonline, totalfriends), 0.4,0.78,1, 0.4,0.78,1)
+
+	local currentZone = GetRealZoneText();
+	local currentRealm = GetRealmName();
+
 	if onlineFriends > 0 then
 		Reports.ToolTip:AddLine(' ')
 		Reports.ToolTip:AddLine(WORLD_OF_WARCRAFT)
-		for i = 1, #friendTable do
-			info = friendTable[i]
-			if info[5] then
-				if GetRealZoneText() == info[4] then zonec = SV.media.color.green else zonec = SV.media.color.medium end
-				classc, levelc = RAID_CLASS_COLORS[info[3]], GetQuestDifficultyColor(info[2])
-
-				classc = classc or GetQuestDifficultyColor(info[2])
-
-				if UnitInParty(info[1]) or UnitInRaid(info[1]) then grouped = 1 else grouped = 2 end
-				Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN3,levelc.r*255,levelc.g*255,levelc.b*255,info[2],info[1],groupedTable[grouped]," "..info[6]),info[4],classc.r,classc.g,classc.b,zonec.r,zonec.g,zonec.b)
+
+		local friendsTable = FRIENDSLIST['General'];
+		for i = 1, #friendsTable do
+			friend = friendsTable[i]
+			if friend.ONLINE then
+				if(currentZone == friend.LOC) then
+					zonec = SV.media.color.green
+				else
+					zonec = SV.media.color.medium
+				end
+				classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)
+
+				classc = classc or GetQuestDifficultyColor(friend.LVL)
+
+				if UnitInParty(friend.NAME) or UnitInRaid(friend.NAME) then
+					groupString = "|cffaaaaaa*|r";
+				else
+					groupString = "";
+				end
+				Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN3, levelc.r*255, levelc.g*255, levelc.b*255, friend.LVL, friend.NAME, groupString, friend.STATUS ), friend.LOC, classc.r, classc.g, classc.b, zonec.r, zonec.g, zonec.b)
 			end
 		end
 	end

 	if numBNetOnline > 0 then
 		local status = 0
-		for client, list in pairs(tableList) do
-			if #list > 0 then
+		for client, list in pairs(FRIENDSLIST) do
+			if((client ~= 'General') and (#list > 0)) then
 				Reports.ToolTip:AddLine(' ')
-				Reports.ToolTip:AddLine(BATTLENET_OPTIONS_LABEL..' ('..client..')')
+				Reports.ToolTip:AddLine(BATTLENET_OPTIONS_LABEL..' ('..client..')')
 				for i = 1, #list do
-					info = list[i]
-					-- for x = 1, #info do
-					-- 	print(x)
-					-- 	print(info[x])
-					-- 	print("-----")
-					-- end
-					if info[6] then
-						if info[5] == BNET_CLIENT_WOW then
-							if (info[7] == true) then status = 1 elseif (info[8] == true) then status = 2 else status = 3 end
-							classc = RAID_CLASS_COLORS[info[13]]
-
-							if UnitInParty(info[4]) or UnitInRaid(info[4]) then grouped = 1 else grouped = 2 end
-
-							if info[15] ~= '' then
-								levelc = GetQuestDifficultyColor(info[15])
-								Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN2, levelc.r*255, levelc.g*255, levelc.b*255, info[15], classc.r*255, classc.g*255, classc.b*255, info[3], groupedTable[grouped], 255, 0, 0, statusTable[status]), info[2], 238, 238, 238, 238, 238, 238)
+					friend = list[i]
+
+					if friend.ONLINE then
+						if friend.CLIENT == BNET_CLIENT_WOW then
+							classc = RAID_CLASS_COLORS[friend.CLASS] or RAID_CLASS_COLORS["PRIEST"]
+
+							if UnitInParty(friend.NAME) or UnitInRaid(friend.NAME) then
+								groupString = "|cffaaaaaa*|r";
 							else
-								classc = classc or RAID_CLASS_COLORS["PRIEST"]
-								Reports.ToolTip:AddDoubleLine(format("|cff%02x%02x%02x%s|r", classc.r*255, classc.g*255, classc.b*255, info[3], groupedTable[grouped], 255, 0, 0, statusTable[status]), info[2], 238, 238, 238, 238, 238, 238)
+								groupString = "";
+							end
+
+							if friend.LVL ~= '' then
+								levelc = GetQuestDifficultyColor(friend.LVL)
+								Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN2, levelc.r*255, levelc.g*255, levelc.b*255, friend.LVL, classc.r*255, classc.g*255, classc.b*255, friend.NAME, groupString, 255, 0, 0, friend.STATUS), friend.BNET_NAME, 238, 238, 238, 238, 238, 238)
+							else
+								Reports.ToolTip:AddDoubleLine(format("|cff%02x%02x%02x%s|r", classc.r*255, classc.g*255, classc.b*255, friend.NAME, groupString, 255, 0, 0, friend.STATUS), friend.BNET_NAME, 238, 238, 238, 238, 238, 238)
 							end

 							if IsShiftKeyDown() then
-								if GetRealZoneText() == info[14] then zonec = SV.media.color.green else zonec = SV.media.color.medium end
-								if GetRealmName() == info[10] then realmc = SV.media.color.green else realmc = SV.media.color.medium end
-								Reports.ToolTip:AddDoubleLine(info[14], info[10], zonec.r, zonec.g, zonec.b, realmc.r, realmc.g, realmc.b)
+								if(currentZone == friend.LOC) then zonec = SV.media.color.green else zonec = SV.media.color.medium end
+								if(currentRealm == friend.REALM) then realmc = SV.media.color.green else realmc = SV.media.color.medium end
+								Reports.ToolTip:AddDoubleLine(friend.LOC, friend.REALM, zonec.r, zonec.g, zonec.b, realmc.r, realmc.g, realmc.b)
 							end
 						else
-							Reports.ToolTip:AddDoubleLine(info[3], info[2], .9, .9, .9, .9, .9, .9)
+							Reports.ToolTip:AddDoubleLine(friend.NAME, friend.BNET_NAME, .9, .9, .9, .9, .9, .9)
 						end
 					end
 				end
 			end
 		end
-	end
-
+	end
+
 	Reports:ShowDataTip()
-end
\ No newline at end of file
+end
diff --git a/SVUI_!Core/system/utilities.lua b/SVUI_!Core/system/utilities.lua
index 899f5d7..691c265 100644
--- a/SVUI_!Core/system/utilities.lua
+++ b/SVUI_!Core/system/utilities.lua
@@ -339,6 +339,174 @@ function SV:SetFrameVisibilityLocks(frame)
 end
 --[[
 ##########################################################
+FRIENDS HELPERS
+##########################################################
+]]--
+do
+  local AFK_INSERT = "|cffFFFFFF[|r|cffFF0000"..L['AFK'].."|r|cffFFFFFF]|r";
+  local DND_INSERT = "|cffFFFFFF[|r|cffFF0000"..L['DND'].."|r|cffFFFFFF]|r";
+  local FRIENDS_CACHE = {
+    ['General'] = {},
+    ['BattleNet'] = {},
+    [BNET_CLIENT_WOW] = {},
+    [BNET_CLIENT_D3] = {},
+    [BNET_CLIENT_SC2] = {},
+    [BNET_CLIENT_WTCG] = {},
+    [BNET_CLIENT_HEROES] = {}
+  };
+
+  local function _reg(a, b)
+    if(a.NAME and b.NAME) then
+      return a.NAME < b.NAME
+    end
+  end
+
+  local function _bn(a, b)
+  	if(a.BNET_NAME and b.BNET_NAME) then
+  		if(a.BNET_NAME == b.BNET_NAME and (a.NAME and b.NAME)) then
+        return a.NAME < b.NAME;
+      end
+  		return a.BNET_NAME < b.BNET_NAME
+  	end
+  end
+
+  local function _sort()
+    tsort(FRIENDS_CACHE, _reg)
+    tsort(FRIENDS_CACHE[BNET_CLIENT_WOW], _bn)
+    tsort(FRIENDS_CACHE[BNET_CLIENT_SC2], _bn)
+    tsort(FRIENDS_CACHE[BNET_CLIENT_D3], _bn)
+    tsort(FRIENDS_CACHE[BNET_CLIENT_WTCG], _bn)
+    tsort(FRIENDS_CACHE[BNET_CLIENT_HEROES], _bn)
+  end
+
+  function SV:GetFriendsCache(total, BNtotal)
+    if(total and total > 0) then
+      wipe(FRIENDS_CACHE['General']);
+
+    	for i = 1, total do
+    		local name, level, class, area, isOnline, status, noteText = GetFriendInfo(i)
+
+    		if(isOnline) then
+          if(status) then
+        		if(status:find(AFK)) then
+        			status = AFK_INSERT
+        		elseif(status:find(DND)) then
+        			status = DND_INSERT
+        		end
+          end
+
+          local classUpdated = false;
+
+    			for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+            if class == v then
+              class = k;
+              classUpdated = true;
+            end
+          end
+
+          if(not classUpdated) then
+            for k,v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
+              if class == v then
+                class = k;
+              end
+            end
+          end
+
+          FRIENDS_CACHE[i] = {
+            NAME = name,
+            LVL = level,
+            CLASS = class,
+            LOC = area,
+            ONLINE = isOnline,
+            STATUS = status,
+            NOTES = noteText
+          };
+    		end
+
+    	end
+
+      tsort(FRIENDS_CACHE, _reg)
+    end
+
+    if(BNtotal and BNtotal > 0) then
+      wipe(FRIENDS_CACHE[BNET_CLIENT_WOW])
+      wipe(FRIENDS_CACHE[BNET_CLIENT_D3])
+      wipe(FRIENDS_CACHE[BNET_CLIENT_SC2])
+      wipe(FRIENDS_CACHE[BNET_CLIENT_WTCG])
+      wipe(FRIENDS_CACHE[BNET_CLIENT_HEROES])
+      wipe(FRIENDS_CACHE['BattleNet'])
+
+      local _, presenceID, presenceName, battleTag, isBattleTagPresence, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText, isRIDFriend, messageTime, canSoR;
+    	local toonName, client, realmName, realmID, faction, race, class, zoneName, level, gameText, broadcastText, broadcastTime;
+
+    	for i = 1, BNtotal do
+    		presenceID, presenceName, battleTag, isBattleTagPresence, toonName, toonID, client, isOnline, lastOnline, isAFK, isDND, messageText, noteText, isRIDFriend, messageTime, canSoR = BNGetFriendInfo(i)
+    		_, _, _, realmName, realmID, faction, race, class, _, zoneName, level, gameText, broadcastText, broadcastTime, _, _ = BNGetToonInfo(presenceID);
+
+    		if(isOnline) then
+          local classUpdated = false;
+
+    			for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do
+            if class == v then
+              class = k;
+              classUpdated = true;
+            end
+          end
+
+          if(not classUpdated) then
+            for k,v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
+              if class == v then
+                class = k;
+              end
+            end
+          end
+
+          local status = "";
+          if(isAFK) then
+      			status = AFK_INSERT
+      		elseif(isDND) then
+      			status = DND_INSERT
+      		end
+
+          local fData = {
+            BNET_ID = presenceID,
+            BNET_NAME = presenceName,
+            ID = toonID,
+            NAME = toonName,
+            CLIENT = client,
+            ONLINE = isOnline,
+            STATUS = status,
+            NOTES = noteText,
+            REALM = realmName,
+            FACTION = faction,
+            RACE = race,
+            CLASS = class,
+            LOC = zoneName,
+            LVL = level
+          };
+
+          if(FRIENDS_CACHE[client]) then
+            tinsert(FRIENDS_CACHE[client], fData);
+        	else
+            tinsert(FRIENDS_CACHE['BattleNet'], fData);
+        	end
+    		end
+    	end
+
+      tsort(FRIENDS_CACHE[BNET_CLIENT_WOW], _bn)
+      tsort(FRIENDS_CACHE[BNET_CLIENT_SC2], _bn)
+      tsort(FRIENDS_CACHE[BNET_CLIENT_D3], _bn)
+      tsort(FRIENDS_CACHE[BNET_CLIENT_WTCG], _bn)
+      tsort(FRIENDS_CACHE[BNET_CLIENT_HEROES], _bn)
+      tsort(FRIENDS_CACHE['BattleNet'], _bn)
+    end
+
+  end
+
+  return FRIENDS_CACHE;
+end
+--[[
+##########################################################
 MISC HELPERS
 ##########################################################
 ]]--