Quantcast

Bunch of shit... Need testing... Don't pull this one Pete (mobius-spirestone)

Repooc [05-22-14 - 21:44]
Bunch of shit... Need testing... Don't pull this one Pete (mobius-spirestone)
Filename
ElvUI_SLE/modules/characterframe/communication.lua
ElvUI_SLE/modules/characterframe/core.lua
ElvUI_SLE/modules/characterframe/inspectframe.lua
diff --git a/ElvUI_SLE/modules/characterframe/communication.lua b/ElvUI_SLE/modules/characterframe/communication.lua
index c90cd9e..05d1e33 100644
--- a/ElvUI_SLE/modules/characterframe/communication.lua
+++ b/ElvUI_SLE/modules/characterframe/communication.lua
@@ -8,48 +8,52 @@ if not AISM then
 	local ProfessionLearnKey = ERR_LEARN_ABILITY_S:gsub('%%s', '(.+)')
 	local ProfessionLearnKey2 = ERR_LEARN_RECIPE_S:gsub('%%s', '(.+)')
 	local ProfessionUnlearnKey = ERR_SPELL_UNLEARNED_S:gsub('%%s', '(.+)')
-
+	local GuildLeaveKey = ERR_GUILD_LEAVE_S:gsub('%%s', '(.+)')
+	local PlayerOfflineKey = ERR_CHAT_PLAYER_NOT_FOUND_S:gsub('%%s', '(.+)')
+
 	local playerName = UnitName('player')
 	local playerRealm = gsub(GetRealmName(),'[%s%-]','')
 	local _, playerClass, playerClassID = UnitClass('player')
 	local playerRace, playerRaceID = UnitRace('player')
 	local playerSex = UnitSex('player')
-	local isHelmDisplayed = ShowingHelm() == 1
-	local isCloakDisplayed = ShowingCloak() == 1
-
+	local isHelmDisplayed, isCloakDisplayed
+
+
 	--<< Create Core >>--
 	AISM = CreateFrame('Frame', 'Armory_InspectSupportModule', UIParent)
 	AISM.Version = 1.0
 	AISM.Tooltip = CreateFrame('GameTooltip', 'AISM_Tooltip', nil, 'GameTooltipTemplate')
 	AISM.Tooltip:SetOwner(UIParent, 'ANCHOR_NONE')
 	AISM.Updater = CreateFrame('Frame', 'AISM_Updater', UIParent)
-
-	AISM.SendMessageDelay = 2
-	AISM.SendDataGroupUpdated = AISM.SendMessageDelay
-	AISM.SendDataGuildUpdated = AISM.SendMessageDelay
-
-	AISM.PlayerData = {}
-	AISM.PlayerData_ShortString = {}
+
+	AISM.SendMessageDelay_Group = 2
+
+	AISM.PlayerData = { ['SetItem'] = {}, }
+	AISM.PlayerData_ShortString = { ['SetItem'] = {}, }
+	AISM.AISMUserList = {}
 	AISM.GroupMemberData = {}
 	AISM.GuildMemberData = {}
 	AISM.CurrentInspectData = {}
 	AISM.InspectRegistered = {}
 	AISM.RemainMessage = {}
 	AISM.RegisteredFunction = {}
-
+
+
 	--<< Define Key Table >>--
+	local SlotIDList = {}
 	AISM.ProfessionList = {
 		[GetSpellInfo(105206)] = 'AC', -- Alchemy
 		[GetSpellInfo(110396)] = 'BS', -- BlackSmithing
 		[GetSpellInfo(110400)] = 'EC', -- Enchanting
 		[GetSpellInfo(110403)] = 'EG', -- Engineering
-		[GetSpellInfo(110413)] = 'HB', -- Herbalism
 		[GetSpellInfo(110417)] = 'IS', -- Inscription
 		[GetSpellInfo(110420)] = 'JC', -- JewelCrafting
-		[GetSpellInfo(102161)] = 'MN', -- Mining
 		[GetSpellInfo(110423)] = 'LW', -- LeatherWorking
-		[GetSpellInfo(102216)] = 'SK', -- Skinning
 		[GetSpellInfo(110426)] = 'TL', -- Tailoring
+
+		[GetSpellInfo(110413)] = 'HB', -- Herbalism
+		[GetSpellInfo(102161)] = 'MN', -- Mining
+		[GetSpellInfo(102216)] = 'SK', -- Skinning
 	}
 	AISM.GearList = {
 		['HeadSlot'] = 'HE',
@@ -97,65 +101,72 @@ if not AISM then
 		AISM.DataTypeTable['SP'..groupNum] = 'Specialization'
 		AISM.DataTypeTable['GL'..groupNum] = 'Glyph'
 	end
-	for _, keyName in pairs(AISM.GearList) do
+	for slotName, keyName in pairs(AISM.GearList) do
 		AISM.DataTypeTable[keyName] = 'Gear'
+		SlotIDList[GetInventorySlotInfo(slotName)] = slotName
 	end
-
+
+
 	--<< Player Data Updater Core >>--
-	local needUpdate, SystemMessage, isPlayer
+	local needUpdate, args
 	AISM.Updater:SetScript('OnUpdate', function(self)
 		AISM.UpdatedData = needUpdate and AISM.UpdatedData or {}
 		needUpdate = nil
-
+
 		if not self.ProfessionUpdated then
 			needUpdate = AISM:GetPlayerProfessionSetting() or needUpdate
 		end
-
+
 		if not self.SpecUpdated then
 			needUpdate = AISM:GetPlayerSpecSetting() or needUpdate
 		end
-
+
 		if not self.GlyphUpdated then
 			needUpdate = AISM:GetPlayerGlyphString() or needUpdate
 		end
-
-		if not self.GearUpdated then
+
+		if self.GearUpdated ~= true then
 			needUpdate = AISM:GetPlayerGearString() or needUpdate
 		end
-
+
 		if not needUpdate then
 			self:Hide()
-
-			if self.Initialize then
-				for _ in pairs(AISM.UpdatedData) do
-					if AISM.CurrentGroupMode and AISM.CurrentGroupMode ~= 'NoGroup' and AISM.CurrentGroupType then
-						AISM:SendData(AISM.UpdatedData)
-					end
-					break
+
+			for _ in pairs(AISM.UpdatedData) do
+				if AISM.CurrentGroupMode and AISM.CurrentGroupMode ~= 'NoGroup' and AISM.CurrentGroupType then
+					AISM:SendData(AISM.UpdatedData)
 				end
+				break
 			end
 		end
 	end)
-
 	AISM.Updater:SetScript('OnEvent', function(self, Event, ...)
-		if Event == 'COMBAT_LOG_EVENT_UNFILTERED' then
-			_, SystemMessage, _, _, _, _, _, _, isPlayer = ...
-
-			if SystemMessage == 'ENCHANT_APPLIED' and isPlayer == playerName then
+		if Event == 'SOCKET_INFO_SUCCESS' or Event == 'ITEM_UPGRADE_MASTER_UPDATE' or Event == 'TRANSMOGRIFY_UPDATE' then
+			self.GearUpdated = nil
+			self:Show()
+		elseif Event == 'UNIT_INVENTORY_CHANGED' then
+			args = ...
+
+			if args == 'player' then
 				self.GearUpdated = nil
 				self:Show()
 			end
-		elseif Event == 'UNIT_INVENTORY_CHANGED' then
-			isPlayer = ...
-
-			if isPlayer == 'player' then
+		elseif Event == 'PLAYER_EQUIPMENT_CHANGED' then
+			args = ...
+			self.GearUpdated = type(self.GearUpdated) == 'table' and self.GearUpdated or {}
+			self.GearUpdated[(SlotIDList[args])] = true
+			self:Show()
+		elseif Event == 'COMBAT_LOG_EVENT_UNFILTERED' then
+			_, Event, _, _, _, _, _, _, args = ...
+
+			if Event == 'ENCHANT_APPLIED' and args == playerName then
 				self.GearUpdated = nil
 				self:Show()
 			end
 		elseif Event == 'CHAT_MSG_SYSTEM' then
-			SystemMessage = ...
-
-			if SystemMessage:find(ProfessionLearnKey) or SystemMessage:find(ProfessionLearnKey2) or SystemMessage:find(ProfessionUnlearnKey) then
+			args = ...
+
+			if args:find(ProfessionLearnKey) or args:find(ProfessionLearnKey2) or args:find(ProfessionUnlearnKey) then
 				self.ProfessionUpdated = nil
 				self:Show()
 			end
@@ -165,93 +176,90 @@ if not AISM then
 		elseif Event == 'GLYPH_ADDED' or Event == 'GLYPH_REMOVED' or Event == 'GLYPH_UPDATED' then
 			self.GlyphUpdated = nil
 			self:Show()
-		elseif Event == 'SOCKET_INFO_SUCCESS' or Event == 'PLAYER_EQUIPMENT_CHANGED' or Event == 'EQUIPMENT_SWAP_FINISHED' or Event == 'ITEM_UPGRADE_MASTER_UPDATE' or Event == 'TRANSMOGRIFY_UPDATE' then
-			self.GearUpdated = nil
-			self:Show()
+		else
 		end
 	end)
-
 	AISM.UpdateHelmDisplaying = function(value)
 		isHelmDisplayed = value == '1'
 		AISM.Updater.GearUpdated = nil
 		AISM.Updater:Show()
-	end
+	end
 	hooksecurefunc('ShowHelm', AISM.UpdateHelmDisplaying)
-
 	AISM.UpdateCloakDisplaying = function(value)
 		isCloakDisplayed = value == '1'
 		AISM.Updater.GearUpdated = nil
 		AISM.Updater:Show()
 	end
 	hooksecurefunc('ShowCloak', AISM.UpdateCloakDisplaying)
-
+
+
 	--<< Profession String >>--
 	function AISM:GetPlayerProfessionSetting()
 		local Profession1, Profession2 = GetProfessions()
 		local Profession1_Level, Profession2_Level = 0, 0
-
+
 		if Profession1 then
 			Profession1, _, Profession1_Level = GetProfessionInfo(Profession1)
-
+
 			if self.ProfessionList[Profession1] then
 				Profession1 = self.ProfessionList[Profession1]..'/'..Profession1_Level
 			else
 				Profession1 = 'F'
 			end
 		end
-
+
 		if Profession2 then
 			Profession2, _, Profession2_Level = GetProfessionInfo(Profession2)
-
+
 			if self.ProfessionList[Profession2] then
 				Profession2 = self.ProfessionList[Profession2]..'/'..Profession2_Level
 			else
 				Profession2 = 'F'
 			end
 		end
-
+
 		if self.PlayerData.Profession1 ~= Profession1 then
 			self.PlayerData.Profession1 = Profession1
 		end
-
+
 		if self.PlayerData.Profession2 ~= Profession2 then
 			self.PlayerData.Profession2 = Profession2
 		end
-
+
 		self.Updater.ProfessionUpdated = true
 	end
 	AISM.Updater:RegisterEvent('CHAT_MSG_SYSTEM')
-
+

 	--<< Specialization String >>--
 	function AISM:GetPlayerSpecSetting()
 		local DataString, isSelected, selectedSlot
 		local ActiveSpec = GetActiveSpecGroup()
-
+
 		for groupNum = 1, MAX_TALENT_GROUPS do
 			DataString = GetSpecialization(nil, nil, groupNum)
-
+
 			if DataString then
 				DataString = GetSpecializationInfo(DataString)
 			else
 				DataString = '0'
 			end
-
+
 			for i = 1, MAX_NUM_TALENT_TIERS do
 				selectedSlot = '0'
-
+
 				for k = 1, NUM_TALENT_COLUMNS do
 					_, _, _, _, isSelected = GetTalentInfo((i - 1) * NUM_TALENT_COLUMNS + k, nil, groupNum)
-
+
 					if isSelected then
 						selectedSlot = k
 						break
 					end
 				end
-
+
 				DataString = DataString..'/'..selectedSlot
 			end
-
+
 			if self.PlayerData['Spec'..groupNum] ~= DataString then
 				self.PlayerData['Spec'..groupNum] = DataString
 			end
@@ -272,175 +280,194 @@ if not AISM then
 	end
 	AISM.Updater:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
 	AISM.Updater:RegisterEvent('CHARACTER_POINTS_CHANGED')
-
+

 	--<< Glyph String >>--
 	function AISM:GetPlayerGlyphString()
 		local ShortString, FullString
 		local ActiveSpec = GetActiveSpecGroup()
-
+
 		local SpellID, GlyphID
 		for groupNum = 1, MAX_TALENT_GROUPS do
 			ShortString, FullString = '', ''
-
+
 			for slotNum = 1, NUM_GLYPH_SLOTS do
 				_, _, _, SpellID, _, GlyphID = GetGlyphSocketInfo(slotNum, groupNum)

 				ShortString = ShortString..(SpellID or '0')..(slotNum ~= NUM_GLYPH_SLOTS and '/' or '')
 				FullString = FullString..(SpellID or '0')..'_'..(GlyphID or '0')..(slotNum ~= NUM_GLYPH_SLOTS and '/' or '')
 			end
-
+
 			if self.PlayerData['Glyph'..groupNum] ~= FullString then
 				self.PlayerData['Glyph'..groupNum] = FullString
 			end
-
+
 			if groupNum == ActiveSpec and self.PlayerData_ShortString.Glyph1 ~= ShortString then
 				self.PlayerData_ShortString.Glyph1 = ShortString
 				self.UpdatedData.Glyph1 = ShortString
 			end
 		end
-
+
 		self.Updater.GlyphUpdated = true
 	end
-
 	AISM.Updater:RegisterEvent('GLYPH_ADDED')
 	AISM.Updater:RegisterEvent('GLYPH_REMOVED')
 	AISM.Updater:RegisterEvent('GLYPH_UPDATED')
-
+
+
 	--<< Gear String >>--
 	function AISM:GetPlayerGearString()
-		local ShortString, FullString
+		local ShortString, FullString, needUpdate, needUpdateList
 		local CurrentSetItem = {}
-
-		local slotID, slotLink, isTransmogrified, transmogrifiedItemID, SetName, GeatSetCount, SetItemMax, colorR, colorG, colorB, checkSpace, SetItemOptionNum, tooltipText
-		for slotName in pairs(self.GearList) do
+
+		local slotID, slotLink, isTransmogrified, transmogrifiedItemID, SetName, GeatSetCount, SetItemMax, SetOptionCount, colorR, colorG, colorB, checkSpace, tooltipText
+		for slotName in pairs(self.Updater.GearUpdated or self.GearList) do
+			needUpdate = nil
+
 			slotID = GetInventorySlotInfo(slotName)
 			slotLink = GetInventoryItemLink('player', slotID)
-
+
 			if slotLink and slotLink:find('%[%]') then -- sometimes itemLink is malformed so we need to update when crashed
-				self.Updater.GearUpdated = nil
-
-				return true
-			end
-
-			if slotLink and self.CanTransmogrifySlot[slotName] then
-				isTransmogrified, _, _, _, _, transmogrifiedItemID = GetTransmogrifySlotInfo(slotID)
+				needUpdate = true
 			else
-				isTransmogrified = nil
-			end
-
-			ShortString = slotLink and select(2, strsplit(':', slotLink)) or 'F'
-			FullString = (slotLink or 'F')..'/'..(slotName == 'HeadSlot' and not isHelmDisplayed and 'ND' or slotName == 'BackSlot' and not isCloakDisplayed and 'ND' or isTransmogrified and transmogrifiedItemID or '0')
-
-			for i = 1, MAX_NUM_SOCKETS do
-				FullString = FullString..'/'..(select(i, GetInventoryItemGems(slotID)) or 0)
-			end
-
-			if self.PlayerData[slotName] ~= FullString then
-				self.PlayerData[slotName] = FullString
-			end
-
-			if self.PlayerData_ShortString[slotName] ~= ShortString then
-				self.PlayerData_ShortString[slotName] = ShortString
-				self.UpdatedData[slotName] = ShortString
-			end
-
-			if slotLink then
-				self.Tooltip:ClearLines()
-				self.Tooltip:SetHyperlink(slotLink)
-				--self.Tooltip:SetInventoryItem('player', slotID)
+				if slotLink and self.CanTransmogrifySlot[slotName] then
+					isTransmogrified, _, _, _, _, transmogrifiedItemID = GetTransmogrifySlotInfo(slotID)
+				else
+					isTransmogrified = nil
+				end

-				checkSpace = 2
-
-				for i = 1, self.Tooltip:NumLines() do
-					SetName, SetItemCount, SetItemMax = _G['AISM_TooltipTextLeft'..i]:GetText():match('^(.+) %((%d)/(%d)%)$') -- find string likes 'SetName (0/5)'
-
-					if SetName then
-						SetItemCount = tonumber(SetItemCount)
-						SetItemMax = tonumber(SetItemMax)
-
-						if SetItemCount > SetItemMax or SetItemMax == 1 then
-							self.Updater.GearUpdated = nil
-
-							return true
-						elseif CurrentSetItem[SetName] then
-							break
-						else
-							CurrentSetItem[SetName] = true
-							ShortString = 0
-							FullString = ''
-
-							for k = 1, self.Tooltip:NumLines() do
-								tooltipText = _G['AISM_TooltipTextLeft'..(i+k)]:GetText()
-
-								if tooltipText == ' ' then
-									checkSpace = checkSpace - 1
-
-									if checkSpace == 0 then break end
-								elseif checkSpace == 2 then
-									colorR, colorG, colorB = _G['AISM_TooltipTextLeft'..(i+k)]:GetTextColor()
-
-									if colorR > LIGHTYELLOW_FONT_COLOR.r - .01 and colorR < LIGHTYELLOW_FONT_COLOR.r + .01 and colorG > LIGHTYELLOW_FONT_COLOR.g - .01 and colorG < LIGHTYELLOW_FONT_COLOR.g + .01 and colorB > LIGHTYELLOW_FONT_COLOR.b - .01 and colorB < LIGHTYELLOW_FONT_COLOR.b + .01 then
-										ShortString = ShortString + 1
-										tooltipText = LIGHTYELLOW_FONT_COLOR_CODE..tooltipText
-									else
-										tooltipText = GRAY_FONT_COLOR_CODE..tooltipText
+				ShortString = slotLink and select(2, strsplit(':', slotLink)) or 'F'
+				FullString = (slotLink or 'F')..'/'..(slotName == 'HeadSlot' and not isHelmDisplayed and 'ND' or slotName == 'BackSlot' and not isCloakDisplayed and 'ND' or isTransmogrified and transmogrifiedItemID or '0')
+
+				for i = 1, MAX_NUM_SOCKETS do
+					FullString = FullString..'/'..(select(i, GetInventoryItemGems(slotID)) or 0)
+				end
+
+				if self.PlayerData[slotName] ~= FullString then
+					self.PlayerData[slotName] = FullString
+				end
+
+				if self.PlayerData_ShortString[slotName] ~= ShortString then
+					self.PlayerData_ShortString[slotName] = ShortString
+					self.UpdatedData[slotName] = ShortString
+				end
+
+				if slotLink then
+					self.Tooltip:ClearLines()
+					self.Tooltip:SetHyperlink(slotLink)
+
+					checkSpace = 2
+					SetOptionCount = 1
+
+					for i = 1, self.Tooltip:NumLines() do
+						SetName, SetItemCount, SetItemMax = _G['AISM_TooltipTextLeft'..i]:GetText():match('^(.+) %((%d)/(%d)%)$') -- find string likes 'SetName (0/5)'
+
+						if SetName then
+							SetItemCount = tonumber(SetItemCount)
+							SetItemMax = tonumber(SetItemMax)
+
+							if SetItemCount > SetItemMax or SetItemMax == 1 then
+								needUpdate = true
+								break
+							else
+								if not (CurrentSetItem[SetName] or self.PlayerData.SetItem or self.PlayerData.SetItem[SetName]) then
+									needUpdate = true
+								end
+
+								CurrentSetItem[SetName] = CurrentSetItem[SetName] or {}
+
+								ShortString = 0
+								FullString = ''
+
+								for k = 1, self.Tooltip:NumLines() do
+									tooltipText = _G['AISM_TooltipTextLeft'..(i+k)]:GetText()
+
+									if tooltipText == ' ' then
+										checkSpace = checkSpace - 1
+
+										if checkSpace == 0 then break end
+									elseif checkSpace == 2 then
+										colorR, colorG, colorB = _G['AISM_TooltipTextLeft'..(i+k)]:GetTextColor()
+
+										if colorR > LIGHTYELLOW_FONT_COLOR.r - .01 and colorR < LIGHTYELLOW_FONT_COLOR.r + .01 and colorG > LIGHTYELLOW_FONT_COLOR.g - .01 and colorG < LIGHTYELLOW_FONT_COLOR.g + .01 and colorB > LIGHTYELLOW_FONT_COLOR.b - .01 and colorB < LIGHTYELLOW_FONT_COLOR.b + .01 then
+											ShortString = ShortString + 1
+											tooltipText = LIGHTYELLOW_FONT_COLOR_CODE..tooltipText
+										else
+											tooltipText = GRAY_FONT_COLOR_CODE..tooltipText
+										end
+
+										if CurrentSetItem[SetName][k] and CurrentSetItem[SetName][k] ~= tooltipText then
+											needUpdate = true
+										end
+
+										CurrentSetItem[SetName][k] = tooltipText
+										FullString = FullString..'/'..tooltipText
+									elseif tooltipText:find(ItemSetBonusKey) then
+										tooltipText = tooltipText:match("^%((%d)%)%s.+:%s.+$") or 'T'
+
+										if CurrentSetItem[SetName]['SetOption'..SetOptionCount] and CurrentSetItem[SetName]['SetOption'..SetOptionCount] ~= tooltipText then
+											needUpdate = true
+										end
+
+										CurrentSetItem[SetName]['SetOption'..SetOptionCount] = tooltipText
+										FullString = FullString..'/'..tooltipText
+
+										SetOptionCount = SetOptionCount + 1
 									end
-									--print(tooltipText..' / '..SetItemCount..' / '..SetItemMax)
-
-									FullString = FullString..'/'..tooltipText
-								elseif tooltipText:find(ItemSetBonusKey) then
-									FullString = FullString..'/'..(tooltipText:match("^%((%d)%)%s.+:%s.+$") or 'T')
+								end
+
+								if self.PlayerData.SetItem[SetName] ~= FullString then
+									self.PlayerData.SetItem[SetName] = FullString
+								end
+
+								if self.PlayerData_ShortString.SetItem[SetName] ~= ShortString then
+									self.PlayerData_ShortString.SetItem[SetName] = ShortString
+
+									self.UpdatedData.SetItem = self.UpdatedData.SetItem or {}
+									self.UpdatedData.SetItem[SetName] = ShortString
 								end
 							end
-
-							self.PlayerData.SetItem = self.PlayerData.SetItem or {}
-							if self.PlayerData.SetItem[SetName] ~= FullString then
-								self.PlayerData.SetItem[SetName] = FullString
-							end
-
-							self.PlayerData_ShortString.SetItem = self.PlayerData_ShortString.SetItem or {}
-							if self.PlayerData_ShortString.SetItem[SetName] ~= ShortString then
-								self.PlayerData_ShortString.SetItem[SetName] = ShortString
-
-								self.UpdatedData.SetItem = self.UpdatedData.SetItem or {}
-								self.UpdatedData.SetItem[SetName] = ShortString
-							end
-
-							break
 						end
+
+						if checkSpace == 0 then break end
 					end
-
-					if checkSpace == 0 then break end
 				end
 			end
+
+			if needUpdate then
+				needUpdateList = needUpdateList or {}
+				needUpdateList[slotName] = true
+			end
 		end
-
+
 		-- Clear cache when there's no gear set
 		if self.PlayerData.SetItem then
 			for SetName in pairs(self.PlayerData.SetItem) do
 				if not CurrentSetItem[SetName] then
 					self.PlayerData.SetItem[SetName] = nil
-
+
 					self.PlayerData_ShortString.SetItem[SetName] = nil
 					self.UpdatedData.SetItem = self.UpdatedData.SetItem or {}
 					self.UpdatedData.SetItem[SetName] = 'F'
 				end
 			end
 		end
-
-		self.Updater.GearUpdated = true
-
-		return nil
+
+		if needUpdateList then
+			self.Updater.GearUpdated = needUpdateList
+			return true
+		else
+			self.Updater.GearUpdated = true
+		end
 	end
 	AISM.Updater:RegisterEvent('SOCKET_INFO_SUCCESS')
 	AISM.Updater:RegisterEvent('PLAYER_EQUIPMENT_CHANGED')
-	--AISM.Updater:RegisterEvent('UNIT_INVENTORY_CHANGED')
-	--AISM.Updater:RegisterEvent('EQUIPMENT_SWAP_FINISHED')
+	AISM.Updater:RegisterEvent('UNIT_INVENTORY_CHANGED')
 	AISM.Updater:RegisterEvent('ITEM_UPGRADE_MASTER_UPDATE')
 	AISM.Updater:RegisterEvent('TRANSMOGRIFY_UPDATE')
 	AISM.Updater:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
-
+
+
 	--<< Player Info >>--
 	function AISM:SettingInspectData(TableToSave)
 		local guildName, guildRankName = GetGuildInfo('player')
@@ -471,47 +498,47 @@ if not AISM then
 	function AISM:SendData(InputData, Prefix, Channel, WhisperTarget)
 		Channel = Channel or IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and 'INSTANCE_CHAT' or string.upper(self.CurrentGroupMode)
 		Prefix = Prefix or 'AISM'
-
+
 		if not InputData or type(InputData) ~= 'table' or Channel == 'NOGROUP' then return end
-
+
 		local Data = {}
-
+
 		if InputData.Profession1 then
 			Data[#Data + 1] = 'PF1:'..InputData.Profession1
 		end
-
+
 		if InputData.Profession2 then
 			Data[#Data + 1] = 'PF2:'..InputData.Profession2
 		end
-
+
 		for groupNum = 1, MAX_TALENT_GROUPS do
 			if InputData['Spec'..groupNum] then
 				Data[#Data + 1] = 'SP'..groupNum..':'..InputData['Spec'..groupNum]
 			end
 		end
-
+
 		if InputData.ActiveSpec then
 			Data[#Data + 1] = 'ASP:'..InputData.ActiveSpec
 		end
-
+
 		for groupNum = 1, MAX_TALENT_GROUPS do
 			if InputData['Glyph'..groupNum] then
 				Data[#Data + 1] = 'GL'..groupNum..':'..InputData['Glyph'..groupNum]
 			end
 		end
-
+
 		for slotName, keyName in pairs(self.GearList) do
 			if InputData[slotName] then
 				Data[#Data + 1] = keyName..':'..InputData[slotName]
 			end
 		end
-
+
 		if InputData.SetItem then
 			for SetName, DataString in pairs(InputData.SetItem) do
 				Data[#Data + 1] = 'SID:'..SetName..(type(DataString) == 'number' and '/' or '')..DataString
 			end
 		end
-
+
 		if InputData.PlayerInfo then
 			Data[#Data + 1] = 'PLI:'..InputData.PlayerInfo
 		end
@@ -523,32 +550,33 @@ if not AISM then
 		if InputData.PvP then
 			Data[#Data + 1] = 'PvP:'..InputData.PvP
 		end
-
+
 		local DataString = ''
 		local stringLength = 0
 		local dataLength
-
+
 		for dataTag, dataText in pairs(Data) do
 			DataString = DataString..'{'..dataText..'}'
 			dataLength = strlen(dataText) + 2
-
+
 			if stringLength + dataLength <= 255 then
 				stringLength = stringLength + dataLength
 			else
 				while strlen(DataString) > 255 do
 					SendAddonMessage(Prefix, strsub(DataString, 1, 255), Channel, WhisperTarget)
-
+
 					DataString = strsub(DataString, 256)
 					stringLength = strlen(DataString)
 				end
 			end
 		end
-
+
 		if DataString ~= '' then
 			SendAddonMessage(Prefix, DataString, Channel, WhisperTarget)
 		end
 	end
-
+
+
 	function AISM:GetPlayerCurrentGroupMode()
 		if not (IsInGroup() or IsInRaid()) or GetNumGroupMembers() == 1 then
 			self.CurrentGroupMode = 'NoGroup'
@@ -559,7 +587,7 @@ if not AISM then
 			else
 				self.CurrentGroupMode = 'party'
 			end
-
+
 			for userName in pairs(self.GroupMemberData) do
 				if not UnitExists(userName) or not UnitIsConnected(userName) then
 					self.GroupMemberData[userName] = nil
@@ -569,93 +597,65 @@ if not AISM then

 		return self.CurrentGroupMode
 	end
-
+
+
 	function AISM:GetCurrentInstanceType()
 		local _, instanceType, difficultyID = GetInstanceInfo()
-
+
 		if difficultyID == 8 then
 			self.InstanceType = 'challenge'
 		else
 			self.InstanceType = instanceType == 'none' and 'field' or instanceType
 		end
 	end
-
-	local LastSendGroupType = 'NoGroup'
-	local LastSendInstanceType = 'field'
+
+
+	local needSendData, Name, TableIndex
 	AISM:SetScript('OnUpdate', function(self, elapsed)
-		if not self.Initialize then
-			SendAddonMessage('AISM', 'AISM_Initialize', 'WHISPER', playerName)
-		else
-			if self.CurrentGroupMode and self.InstanceType then
-				if LastSendGroupType ~= self.CurrentGroupMode or LastSendInstanceType ~= self.InstanceType or self.needSendDataGroup ~= nil then
-					LastSendGroupType = self.CurrentGroupMode
-					LastSendInstanceType = self.InstanceType
-
-					if self.CurrentGroupMode ~= 'NoGroup' then
-						local Name, TableIndex
-
-						for i = 1, MAX_RAID_MEMBERS do
-							Name = UnitName(self.CurrentGroupMode..i)
-							TableIndex = GetUnitName(self.CurrentGroupMode..i, true)
-
-							if Name and not UnitIsUnit('player', self.CurrentGroupMode..i) then
-								if Name == UNKNOWNOBJECT or Name == COMBATLOG_UNKNOWN_UNIT then
-									if self.needSendDataGroup == nil then
-										self.needSendDataGroup = false
-									end
-								elseif not UnitIsConnected(self.CurrentGroupMode..i) then
-									if self.needSendDataGroup == nil then
-										self.needSendDataGroup = 0
-									elseif type(self.needSendDataGroup) == 'number' then
-										self.needSendDataGroup = self.needSendDataGroup + 1
-
-										if self.needSendDataGroup > 30 then
-											self.needSendDataGroup = nil
-										end
-									end
-									self.GroupMemberData[TableIndex] = nil
-								elseif not self.GroupMemberData[TableIndex] then
-									self.needSendDataGroup = true
-									self.GroupMemberData[TableIndex] = true
-								end
-							end
-						end
-					else
-						self.needSendDataGroup = nil
-						self.SendDataGroupUpdated = self.SendMessageDelay
-					end
-				end
-
-				if self.needSendDataGroup == true and self.Updater.SpecUpdated and self.Updater.GlyphUpdated and self.Updater.GearUpdated then
-					self.SendDataGroupUpdated = self.SendDataGroupUpdated - elapsed
+		if elapsed < .1 then
+			needSendData = nil
+
+			if self.CurrentGroupMode ~= 'NoGroup' then
+				for i = 1, MAX_RAID_MEMBERS do
+					Name = UnitName(self.CurrentGroupMode..i)
+					TableIndex = GetUnitName(self.CurrentGroupMode..i, true)

-					if self.SendDataGroupUpdated < 0 then
-						self.SendDataGroupUpdated = self.SendMessageDelay
-
-						self:SendData(self.PlayerData_ShortString)
-						self.needSendDataGroup = nil
+					if Name and not UnitIsUnit('player', self.CurrentGroupMode..i) then
+						if Name == UNKNOWNOBJECT or Name == COMBATLOG_UNKNOWN_UNIT or not UnitIsConnected(self.CurrentGroupMode..i) then
+							self.AISMUserList[TableIndex] = nil
+							self.GroupMemberData[TableIndex] = nil
+						elseif not self.GroupMemberData[TableIndex] then
+							needSendData = true
+							self.GroupMemberData[TableIndex] = true
+						end
 					end
 				end
+			else
+				needSendData = nil
+				self.SendDataGroupUpdated = nil
 			end

-			if self.needSendDataGuild then
-				self.SendDataGuildUpdated = self.SendDataGuildUpdated - elapsed
-
-				if self.SendDataGuildUpdated < 0 then
-					self.SendDataGuildUpdated = self.SendMessageDelay
+			if needSendData and self.Updater.SpecUpdated and self.Updater.GlyphUpdated and self.Updater.GearUpdated then
+				self.SendDataGroupUpdated = (self.SendDataGroupUpdated or self.SendMessageDelay_Group) - elapsed
+
+				if self.SendDataGroupUpdated < 0 then
+					needSendData = nil
+					self.SendDataGroupUpdated = nil

-					SendAddonMessage('AISM', 'AISM_GUILD_RegistME', 'GUILD')
-					self.needSendDataGuild = nil
+					self:SendData(self.PlayerData_ShortString)
 				end
 			end

-			if self.needSendDataGroup == nil and self.needSendDataGuild == nil then
+			if needSendData == nil then
 				self:Hide() -- close function
 			end
 		end
 	end)

+
 	function AISM:PrepareTableSetting(Prefix, Sender)
+		self.AISMUserList[Sender] = self.AISMUserList[Sender] or true
+
 		if Prefix == 'AISM' then
 			local NeedResponse

@@ -670,38 +670,47 @@ if not AISM then
 			return self.CurrentInspectData[Sender]
 		end
 	end
-
+
+
 	local SenderRealm
 	function AISM:Receiver(Prefix, Message, Channel, Sender)
 		Sender, SenderRealm = strsplit('-', Sender)
 		Sender = Sender..(SenderRealm and SenderRealm ~= '' and SenderRealm ~= playerRealm and '-'..SenderRealm or '')
-
+
 		--print('|cffceff00['..Channel..']|r|cff2eb7e4['..Prefix..']|r '..Sender..' : ')
 		--print(Message)
-
-		if Message == 'AISM_UnregistME' then
-			self.GroupMemberData[Sender] = nil
-		elseif Message == 'AISM_GUILD_RegistME' then
-			self.GuildMemberData[Sender] = true
-			SendAddonMessage('AISM', 'AISM_GUILD_RegistResponse', SenderRealm == playerRealm and 'WHISPER' or 'GUILD', Sender)
-		elseif Message == 'AISM_GUILD_RegistResponse' then
-			self.GuildMemberData[Sender] = true
-		elseif Message == 'AISM_GUILD_UnregistME' then
-			self.GuildMemberData[Sender] = nil
-			self.CurrentInspectData[Sender] = nil
-		elseif Message:find('AISM_DataRequestForInspecting:') then
-			local needplayerName, needplayerRealm = Message:match('^.+:(.+)-(.+)$')
-
-			if needplayerName == playerName and needplayerRealm == playerRealm then
-				local TableToSend = {}
-
-				for Index, Data in pairs(self.PlayerData) do
-					TableToSend[Index] = Data
-				end
-
-				self:SettingInspectData(TableToSend)
+
+		if Message:find('AISM_') then
+			if Message == 'AISM_Check' then
+				self.AISMUserList[Sender] = true
+				SendAddonMessage('AISM', 'AISM_CheckResponse', 'WHISPER', Sender)
+			elseif Message == 'AISM_CheckResponse' then
+				self.AISMUserList[Sender] = true
+			elseif Message == 'AISM_UnregistME' then
+				self.AISMUserList[Sender] = nil
+				self.GroupMemberData[Sender] = nil
+			elseif Message == 'AISM_GUILD_Check' then
+				self.AISMUserList[Sender] = 'GUILD'
+				SendAddonMessage('AISM', 'AISM_GUILD_CheckResponse', SenderRealm == playerRealm and 'WHISPER' or 'GUILD', Sender)
+			elseif Message == 'AISM_GUILD_CheckResponse' then
+				self.AISMUserList[Sender] = 'GUILD'
+			elseif Message == 'AISM_GUILD_UnregistME' then
+				self.AISMUserList[Sender] = nil
+				self.CurrentInspectData[Sender] = nil
+			elseif Message:find('AISM_DataRequestForInspecting:') then
+				local needplayerName, needplayerRealm = Message:match('^.+:(.+)-(.+)$')

-				self:SendData(TableToSend, Prefix, Channel, Sender)
+				if needplayerName == playerName and needplayerRealm == playerRealm then
+					local TableToSend = {}
+
+					for Index, Data in pairs(self.PlayerData) do
+						TableToSend[Index] = Data
+					end
+
+					self:SettingInspectData(TableToSend)
+
+					self:SendData(TableToSend, Prefix, Channel, Sender)
+				end
 			end
 		else
 			local TableToSave, NeedResponse, Group, stringTable
@@ -714,25 +723,25 @@ if not AISM then
 				return
 			else
 				Message = (self.RemainMessage[Sender] or '')..Message
-
+
 				for DataType, DataString in Message:gmatch('%{(.-):(.-)%}') do
 					if self.DataTypeTable[DataType] then
-						Message = string.gsub(Message, '%{'..DataType..':.-%}', '')
+						Message = Message:gsub('%{'..DataType..':.-%}', '')
 						Group = DataType:match('^.+(%d)$')
 						stringTable = { strsplit('/', DataString) }
-
+
 						for Index, Data in pairs(stringTable) do
 							if tonumber(Data) then
 								stringTable[Index] = tonumber(Data)
 							end
 						end
-
+
 						if Group and self.DataTypeTable[DataType] ~= 'Gear' then -- Prepare group setting
 							Group = tonumber(Group)
 							TableToSave[(self.DataTypeTable[DataType])] = TableToSave[(self.DataTypeTable[DataType])] or {}
 							TableToSave[(self.DataTypeTable[DataType])][Group] = TableToSave[(self.DataTypeTable[DataType])][Group] or {}
 						end
-
+
 						if self.DataTypeTable[DataType] == 'Profession' then
 							if stringTable[1] == 'F' then
 								TableToSave.Profession[Group].Name = EMPTY
@@ -776,12 +785,13 @@ if not AISM then
 							end

 							TableToSave.Gear[DataType] = {
-								['ItemLink'] = stringTable[1] ~= 'F' and stringTable[1],
-								['Transmogrify'] = stringTable[2] == 'ND' and 'NotDisplayed' or stringTable[2] ~= 0 and stringTable[2],
-								['Gem1'] = stringTable[3] ~= 0 and stringTable[3],
-								['Gem2'] = stringTable[4] ~= 0 and stringTable[4],
-								['Gem3'] = stringTable[5] ~= 0 and stringTable[5],
+								['ItemLink'] = stringTable[1] ~= 'F' and stringTable[1] or nil,
+								['Transmogrify'] = stringTable[2] == 'ND' and 'NotDisplayed' or stringTable[2] ~= 0 and stringTable[2] or nil
 							}
+
+							for i = 1, MAX_NUM_SOCKETS do
+								TableToSave.Gear[DataType]['Gem'..i] = stringTable[i + 2] ~= 0 and stringTable[i + 2] or nil
+							end
 						elseif self.DataTypeTable[DataType] == 'SetItemData' then
 							TableToSave.SetItem = TableToSave.SetItem or {}

@@ -837,7 +847,7 @@ if not AISM then
 						end
 					end
 				end
-
+
 				if Message == '' then
 					for funcName, func in pairs(self.RegisteredFunction) do
 						func(Sender, TableToSave)
@@ -854,36 +864,18 @@ if not AISM then
 			end
 		end
 	end
-
-	local prefix, message, channel, sender, needUpdate, updateData
+
+
+	local Prefix, Message, Channel, Sender, Type
 	AISM:SetScript('OnEvent', function(self, Event, ...)
-		if Event == 'PLAYER_LOGIN' then
-			self:GetPlayerCurrentGroupMode()
-			self:GetCurrentInstanceType()
+		if Event == 'VARIABLES_LOADED' then
 			isHelmDisplayed = ShowingHelm() == 1
 			isCloakDisplayed = ShowingCloak() == 1
-		elseif Event == 'PLAYER_GUILD_UPDATE' then
-			if IsInGuild() then
-				self.needSendDataGuild = true
-				self:Show()
-				self:UnregisterEvent('PLAYER_GUILD_UPDATE')
-			end
-		elseif Event == 'CHAT_MSG_ADDON' then
-			Prefix, Message, Channel, Sender = ...

-			if (Prefix == 'AISM' or Prefix == 'AISM_Inspect') and Sender ~= playerName..'-'..playerRealm then
-				self:Receiver(Prefix, Message, Channel, Sender)
-			elseif not self.Initialize and Prefix == 'AISM' and Message == 'AISM_Initialize' and Sender == playerName..'-'..playerRealm then
-				self.Initialize = true
-
-				if IsInGuild() then
-					self.needSendDataGuild = true
-					self:Show()
-				else
-					self:RegisterEvent('PLAYER_GUILD_UPDATE')
-				end
-
-			end
+			self:UnregisterEvent('VARIABLES_LOADED')
+		elseif Event == 'PLAYER_LOGIN' then
+			self:GetPlayerCurrentGroupMode()
+			self:GetCurrentInstanceType()
 		elseif Event == 'PLAYER_LOGOUT' then
 			if IsInGuild() then
 				SendAddonMessage('AISM', 'AISM_GUILD_UnregistME', 'GUILD')
@@ -891,21 +883,49 @@ if not AISM then
 			if self.CurrentGroupMode ~= 'NoGroup' then
 				SendAddonMessage('AISM', 'AISM_UnregistME', IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and 'INSTANCE_CHAT' or string.upper(self.CurrentGroupMode))
 			end
+		elseif Event == 'CHAT_MSG_SYSTEM' then
+			Message = ...
+			Type = Message:find(GuildLeaveKey) and 'GUILD' or Message:find(PlayerOfflineKey) and 'OFFLINE' or nil
+
+			if Type then
+				local SenderRealm
+
+				Sender = Message:match(GuildLeaveKey) or Message:match(PlayerOfflineKey)
+				Sender = Sender:gsub('@', '-')
+				Sender, SenderRealm = strsplit('-', Sender)
+				Sender = Sender..(SenderRealm and SenderRealm ~= '' and SenderRealm ~= playerRealm and '-'..SenderRealm or '')
+
+				for userName in pairs(self.AISMUserList) do
+					if userName == Sender then
+						self.AISMUserList[userName] = Type == 'GUILD' and true or nil
+
+						return
+					end
+				end
+			end
+		elseif Event == 'CHAT_MSG_ADDON' then
+			Prefix, Message, Channel, Sender = ...
+
+			if (Prefix == 'AISM' or Prefix == 'AISM_Inspect') and Sender ~= playerName..'-'..playerRealm then
+				self:Receiver(Prefix, Message, Channel, Sender)
+			end
 		elseif Event == 'GROUP_ROSTER_UPDATE' then
 			self:GetPlayerCurrentGroupMode()
 			self:Show()
 		elseif Event == 'PLAYER_ENTERING_WORLD' or Event == 'ZONE_CHANGED_NEW_AREA' then
 			self:GetCurrentInstanceType()
 			self:Show()
-		end
 	end)
+	AISM:RegisterEvent('VARIABLES_LOADED')
 	AISM:RegisterEvent('PLAYER_LOGIN')
 	AISM:RegisterEvent('PLAYER_LOGOUT')
+	AISM:RegisterEvent('CHAT_MSG_SYSTEM')
 	AISM:RegisterEvent('CHAT_MSG_ADDON')
 	AISM:RegisterEvent('GROUP_ROSTER_UPDATE')
 	AISM:RegisterEvent('PLAYER_ENTERING_WORLD')
 	AISM:RegisterEvent('ZONE_CHANGED_NEW_AREA')
-
+
+
 	function AISM:RegisterInspectDataRequest(Func, funcName, PreserveFunction)
 		if type(Func) == 'function' then
 			funcName = funcName or #self.RegisteredFunction + 1
@@ -919,7 +939,7 @@ if not AISM then
 			end
 		end
 	end
-
+
 	RegisterAddonMessagePrefix('AISM')
 	RegisterAddonMessagePrefix('AISM_Inspect')
 end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/characterframe/core.lua b/ElvUI_SLE/modules/characterframe/core.lua
index 163533b..b340eeb 100644
--- a/ElvUI_SLE/modules/characterframe/core.lua
+++ b/ElvUI_SLE/modules/characterframe/core.lua
@@ -112,6 +112,40 @@ SLArmoryConstants = {

 			GameTooltip:Show()
 		end
+		['Transmogrify_OnEnter'] = function(self)
+			self.Texture:SetVertexColor(1, .8, 1)
+
+			if self.Link then
+				if GetItemInfo(self.Link) then
+					GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
+					GameTooltip:SetHyperlink(select(2, GetItemInfo(self.Link)))
+					GameTooltip:Show()
+				else
+					self:SetScript('OnUpdate', function()
+						if GetItemInfo(self.Link) then
+							SLArmoryConstants.CommonScript.Transmogrify_OnEnter(self)
+							self:SetScript('OnUpdate', nil)
+						end
+					end)
+				end
+			end
+		end,
+		['Transmogrify_OnLeave'] = function(self)
+			self:SetScript('OnUpdate', nil)
+			self.Texture:SetVertexColor(1, .5, 1)
+
+			GameTooltip:Hide()
+		end,
+		['ClearTooltip'] = function(tooltip)
+			local tooltipName = tooltip:GetName()
+
+			tooltip:ClearLines()
+			for i = 1, 10 do
+				_G[tooltipName..'Texture'..i]:SetTexture(nil)
+				_G[tooltipName..'Texture'..i]:ClearAllPoints()
+				_G[tooltipName..'Texture'..i]:Point('TOPLEFT', tooltip)
+			end
+		end,
 	},

 	['Toolkit'] = {
diff --git a/ElvUI_SLE/modules/characterframe/inspectframe.lua b/ElvUI_SLE/modules/characterframe/inspectframe.lua
index ff001da..6793e9d 100644
--- a/ElvUI_SLE/modules/characterframe/inspectframe.lua
+++ b/ElvUI_SLE/modules/characterframe/inspectframe.lua
@@ -9,6 +9,7 @@ local S = E:GetModule('Skins')
 --------------------------------------------------------------------------------
 local SLI = CreateFrame('Frame', 'KnightInspect', E.UIParent)
 local ENI = _G['EnhancedNotifyInspectFrame'] or { ['CancelInspect'] = function() end, }
+local ButtonName = L['Knight Button']
 local C = SLArmoryConstants

 local CORE_FRAME_LEVEL = 10
@@ -136,13 +137,22 @@ function SLI:ChangePage(Type)
 	end
 end

+
 SLI.EquipmentSlot_OnEnter = function(self)
+	if C.CanTransmogrifySlot[self.SlotName] and type(self.TransmogrifyLink) == 'number' and not GetItemInfo(self.TransmogrifyLink) then
+		self:SetScript('OnUpdate', function()
+			if GetItemInfo(self.TransmogrifyLink) then
+				SLI.EquipmentSlot_OnEnter(self)
+				self:SetScript('OnUpdate', nil)
+			end
+		end)
+		return
+	end
+
 	if self.Link then
 		GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
 		GameTooltip:SetHyperlink(self.Link)

-		--ITEM_SOULBOUND
-
 		local CurrentLineText, SetName
 		for i = 1, GameTooltip:NumLines() do
 			CurrentLineText = _G['GameTooltipTextLeft'..i]:GetText()
@@ -179,22 +189,21 @@ SLI.EquipmentSlot_OnEnter = function(self)
 				end

 				break
+			elseif C.CanTransmogrifySlot[self.SlotName] and C.ItemBindString[CurrentLineText] and self.TransmogrifyAnchor.Link then
+				_G['GameTooltipTextLeft'..i]:SetText(E:RGBToHex(1, .5, 1)..format(TRANSMOGRIFIED, GetItemInfo(self.TransmogrifyAnchor.Link) or self.TransmogrifyAnchor.Link)..'|r|n'..CurrentLineText)
 			end
 		end

 		GameTooltip:Show()
 	end
 end
-
 SLI.ScrollFrame_OnMouseWheel = function(self, spinning)
 	local Page = self:GetScrollChild()
 	local PageHeight = Page:GetHeight()
 	local WindowHeight = self:GetHeight()

-	self.Offset = self.Offset or 0
-
 	if PageHeight > WindowHeight then
-		self.Offset = self.Offset - spinning * 5
+		self.Offset = (self.Offset or 0) - spinning * 5

 		Page:ClearAllPoints()
 		if self.Offset > PageHeight - WindowHeight then
@@ -215,31 +224,11 @@ SLI.ScrollFrame_OnMouseWheel = function(self, spinning)
 end
 SLI.Category_OnClick = function(self)
 	self = self:GetParent()
+
 	self.Closed = not self.Closed

 	SLI:ReArrangeCategory()
 end
-
-SLI.GemSocket_OnEnter = function(self)
-	GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
-
-	self = self:GetParent()
-
-	if self.GemItemID then
-		if type(self.GemItemID) == 'number' then
-			GameTooltip:SetHyperlink(select(2, GetItemInfo(self.GemItemID)))
-		else
-			GameTooltip:ClearLines()
-			GameTooltip:AddLine(self.GemItemID)
-		end
-	elseif self.GemType then
-		GameTooltip:ClearLines()
-		GameTooltip:AddLine(_G['EMPTY_SOCKET_'..self.GemType])
-	end
-
-	GameTooltip:Show()
-end
-
 SLI.GemSocket_OnClick = function(self, button)
 	self = self:GetParent()

@@ -270,15 +259,6 @@ SLI.OnClick = function(self)
 	end
 end

-local function SetModifiedBackdrop(self)
-	if self.backdrop then self = self.backdrop end
-	self:SetBackdropBorderColor(unpack(E["media"].rgbvaluecolor))
-end
-
-local function SetOriginalBackdrop(self)
-	if self.backdrop then self = self.backdrop end
-	self:SetBackdropBorderColor(unpack(E["media"].bordercolor))
-end

 function SLI:CreateInspectFrame()
 	do --<< Core >>--
@@ -317,48 +297,20 @@ function SLI:CreateInspectFrame()
 		self.Tab = CreateFrame('Frame', nil, self)
 		self.Tab:Point('TOPLEFT', self, SPACING, -SPACING)
 		self.Tab:Point('BOTTOMRIGHT', self, 'TOPRIGHT', -SPACING, -(SPACING + TAB_HEIGHT))
-		--self.Tab:SetBackdrop({
-		--	bgFile = E.media.normTex,
-		--	edgeFile = E.media.blankTex,
-		--	tile = false, tileSize = 0, edgeSize = E.mult,
-		--	insets = { left = 0, right = 0, top = 0, bottom = 0}
-		--})
-		--self.Tab:SetBackdropBorderColor(unpack(E.media.bordercolor))
+		self.Tab:SetBackdrop({
+			bgFile = E.media.normTex,
+			edgeFile = E.media.blankTex,
+			tile = false, tileSize = 0, edgeSize = E.mult,
+			insets = { left = 0, right = 0, top = 0, bottom = 0}
+		})
+		self.Tab:SetBackdropBorderColor(0, 0, 0)
 		C.Toolkit.TextSetting(self.Tab, ' |cff2eb7e4S&L Inspect', { ['FontSize'] = 10, ['FontOutline'] = 'OUTLINE', }, 'LEFT', 6, 1)
 		self.Tab:SetScript('OnMouseDown', function() self:StartMoving() end)
 		self.Tab:SetScript('OnMouseUp', function() self:StopMovingOrSizing() end)
 	end

-	--S:HandleCloseButton
-	--My Modified One
 	do --<< Close Button >>--
 		self.Close = CreateFrame('Button', nil, self.Tab)
-		self.Close:StripTextures()
-		self.Close:CreateBackdrop('Default', true)
-		self.Close:Size(TAB_HEIGHT - 8)
-		self.Close:Point('RIGHT', -4, 0)
-		self.Close:HookScript('OnEnter', SetModifiedBackdrop)
-		self.Close:HookScript('OnLeave', SetOriginalBackdrop)
-		self.Close:SetScript('OnClick', function() HideUIPanel(self) end)
-		self.Close.text = self.Close:CreateFontString(nil, 'OVERLAY')
-		self.Close.text:SetFont([[Interface\AddOns\ElvUI\media\fonts\PT_Sans_Narrow.ttf]], 16, 'OUTLINE')
-		self.Close.text:SetText('x')
-		self.Close.text:SetJustifyH('CENTER')
-		self.Close.text:SetPoint('CENTER', self.Close, 'CENTER')
-
-		--self.Close:Size(TAB_HEIGHT - 8)
-		--self.Close:SetTemplate()
-		--self.Close.backdropTexture:SetVertexColor(0.1, 0.1, 0.1)
-		--self.Close:Point('RIGHT', -4, 0)
-		--C.Toolkit.TextSetting(self.Close, 'X', { ['FontSize'] = 13, }, 'CENTER', 1, 0)
-		--self.Close:SetScript('OnEnter', Button_OnEnter)
-		--self.Close:SetScript('OnLeave', Button_OnLeave)
-		--self.Close:SetScript('OnClick', function() HideUIPanel(self) end)
-		--self.Close.buttonString = 'X'
-	end
-	--Original
-	--do --<< Close Button >>--
-		--[[self.Close = CreateFrame('Button', nil, self.Tab)
 		self.Close:Size(TAB_HEIGHT - 8)
 		self.Close:SetTemplate()
 		self.Close.backdropTexture:SetVertexColor(0.1, 0.1, 0.1)
@@ -368,7 +320,7 @@ function SLI:CreateInspectFrame()
 		self.Close:SetScript('OnLeave', Button_OnLeave)
 		self.Close:SetScript('OnClick', function() HideUIPanel(self) end)
 		self.Close.buttonString = 'X'
-	end]]
+	end

 	do --<< Bottom Panel >>--
 		self.BP = CreateFrame('Frame', nil, self)
@@ -381,7 +333,7 @@ function SLI:CreateInspectFrame()
 			insets = { left = 0, right = 0, top = 0, bottom = 0}
 		})
 		self.BP:SetBackdropColor(0.09, 0.3, 0.45)
-		self.BP:SetBackdropBorderColor(unpack(E.media.bordercolor))
+		self.BP:SetBackdropBorderColor(0, 0, 0)
 		self.BP:SetFrameLevel(CORE_FRAME_LEVEL + 2)

 		self.MessageFrame = CreateFrame('ScrollFrame', nil, self.BP)
@@ -389,7 +341,6 @@ function SLI:CreateInspectFrame()
 		self.MessageFrame:Point('BOTTOMRIGHT', self.BP, -10, 1)
 		self.MessageFrame.UpdateInterval = 3
 		self.MessageFrame.ScrollSpeed = 1
-		self.MessageFrame:SetScript('OnEnter', function() self.MessageFrame.UpdatedTime = 0 end)

 		local PageWidth
 		local VisibleWidth
@@ -455,21 +406,9 @@ function SLI:CreateInspectFrame()
 				tile = false, tileSize = 0, edgeSize = E.mult,
 				insets = { left = 0, right = 0, top = 0, bottom = 0}
 			})
-			--self[buttonName]:SetBackdropBorderColor(unpack(E.media.bordercolor))
+			self[buttonName]:SetBackdropBorderColor(0, 0, 0)
 			self[buttonName]:SetFrameLevel(CORE_FRAME_LEVEL + 1)
 			C.Toolkit.TextSetting(self[buttonName], _G[buttonString], { ['FontSize'] = 9, ['FontOutline'] = 'OUTLINE' })
-			--Test
-			if self[buttonName].GetHighlightTexture and self[buttonName]:GetHighlightTexture() then
-				self[buttonName]:GetHighlightTexture():SetTexture(nil)
-			else
-				self[buttonName]:StripTextures()
-			end
-			self[buttonName].backdrop = CreateFrame("Frame", nil, self[buttonName])
-			self[buttonName].backdrop:SetTemplate("Default")
-			self[buttonName].backdrop:SetFrameLevel(self[buttonName]:GetFrameLevel() - 1)
-			self[buttonName].backdrop:Point("TOPLEFT", 10, E.PixelMode and -1 or -3)
-			self[buttonName].backdrop:Point("BOTTOMRIGHT", -10, 3)
-			--End Test
 			self[buttonName]:SetScript('OnEnter', Button_OnEnter)
 			self[buttonName]:SetScript('OnLeave', Button_OnLeave)
 			self[buttonName]:SetScript('OnClick', function() SLI:ChangePage(buttonName) end)
@@ -499,7 +438,8 @@ function SLI:CreateInspectFrame()
 		self.Bookmark.CheckedTexture:SetTexture('Interface\\Common\\ReputationStar.tga')
 		self.Bookmark.CheckedTexture:SetInside()
 		self.Bookmark:SetCheckedTexture(self.Bookmark.CheckedTexture)
-		self.Bookmark:Point('LEFT', self.Tab, 'BOTTOMLEFT', 7, -35)
+		self.Bookmark:Point('LEFT', self.Tab, 'BOTTOMLEFT', 7, -34)
+		self.Bookmark:Hide()
 	end

 	do --<< Texts >>--
@@ -507,6 +447,7 @@ function SLI:CreateInspectFrame()
 		C.Toolkit.TextSetting(self, nil, { ['Tag'] = 'Title', ['FontSize'] = 9, ['FontOutline'] = 'OUTLINE', }, 'BOTTOMLEFT', self.Name, 'TOPLEFT', 2, 5)
 		C.Toolkit.TextSetting(self, nil, { ['Tag'] = 'LevelRace', ['FontSize'] = 10, ['directionH'] = 'LEFT', }, 'BOTTOMLEFT', self.Name, 'BOTTOMRIGHT', 5, 2)
 		C.Toolkit.TextSetting(self, nil, { ['Tag'] = 'Guild', ['FontSize'] = 10, ['directionH'] = 'LEFT', }, 'TOPLEFT', self.Name, 'BOTTOMLEFT', 4, -5)
+		C.Toolkit.TextSetting(self, nil, { ['Tag'] = 'Realm', ['FontSize'] = 10, ['directionH'] = 'LEFT', }, 'BOTTOMLEFT', self.Name, 'TOPLEFT', 2, 14)
 		self.Guild:Point('RIGHT', self, -44, 0)
 	end

@@ -682,6 +623,26 @@ function SLI:CreateInspectFrame()
 				Slot.SocketWarning.Texture:SetTexture('Interface\\AddOns\\ElvUI_SLE\\media\\textures\\Warning-Small')
 				Slot.SocketWarning:SetScript('OnEnter', C.CommonScript.OnEnter)
 				Slot.SocketWarning:SetScript('OnLeave', C.CommonScript.OnLeave)
+
+				if C.CanTransmogrifySlot[slotName] then
+					Slot.TransmogrifyAnchor = CreateFrame('Button', nil, Slot.Gradation)
+					Slot.TransmogrifyAnchor:Size(12)
+					Slot.TransmogrifyAnchor:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+					Slot.TransmogrifyAnchor:Point('BOTTOM'..Slot.Direction, Slot)
+					Slot.TransmogrifyAnchor:SetScript('OnEnter', C.CommonScript.Transmogrify_OnEnter)
+					Slot.TransmogrifyAnchor:SetScript('OnLeave', C.CommonScript.Transmogrify_OnLeave)
+
+					Slot.TransmogrifyAnchor.Texture = Slot.TransmogrifyAnchor:CreateTexture(nil, 'OVERLAY')
+					Slot.TransmogrifyAnchor.Texture:SetInside()
+					Slot.TransmogrifyAnchor.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Anchor')
+					Slot.TransmogrifyAnchor.Texture:SetVertexColor(1, .5, 1)
+
+					if Slot.Direction == 'LEFT' then
+						Slot.TransmogrifyAnchor.Texture:SetTexCoord(0, 1, 0, 1)
+					else
+						Slot.TransmogrifyAnchor.Texture:SetTexCoord(1, 0, 0, 1)
+					end
+				end
 			end

 			self[slotName] = Slot
@@ -832,10 +793,10 @@ function SLI:CreateInspectFrame()
 				self.Info.Profession['Prof'..i].Bar:SetStatusBarTexture(E.media.normTex)
 				self.Info.Profession['Prof'..i].Bar:SetMinMaxValues(0, 600)

-				C.Toolkit.TextSetting(self.Info.Profession['Prof'..i], '257', { ['Tag'] = 'Level', ['FontSize'] = 10 }, 'TOP', self.Info.Profession['Prof'..i].Icon)
+				C.Toolkit.TextSetting(self.Info.Profession['Prof'..i], nil, { ['Tag'] = 'Level', ['FontSize'] = 10 }, 'TOP', self.Info.Profession['Prof'..i].Icon)
 				self.Info.Profession['Prof'..i].Level:Point('RIGHT', self.Info.Profession['Prof'..i].Bar)

-				C.Toolkit.TextSetting(self.Info.Profession['Prof'..i], 'JewelCrafting', { ['Tag'] = 'Name', ['FontSize'] = 10, ['directionH'] = 'LEFT' }, 'TOP', self.Info.Profession['Prof'..i].Icon)
+				C.Toolkit.TextSetting(self.Info.Profession['Prof'..i], nil, { ['Tag'] = 'Name', ['FontSize'] = 10, ['directionH'] = 'LEFT' }, 'TOP', self.Info.Profession['Prof'..i].Icon)
 				self.Info.Profession['Prof'..i].Name:Point('LEFT', self.Info.Profession['Prof'..i].Bar)
 				self.Info.Profession['Prof'..i].Name:Point('RIGHT', self.Info.Profession['Prof'..i].Level, 'LEFT', -SPACING, 0)
 			end
@@ -874,7 +835,6 @@ function SLI:CreateInspectFrame()
 			for _, Type in pairs({ '2vs2', '3vs3', '5vs5', 'RB' }) do
 				self.Info.PvP[Type] = CreateFrame('Frame', nil, self.Info.PvP.Page)
 				self.Info.PvP[Type]:SetFrameLevel(CORE_FRAME_LEVEL + 4)
-				--self.Info.PvP[Type]:Height(70)

 				self.Info.PvP[Type].Rank = self.Info.PvP.Page:CreateTexture(nil, 'OVERLAY')
 				self.Info.PvP[Type].Rank:SetTexture('Interface\\ACHIEVEMENTFRAME\\UI-ACHIEVEMENT-SHIELDS')
@@ -1195,7 +1155,7 @@ function SLI:CreateInspectFrame()
 		KnightInspect_UnitPopup.Highlight:SetBlendMode('ADD')
 		KnightInspect_UnitPopup.Highlight:SetAllPoints()
 		KnightInspect_UnitPopup:SetHighlightTexture(KnightInspect_UnitPopup.Highlight)
-		KnightInspect_UnitPopup:SetText('KnightInspect')
+		--KnightInspect_UnitPopup:SetText('KnightInspect')

 		KnightInspect_UnitPopup:SetScript('OnEnter', function()
 			UIDropDownMenu_StopCounting(DropDownList1)
@@ -1208,30 +1168,28 @@ function SLI:CreateInspectFrame()
 				self.Anchored = nil
 				self.Data = nil
 				self:SetParent(nil)
+				self:ClearAllPoints()
 				self:Hide()
 			end
 		end)
 		KnightInspect_UnitPopup:SetScript('OnClick', function(self)
 			local SendChannel

-			if AISM and AISM.GuildMemberData[self.Data.TableIndex] then
+			if AISM and AISM.AISMUserList[self.Data.TableIndex] then
 				if self.Data.Realm == E.myrealm then
 					SendChannel = 'WHISPER'
-				else
+				elseif AISM.AISMUserList[self.Data.TableIndex] == 'GUILD' then
 					SendChannel = 'GUILD'
-				end
-			elseif SLI.CurrentGroupMode ~= 'NoGroup' and AISM and type(AISM.GroupMemberData[self.Data.TableIndex]) == 'table' then
-				if self.Data.Realm == E.myrealm then
-					SendChannel = 'WHISPER'
-				else
+				elseif SLI.CurrentGroupMode ~= 'NoGroup' and type(AISM.GroupMemberData[self.Data.TableIndex]) == 'table' then
 					SendChannel = IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and 'INSTANCE_CHAT' or string.upper(SLI.CurrentGroupMode)
 				end
 			end

-			if AISM and SendChannel then
+			if SendChannel then
 				ENI.CancelInspect(self.Data.TableIndex)
 				SLI:UnregisterEvent('INSPECT_READY')

+				SLI.NeedModelSetting = true
 				SLI.CurrentInspectData = E:CopyTable({}, SLI.Default_CurrentInspectData)
 				AISM.CurrentInspectData[self.Data.TableIndex] = {
 					['UnitID'] = self.Data.Unit,
@@ -1259,9 +1217,11 @@ function SLI:CreateInspectFrame()
 				return
 			end

-			if AISM and (type(AISM.GroupMemberData[self.Data.TableIndex]) == 'table' or AISM.GuildMemberData[self.Data.TableIndex]) or self.Data.Unit and UnitIsVisible(self.Data.Unit) and UnitIsConnected(self.Data.Unit) and not UnitIsDeadOrGhost('player') then
+			if AISM and (type(AISM.GroupMemberData[self.Data.TableIndex]) == 'table' or AISM.AISMUserList[self.Data.TableIndex]) or self.Data.Unit and UnitIsVisible(self.Data.Unit) and UnitIsConnected(self.Data.Unit) and not UnitIsDeadOrGhost('player') then
+				self:SetText(C.Toolkit.Color_Value(ButtonName))
 				self:Enable()
 			else
+				self:SetText(ButtonName)
 				self:Disable()
 			end
 		end)
@@ -1287,13 +1247,14 @@ function SLI:CreateInspectFrame()
 				end

 				if not Button then
-					if DataTable.Unit and (UnitCanAttack('player', DataTable.Unit) or not UnitIsConnected(DataTable.Unit)) then
+					if DataTable.Unit and (UnitCanAttack('player', DataTable.Unit) or not UnitIsConnected(DataTable.Unit) or not UnitIsPlayer(DataTable.Unit)) then
 						if AISM then
+							AISM.AISMUserList[DataTable.TableIndex] = nil
 							AISM.GroupMemberData[DataTable.TableIndex] = nil
 						end

 						return
-					elseif DataTable.Unit or AISM and (AISM.GuildMemberData[DataTable.TableIndex] or AISM.GroupMemberData[DataTable.TableIndex]) then
+					elseif DataTable.Unit or AISM and (Menu.which == 'GUILD' or AISM.AISMUserList[DataTable.TableIndex] or AISM.GroupMemberData[DataTable.TableIndex]) then
 						Button = UIDropDownMenu_CreateInfo()
 						Button.notCheckable = 1
 						UIDropDownMenu_AddButton(Button)
@@ -1304,7 +1265,7 @@ function SLI:CreateInspectFrame()

 				if Button then
 					Button.value = 'KnightInspect'
-					Button:SetText('')
+					Button:SetText((' '):rep(strlen(ButtonName)))

 					KnightInspect_UnitPopup:Show()
 					KnightInspect_UnitPopup:SetParent('DropDownList1')
@@ -1315,6 +1276,14 @@ function SLI:CreateInspectFrame()
 					KnightInspect_UnitPopup:Point('BOTTOMRIGHT', Button)
 					KnightInspect_UnitPopup.Anchored = true
 					KnightInspect_UnitPopup.Data = DataTable
+
+					if AISM and not (AISM.AISMUserList[DataTable.TableIndex] or AISM.GroupMemberData[DataTable.TableIndex]) then
+						if DataTable.Unit and not (UnitCanAttack('player', DataTable.Unit) or not UnitIsConnected(DataTable.Unit) or not UnitIsPlayer(DataTable.Unit)) and DataTable.Realm == E.myrealm then
+							SendAddonMessage('AISM', 'AISM_Check', 'WHISPER', DataTable.Name)
+						elseif Menu.which == 'GUILD' then
+							SendAddonMessage('AISM', 'AISM_GUILD_Check', DataTable.Realm == E.myrealm and 'WHISPER' or 'GUILD', DataTable.Name)
+						end
+					end
 				end
 			end
 		end)
@@ -1330,6 +1299,7 @@ function SLI:CreateInspectFrame()
 	self.CreateInspectFrame = nil
 end

+
 SLI.INSPECT_HONOR_UPDATE = function(Event)
 	if Event or HasInspectHonorData() then
 		for i, Type in pairs({ '2vs2', '3vs3', '5vs5' }) do
@@ -1347,14 +1317,14 @@ SLI.INSPECT_HONOR_UPDATE = function(Event)
 	end
 end

+
 SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
-	local UnitID = SLI.CurrentInspectData.Name..(SLI.CurrentInspectData.Realm and '-'..SLI.CurrentInspectData.Realm or '')
-	local GUIDByUnitName = UnitGUID(UnitID)
+	local TableIndex = SLI.CurrentInspectData.Name..(SLI.CurrentInspectData.Realm and '-'..SLI.CurrentInspectData.Realm or '')
+	local UnitID = TableIndex
 	local Name, Realm = UnitFullName(UnitID)

-	if not GUIDByUnitName then
+	if not Name then
 		UnitID = SLI.CurrentInspectData.UnitID
-		GUIDByUnitName = UnitGUID(UnitID)
 		Name, Realm = UnitFullName(UnitID)
 	end

@@ -1362,19 +1332,13 @@ SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
 		_, _, _, _, _, Name, Realm = GetPlayerInfoByGUID(InspectedUnitGUID)
 	end

-	local TableIndex = Name..(Realm and Realm ~= '' and Realm ~= E.myrealm and '-'..Realm or '')
-
-	if InspectedUnitGUID ~= GUIDByUnitName then
-		if GUIDByUnitName and SLI.CurrentInspectData.Name == Name and SLI.CurrentInspectData.Realm == Realm then
-			SLI.CurrentInspectData.UnitGUID = GUIDByUnitName
-			return
-		else
+		if not (SLI.CurrentInspectData.Name == Name and SLI.CurrentInspectData.Realm == Realm and SLI.CurrentInspectData.UnitGUID == InspectedUnitGUID) then
+			if UnitGUID(UnitID) ~= SLI.CurrentInspectData.UnitGUID then
 			ENI.CancelInspect(TableIndex)
 			SLI:UnregisterEvent('INSPECT_READY')
 			SLI:UnregisterEvent('INSPECT_HONOR_UPDATE')
-
-			return
 		end
+		return
 	elseif HasInspectHonorData() then
 		SLI.INSPECT_HONOR_UPDATE()
 	end
@@ -1394,14 +1358,11 @@ SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
 			SlotLink = GetInventoryItemLink(UnitID, Slot.ID)

 			if not SlotLink then
-				needReinspect = true
+				needReinspect = 'SlotLink_NotLoaded' -- this will stop setting inspect frame
 			else
 				SLI.CurrentInspectData.Gear[SlotName].ItemLink = SlotLink

-				SLI.ScanTTForInspecting:ClearLines()
-				for i = 1, 10 do
-					_G['KnightInspectScanTT_ITexture'..i]:SetTexture(nil)
-				end
+				C.Toolkit.CommonScript.ClearTooltip(SLI.ScanTTForInspecting)
 				SLI.ScanTTForInspecting:SetInventoryItem(UnitID, Slot.ID)

 				TransmogrifiedItem = nil
@@ -1424,13 +1385,15 @@ SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
 						SetItemCount = tonumber(SetItemCount)
 						SetItemMax = tonumber(SetItemMax)

-						if SetItemCount > SetItemMax or SetItemMax == 1 then
+						if (SetItemCount > SetItemMax or SetItemMax == 1) and not needReinspect then
 							needReinspect = true
 							break
-						elseif CurrentSetItem[SetName] then
-							break
 						else
-							CurrentSetItem[SetName] = {}
+							if not (CurrentSetItem[SetName] or SLI.CurrentInspectData.SetItem[SetName]) and not needReinspect then
+								needReinspect = true
+							end
+
+							CurrentSetItem[SetName] = CurrentSetItem[SetName] or {}

 							for k = 1, SLI.ScanTTForInspecting:NumLines() do
 								tooltipText = _G['KnightInspectScanTT_ITextLeft'..(i+k)]:GetText()
@@ -1443,17 +1406,27 @@ SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
 									colorR, colorG, colorB = _G['KnightInspectScanTT_ITextLeft'..(i+k)]:GetTextColor()

 									if colorR > LIGHTYELLOW_FONT_COLOR.r - 0.01 and colorR < LIGHTYELLOW_FONT_COLOR.r + 0.01 and colorG > LIGHTYELLOW_FONT_COLOR.g - 0.01 and colorG < LIGHTYELLOW_FONT_COLOR.g + 0.01 and colorB > LIGHTYELLOW_FONT_COLOR.b - 0.01 and colorB < LIGHTYELLOW_FONT_COLOR.b + 0.01 then
-										CurrentSetItem[SetName][#CurrentSetItem[SetName] + 1] = LIGHTYELLOW_FONT_COLOR_CODE..tooltipText
+										tooltipText = LIGHTYELLOW_FONT_COLOR_CODE..tooltipText
 									else
-										CurrentSetItem[SetName][#CurrentSetItem[SetName] + 1] = GRAY_FONT_COLOR_CODE..tooltipText
+										tooltipText = GRAY_FONT_COLOR_CODE..tooltipText
+									end
+
+									if CurrentSetItem[SetName][k] and CurrentSetItem[SetName][k] ~= tooltipText and not needReinspect then
+										needReinspect = true
 									end
+
+									CurrentSetItem[SetName][k] = tooltipText
 								elseif tooltipText:find(C.ItemSetBonusKey) then
-									CurrentSetItem[SetName]['SetOption'..SetOptionCount] = tooltipText:match("^%((%d)%)%s.+:%s.+$") or true
+									tooltipText = tooltipText:match("^%((%d)%)%s.+:%s.+$") or true

+									if CurrentSetItem[SetName]['SetOption'..SetOptionCount] and CurrentSetItem[SetName]['SetOption'..SetOptionCount] ~= tooltipText and not needReinspect then
+										needReinspect = true
+									end
+
+									CurrentSetItem[SetName]['SetOption'..SetOptionCount] = tooltipText
 									SetOptionCount = SetOptionCount + 1
 								end
 							end
-
 							SLI.CurrentInspectData.SetItem[SetName] = CurrentSetItem[SetName]

 							break
@@ -1493,19 +1466,26 @@ SLI.INSPECT_READY = function(Event, InspectedUnitGUID)
 	SLI.CurrentInspectData.guildLevel, _, SLI.CurrentInspectData.guildNumMembers = GetInspectGuildInfo(UnitID)
 	SLI.CurrentInspectData.guildEmblem = { GetGuildLogoInfo(UnitID) }

-	if needReinspect then
+	if needReinspect  and needReinspect ~= true then
 		return
 	end

 	SLI.ForbidUpdatePvPInformation = nil
-	ENI.CancelInspect(TableIndex)
-
 	SLI:ShowFrame(SLI.CurrentInspectData)
-	SLI:UnregisterEvent('INSPECT_READY')
+
+	if needReinspect then
+		return
+	elseif SLI.ReinspectCount > 0 then
+		SLI.ReinspectCount = SLI.ReinspectCount - 1
+	else
+		ENI.CancelInspect(TableIndex)
+		SLI:UnregisterEvent('INSPECT_READY')
+	end
 end

+
 SLI.InspectUnit = function(UnitID)
-	if not UnitExists('mouseover') and UnitExists('target') then
+	if UnitID == 'mouseover' and not UnitExists('mouseover') and UnitExists('target') then
 		UnitID = 'target'
 	end

@@ -1532,39 +1512,30 @@ SLI.InspectUnit = function(UnitID)

 		SLI.CurrentInspectData.Realm = SLI.CurrentInspectData.Realm ~= '' and SLI.CurrentInspectData.Realm ~= E.myrealm and SLI.CurrentInspectData.Realm or nil

+		SLI.ReinspectCount = 1
+		SLI.NeedModelSetting = true
 		SLI.ForbidUpdatePvPInformation = true
 		SLI:RegisterEvent('INSPECT_READY')
 		SLI:RegisterEvent('INSPECT_HONOR_UPDATE')
 	end
 end

+
 function SLI:ShowFrame(DataTable)
-	local needUpdate, CheckItemInfoReceived
+	self.GET_ITEM_INFO_RECEIVED = nil
+	self:UnregisterEvent('GET_ITEM_INFO_RECEIVED')

 	for _, slotName in pairs(C.GearList) do
-		if DataTable.Gear[slotName] and DataTable.Gear[slotName].ItemLink then
-			_, CheckItemInfoReceived = GetItemInfo(DataTable.Gear[slotName].ItemLink)
-
-			if not CheckItemInfoReceived then
-				needUpdate = true
-
-				if not self.GET_ITEM_INFO_RECEIVED then
-					self.GET_ITEM_INFO_RECEIVED = function()
-						self:ShowFrame(DataTable)
-					end
-					SLI:RegisterEvent('GET_ITEM_INFO_RECEIVED')
-				end
-			end
+		if DataTable.Gear[slotName] and DataTable.Gear[slotName].ItemLink and not GetItemInfo(DataTable.Gear[slotName].ItemLink) then
+			self.GET_ITEM_INFO_RECEIVED = function() self:ShowFrame(DataTable) end
 		end
 	end

-	if needUpdate then
+	if self.GET_ITEM_INFO_RECEIVED then
+		self:RegisterEvent('GET_ITEM_INFO_RECEIVED')
 		return
 	end

-	self.GET_ITEM_INFO_RECEIVED = nil
-	SLI:UnregisterEvent('GET_ITEM_INFO_RECEIVED')
-
 	self.Updater:Show()
 	self.Updater:SetScript('OnUpdate', function()
 		if not self:InspectFrame_DataSetting(DataTable) then
@@ -1577,15 +1548,16 @@ function SLI:ShowFrame(DataTable)
 	end)
 end

+
 function SLI:InspectFrame_DataSetting(DataTable)
-	local needUpdate
+	local needUpdate, needUpdateList
 	local r, g, b

 	do --<< Equipment Slot and Enchant, Gem Setting >>--
 		local ErrorDetected
 		local ItemCount, ItemTotal = 0, 0
 		local Slot, ItemRarity, BasicItemLevel, TrueItemLevel, ItemUpgradeID, ItemTexture, IsEnchanted, CurrentLineText, GemCount_Default, GemCount_Enable, GemCount_Now, GemCount
-		local arg1, itemID, enchantID, _, _, _, _, arg2, arg3, arg4, arg5, arg6
+		local arg1, itemID, enchantID, arg2, arg3, arg4, arg5, arg6

 		-- Setting except shirt and tabard
 		for _, slotName in pairs(self.GearUpdated or C.GearList) do
@@ -1593,7 +1565,7 @@ function SLI:InspectFrame_DataSetting(DataTable)
 				Slot = self[slotName]

 				do --<< Clear Setting >>--
-					ErrorDetected, TrueItemLevel, IsEnchanted, ItemUpgradeID, ItemTexture, r, g, b = nil, nil, nil, nil, nil, 0, 0, 0
+					needUpdate, ErrorDetected, TrueItemLevel, IsEnchanted, ItemUpgradeID, ItemTexture, r, g, b = nil, nil, nil, nil, nil, nil, 0, 0, 0

 					Slot.Link = nil
 					Slot.ItemLevel:SetText(nil)
@@ -1619,10 +1591,7 @@ function SLI:InspectFrame_DataSetting(DataTable)
 					do --<< Gem Parts >>--
 						arg1, itemID, enchantID, _, _, _, _, arg2, arg3, arg4, arg5, arg6 = strsplit(':', Slot.Link)

-						self.ScanTT:ClearLines()
-						for i = 1, 10 do
-							_G['KnightInspectScanTTTexture'..i]:SetTexture(nil)
-						end
+						C.Toolkit.CommonScript.ClearTooltip(self.ScanTT)
 						self.ScanTT:SetHyperlink(format('%s:%s:%d:0:0:0:0:%s:%s:%s:%s:%s', arg1, itemID, enchantID, arg2, arg3, arg4, arg5, arg6))

 						GemCount_Default, GemCount_Now, GemCount = 0, 0, 0
@@ -1646,10 +1615,7 @@ function SLI:InspectFrame_DataSetting(DataTable)
 							Slot['Socket'..GemCount_Enable].GemType = 'PRISMATIC'
 						end

-						self.ScanTT:ClearLines()
-						for i = 1, 10 do
-							_G['KnightInspectScanTTTexture'..i]:SetTexture(nil)
-						end
+						C.Toolkit.CommonScript.ClearTooltip(self.ScanTT)
 						self.ScanTT:SetHyperlink(Slot.Link)

 						-- Apply current item's gem setting
@@ -1665,30 +1631,28 @@ function SLI:InspectFrame_DataSetting(DataTable)
 								Slot['Socket'..i].Socket:SetBackdropBorderColor(1, 1, 1)
 							end

-							if ItemTexture then
+							CurrentLineText = select(2, _G['KnightInspectScanTTTexture'..i]:GetPoint())
+							CurrentLineText = DataTable.Gear[slotName]['Gem'..i] or CurrentLineText ~= self.ScanTT and CurrentLineText.GetText and CurrentLineText:GetText():gsub('|cff......', ''):gsub('|r', '') or nil
+
+							if CurrentLineText then
 								Slot['Socket'..i]:Show()
 								GemCount_Now = GemCount_Now + 1
 								Slot.SocketWarning:Point(Slot.Direction, Slot['Socket'..i], (Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 3 or -3, 0)
-
-								if DataTable.Gear[slotName]['Gem'..i] then
+
+								ItemTexture = ItemTexture or DataTable.Gear[slotName]['Gem'..i] and select(10, GetItemInfo(DataTable.Gear[slotName]['Gem'..i])) or nil
+
+								if not ItemTexture then
+									needUpdate = true
+								elseif not C.EmptySocketString[CurrentLineText] then
 									GemCount = GemCount + 1
+									Slot['Socket'..i].GemItemID = CurrentLineText
 									Slot['Socket'..i].Texture:SetTexture(ItemTexture)
-									Slot['Socket'..i].GemItemID = DataTable.Gear[slotName]['Gem'..i]
-								else
-									CurrentLineText = select(2, _G['KnightInspectScanTTTexture'..i]:GetPoint()):GetText()
-
-									if not C.EmptySocketString[CurrentLineText] then
-										GemCount = GemCount + 1
-										Slot['Socket'..i].Texture:SetTexture(ItemTexture)
-										Slot['Socket'..i].GemItemID = CurrentLineText
-									end
 								end
 							end
 						end

 						if GemCount_Now < GemCount_Default then -- ItemInfo not loaded
-							needUpdate = needUpdate or {}
-							needUpdate[#needUpdate + 1] = slotName
+							needUpdate = true
 						end
 					end

@@ -1806,6 +1770,16 @@ function SLI:InspectFrame_DataSetting(DataTable)
 					end
 				end

+				if Slot.TransmogrifyAnchor then --<< Transmogrify Parts >>--
+					Slot.TransmogrifyAnchor.Link = DataTable.Gear[slotName].Transmogrify ~= 'NotDisplayed' and DataTable.Gear[slotName].Transmogrify
+
+					if type(Slot.TransmogrifyAnchor.Link) == 'number' then
+						Slot.TransmogrifyAnchor:Show()
+					else
+						Slot.TransmogrifyAnchor:Hide()
+					end
+				end
+
 				-- Change Gradation
 				if ErrorDetected then
 					if Slot.Direction == 'LEFT' then
@@ -1823,6 +1797,11 @@ function SLI:InspectFrame_DataSetting(DataTable)

 				Slot.Texture:SetTexture(ItemTexture or Slot.EmptyTexture)
 				Slot:SetBackdropBorderColor(r, g, b)
+
+				if needUpdate then
+					needUpdateList = needUpdateList or {}
+					needUpdateList[#needUpdateList + 1] = slotName
+				end
 			end
 		end

@@ -1843,7 +1822,6 @@ function SLI:InspectFrame_DataSetting(DataTable)

 		self.SetItem = E:CopyTable({}, SLI.CurrentInspectData.SetItem)
 		self.Character.AverageItemLevel:SetText('|c'..RAID_CLASS_COLORS[DataTable.Class].colorStr..STAT_AVERAGE_ITEM_LEVEL..'|r: '..format('%.2f', ItemTotal / ItemCount))
-		--self.Character.AverageItemLevel:SetText(C.Toolkit.Color_Value(STAT_AVERAGE_ITEM_LEVEL)..' : '..format('%.2f', ItemTotal / ItemCount))
 	end

 	if needUpdate then
@@ -1856,8 +1834,10 @@ function SLI:InspectFrame_DataSetting(DataTable)
 	r, g, b = RAID_CLASS_COLORS[DataTable.Class].r, RAID_CLASS_COLORS[DataTable.Class].g, RAID_CLASS_COLORS[DataTable.Class].b

 	do --<< Basic Information >>--
-		self.Title:SetText((DataTable.Realm and DataTable.Realm ~= E.myrealm and DataTable.Realm..L[" Server "] or '')..'|cff93daff'..(DataTable.Title and string.gsub(DataTable.Title, DataTable.Name, '') or ''))
+		self.Title:SetText((DataTable.Realm and DataTable.Realm ~= E.myrealm and L["Server: "]..DataTable.Realm or '')..'|cff93daff'..(DataTable.Title and string.gsub(DataTable.Title, DataTable.Name, '') or ''))
+		--self.Title:SetText((DataTable.Realm and DataTable.Realm ~= E.myrealm and DataTable.Realm..L[" Server "] or '')..'|cff93daff'..(DataTable.Title and string.gsub(DataTable.Title, DataTable.Name, '') or ''))
 		self.Guild:SetText(DataTable.guildName and '<|cff2eb7e4'..DataTable.guildName..'|r>  [|cff2eb7e4'..DataTable.guildRankName..'|r]' or '')
+		self.Realm:SetText((DataTable.Realm and DataTable.Realm ~= E.myrealm and L["Server: "]..DataTable.Realm or ''))
 	end

 	do --<< Information Page Setting >>--
@@ -1920,18 +1900,23 @@ function SLI:InspectFrame_DataSetting(DataTable)

 			Name = nil

-			if DataTable.Specialization[i].SpecializationID then
+			if DataTable.Specialization[i].SpecializationID and DataTable.Specialization[i].SpecializationID ~= 0 then
 				_, Name, _, Texture = GetSpecializationInfoByID(DataTable.Specialization[i].SpecializationID)

 				if Name then
-					SpecRole = C.ClassRole[DataTable.Class][Name].Role
+					if C.ClassRole[DataTable.Class][Name] then
+
+						SpecRole = C.ClassRole[DataTable.Class][Name].Role

-					if i == SpecGroup then
-						Color = C.ClassRole[DataTable.Class][Name].Color
-						self.SpecIcon:SetTexture(Texture)
-					end
+						if i == SpecGroup then
+							Color = C.ClassRole[DataTable.Class][Name].Color
+							self.SpecIcon:SetTexture(Texture)
+						end

-					Name = (SpecRole == 'Tank' and '|TInterface\\AddOns\\ElvUI\\media\\textures\\tank.tga:16:16:-3:0|t' or SpecRole == 'Healer' and '|TInterface\\AddOns\\ElvUI\\media\\textures\\healer.tga:16:16:-3:-1|t' or '|TInterface\\AddOns\\ElvUI\\media\\textures\\dps.tga:16:16:-2:-1|t')..Name
+						Name = (SpecRole == 'Tank' and '|TInterface\\AddOns\\ElvUI\\media\\textures\\tank.tga:16:16:-3:0|t' or SpecRole == 'Healer' and '|TInterface\\AddOns\\ElvUI\\media\\textures\\healer.tga:16:16:-3:-1|t' or '|TInterface\\AddOns\\ElvUI\\media\\textures\\dps.tga:16:16:-2:-1|t')..Name
+					else
+						self.Spec.Message = L['Specialization data seems to be corrupt.  Please inspect again.']
+					end
 				end
 			end

@@ -1956,30 +1941,30 @@ function SLI:InspectFrame_DataSetting(DataTable)
 	end

 	do --<< Model and Frame Setting When InspectUnit Changed >>--
-		if DataTable.UnitID and UnitIsVisible(DataTable.UnitID) then
+		if DataTable.UnitID and UnitIsVisible(DataTable.UnitID) and SLI.NeedModelSetting then
 			self.Model:SetUnit(DataTable.UnitID)
-			self.Character.Message = nil
+			--self.Character.Message = nil
 			--self.Character.Message = 'This is a test string. When contained string is too long then string will scrolling. If you check this scrolling ingame then erase this string part and make a nil. Like this : "self.Character.Message = nil". Congratulation your birthday Trevor :D'
-		else
+		elseif SLI.NeedModelSetting then
+			self.Model:SetUnit('player')
 			self.Model:SetCustomRace(self.ModelList[DataTable.RaceID].RaceID, DataTable.GenderID - 2)
 			self.Model:TryOn(HeadSlotItem)
 			self.Model:TryOn(BackSlotItem)
-			self.Model:UndressSlot(self.HeadSlot.ID)
-			self.Model:UndressSlot(self.BackSlot.ID)
 			self.Model:Undress()

 			for _, slotName in pairs(C.GearList) do
-				if DataTable.Gear[slotName].ItemLink then
-					if type(DataTable.Gear[slotName].Transmogrify) == 'number' then
-						self.Model:TryOn(DataTable.Gear[slotName].Transmogrify)
-					elseif not (DataTable.Gear[slotName].Transmogrify and DataTable.Gear[slotName].Transmogrify == 'NotDisplayed') then
-						self.Model:TryOn(DataTable.Gear[slotName].ItemLink)
-					end
+				if type(DataTable.Gear[slotName].Transmogrify) == 'number' then
+					self.Model:TryOn(DataTable.Gear[slotName].Transmogrify)
+				elseif DataTable.Gear[slotName].ItemLink and not (DataTable.Gear[slotName].Transmogrify and DataTable.Gear[slotName].Transmogrify == 'NotDisplayed') then
+					self.Model:TryOn(DataTable.Gear[slotName].ItemLink)
+				else
+					self.Model:UndressSlot(self[slotName].ID)
 				end
 			end

-			self.Character.Message = L["Character model may differ because it was constructed by the inspect data."]
+			self.Character.Message = L['Character model may differ because it was constructed by the inspect data.']
 		end
+		SLI.NeedModelSetting = nil

 		if not (self.LastDataSetting and self.LastDataSetting == DataTable.Name..(DataTable.Realm and '-'..DataTable.Realm or '')) then
 			--<< Initialize Inspect Page >>--
@@ -2024,6 +2009,7 @@ function SLI:InspectFrame_DataSetting(DataTable)
 	self.LastDataSetting = DataTable.Name..(DataTable.Realm and '-'..DataTable.Realm or '')
 end

+
 function SLI:InspectFrame_PvPSetting(DataTable)
 	local Rating, Played, Won
 	local needExpand = 0
@@ -2085,6 +2071,7 @@ function SLI:InspectFrame_PvPSetting(DataTable)
 	self:ReArrangeCategory()
 end

+
 function SLI:ReArrangeCategory()
 	local InfoPage_Height = 0
 	local PrevCategory