Quantcast

THIS IS BOMB!! DON'T TOUCH THIS!!

Arstraea [03-09-15 - 02:20]
THIS IS BOMB!! DON'T TOUCH THIS!!
----------------------------------------------------
Start adapting armory functions and syncing from my project.
Filename
ElvUI_SLE/modules/Armory/CharacterArmory/CharacterArmory.lua
ElvUI_SLE/modules/Armory/CharacterArmory/Load_CharacterArmory.xml
ElvUI_SLE/modules/Armory/CharacterArmory/Profile.lua
ElvUI_SLE/modules/Armory/Constants.lua
ElvUI_SLE/modules/Armory/EnchantList.lua
ElvUI_SLE/modules/Armory/InspectArmory/Communication.lua
ElvUI_SLE/modules/Armory/InspectArmory/InspectArmory.lua
ElvUI_SLE/modules/Armory/InspectArmory/Load_InspectArmory.xml
ElvUI_SLE/modules/Armory/InspectArmory/NotifyInspect.lua
ElvUI_SLE/modules/Armory/InspectArmory/Profile.lua
ElvUI_SLE/modules/Armory/KnightFrame.lua
ElvUI_SLE/modules/Armory/Load_Armory.xml
diff --git a/ElvUI_SLE/modules/Armory/CharacterArmory/CharacterArmory.lua b/ElvUI_SLE/modules/Armory/CharacterArmory/CharacterArmory.lua
new file mode 100644
index 0000000..b451d9e
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/CharacterArmory/CharacterArmory.lua
@@ -0,0 +1,799 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+--------------------------------------------------------------------------------
+--<< KnightFrame : Upgrade Character Frame's Item Info like Wow-Armory		>>--
+--------------------------------------------------------------------------------
+local CA = CharacterArmory or CreateFrame('Frame', 'CharacterArmory', PaperDollFrame)
+
+local IsGemType = select(8, GetAuctionItemClasses())
+local SlotIDList = {}
+local InsetDefaultPoint = { CharacterFrameInsetRight:GetPoint() }
+local ExpandButtonDefaultPoint = { CharacterFrameExpandButton:GetPoint() }
+
+do --<< Button Script >>--
+	function CA:OnEnter()
+		if self.Link or self.Message then
+			GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
+
+			self:SetScript('OnUpdate', function()
+				GameTooltip:ClearLines()
+
+				if self.Link then
+					GameTooltip:SetHyperlink(self.Link)
+				end
+
+				if self.Link and self.Message then GameTooltip:AddLine(' ') end -- Line space
+
+				if self.Message then
+					GameTooltip:AddLine(self.Message, 1, 1, 1)
+				end
+
+				GameTooltip:Show()
+			end)
+		end
+	end
+
+
+	function CA:OnLeave()
+		self:SetScript('OnUpdate', nil)
+		GameTooltip:Hide()
+	end
+
+
+	function CA:GemSocket_OnEnter()
+		GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
+
+		local Parent = self:GetParent()
+
+		if Parent.GemItemID then
+			if type(Parent.GemItemID) == 'number' then
+				if GetItemInfo(Parent.GemItemID) then
+					GameTooltip:SetHyperlink(select(2, GetItemInfo(Parent.GemItemID)))
+					self:SetScript('OnUpdate', nil)
+				else
+					self:SetScript('OnUpdate', CA.GemSocket_OnEnter)
+					return
+				end
+			else
+				GameTooltip:ClearLines()
+				GameTooltip:AddLine('|cffffffff'..Parent.GemItemID)
+			end
+		elseif Parent.GemType then
+			GameTooltip:ClearLines()
+			GameTooltip:AddLine('|cffffffff'.._G['EMPTY_SOCKET_'..Parent.GemType])
+		end
+
+		GameTooltip:Show()
+	end
+
+
+	function CA:GemSocket_OnClick(Button)
+		if CursorHasItem() then
+			CA.GemSocket_OnRecieveDrag(self)
+			return
+		else
+			self = self:GetParent()
+		end
+
+		if self.GemItemID then
+			local ItemName, ItemLink = GetItemInfo(self.GemItemID)
+
+			if not IsShiftKeyDown() then
+				SetItemRef(ItemLink, ItemLink, 'LeftButton')
+			else
+				if Button == 'RightButton' then
+					SocketInventoryItem(GetInventorySlotInfo(self.SlotName))
+				elseif HandleModifiedItemClick(ItemLink) then
+				elseif BrowseName and BrowseName:IsVisible() then
+					AuctionFrameBrowse_Reset(BrowseResetButton)
+					BrowseName:SetText(ItemName)
+					BrowseName:SetFocus()
+				end
+			end
+		end
+	end
+
+
+	function CA:GemSocket_OnRecieveDrag()
+		self = self:GetParent()
+
+		if CursorHasItem() then
+			local CursorType, _, ItemLink = GetCursorInfo()
+
+			if CursorType == 'item' and select(6, GetItemInfo(ItemLink)) == IsGemType then
+				SocketInventoryItem(GetInventorySlotInfo(self.SlotName))
+				ClickSocketButton(self.SocketNumber)
+			end
+		end
+	end
+
+
+	function CA:Transmogrify_OnEnter()
+		self.Texture:SetVertexColor(1, .8, 1)
+
+		GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
+		GameTooltip:SetHyperlink(self.Link)
+		GameTooltip:Show()
+	end
+
+
+	function CA:Transmogrify_OnLeave()
+		self.Texture:SetVertexColor(1, .5, 1)
+
+		GameTooltip:Hide()
+	end
+
+
+	function CA:Transmogrify_OnClick(Button)
+		local ItemName, ItemLink = GetItemInfo(self.Link)
+
+		if not IsShiftKeyDown() then
+			SetItemRef(ItemLink, ItemLink, 'LeftButton')
+		else
+			if HandleModifiedItemClick(ItemLink) then
+			elseif BrowseName and BrowseName:IsVisible() then
+				AuctionFrameBrowse_Reset(BrowseResetButton)
+				BrowseName:SetText(ItemName)
+				BrowseName:SetFocus()
+			end
+		end
+	end
+end
+
+
+function CA:Setup_CharacterArmory()
+	--<< Core >>--
+	self:Point('TOPLEFT', CharacterFrameInset, 10, 20)
+	self:Point('BOTTOMRIGHT', CharacterFrameInsetRight, 'BOTTOMLEFT', -10, 5)
+
+	--<< Updater >>--
+	local args
+	self:SetScript('OnEvent', function(self, Event, ...)
+		if Event == 'SOCKET_INFO_SUCCESS' or Event == 'ITEM_UPGRADE_MASTER_UPDATE' or Event == 'TRANSMOGRIFY_UPDATE' or Event == 'PLAYER_ENTERING_WORLD' then
+			self.GearUpdated = nil
+			self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+		elseif Event == 'UNIT_INVENTORY_CHANGED' then
+			args = ...
+
+			if args == 'player' then
+				self.GearUpdated = nil
+				self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+			end
+		elseif Event == 'PLAYER_EQUIPMENT_CHANGED' then
+			args = ...
+
+			self.GearUpdated = type(self.GearUpdated) == 'table' and self.GearUpdated or {}
+			self.GearUpdated[#self.GearUpdated + 1] = SlotIDList[args]
+			self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+		elseif Event == 'COMBAT_LOG_EVENT_UNFILTERED' then
+			_, Event, _, _, _, _, _, _, args = ...
+
+			if Event == 'ENCHANT_APPLIED' and args == E.myname then
+				self.GearUpdated = nil
+				self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+			end
+		elseif Event == 'UPDATE_INVENTORY_DURABILITY' then
+			self.DurabilityUpdated = nil
+			self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+		end
+	end)
+	self:SetScript('OnShow', self.CharacterArmory_DataSetting)
+	hooksecurefunc('CharacterFrame_Collapse', function() if Info.CharacterArmory_Activate and PaperDollFrame:IsShown() then CharacterFrame:SetWidth(448) end end)
+	hooksecurefunc('CharacterFrame_Expand', function() if Info.CharacterArmory_Activate and PaperDollFrame:IsShown() then CharacterFrame:SetWidth(650) end end)
+	hooksecurefunc('ToggleCharacter', function(frameType)
+		if frameType ~= 'PaperDollFrame' and frameType ~= 'PetPaperDollFrame' then
+			CharacterFrame:SetWidth(PANEL_DEFAULT_WIDTH)
+		elseif Info.CharacterArmory_Activate and frameType == 'PaperDollFrame' then
+			CharacterFrameInsetRight:SetPoint('TOPLEFT', CharacterFrameInset, 'TOPRIGHT', 110, 0)
+			CharacterFrameExpandButton:SetPoint('BOTTOMRIGHT', CharacterFrameInsetRight, 'BOTTOMLEFT', 0, 1)
+		else
+			CharacterFrameInsetRight:SetPoint(unpack(InsetDefaultPoint))
+			CharacterFrameExpandButton:SetPoint(unpack(ExpandButtonDefaultPoint))
+		end
+	end)
+	hooksecurefunc('PaperDollFrame_SetLevel', function()
+		if Info.CharacterArmory_Activate then
+			CharacterLevelText:SetText('|c'..RAID_CLASS_COLORS[E.myclass].colorStr..CharacterLevelText:GetText())
+
+			CharacterFrameTitleText:ClearAllPoints()
+			CharacterFrameTitleText:Point('TOP', self, 0, 23)
+			CharacterFrameTitleText:SetParent(self)
+			CharacterLevelText:ClearAllPoints()
+			CharacterLevelText:SetPoint('TOP', CharacterFrameTitleText, 'BOTTOM', 0, -13)
+			CharacterLevelText:SetParent(self)
+		end
+	end)
+
+	--<< Background >>--
+	self.BG = self:CreateTexture(nil, 'OVERLAY')
+	self.BG:SetInside()
+	self.BG:SetTexture(KF.db.Modules.Armory.Character.BackgroundImage)
+
+	--<< Change Model Frame's frameLevel >>--
+	CharacterModelFrame:SetFrameLevel(self:GetFrameLevel() + 2)
+
+	--<< Average Item Level >>--
+	KF:TextSetting(self, nil, { Tag = 'AverageItemLevel', FontSize = 12 }, 'BOTTOM', CharacterModelFrame, 'TOP', 0, 14)
+	local function ValueColorUpdate()
+		self.AverageItemLevel:SetText(KF:Color_Value(L['Average'])..' : '..format('%.2f', select(2, GetAverageItemLevel())))
+	end
+	E.valueColorUpdateFuncs[ValueColorUpdate] = true
+
+	-- Create each equipment slots gradation, text, gem socket icon.
+	local Slot
+	for i, SlotName in pairs(Info.Armory_Constants.GearList) do
+		-- Equipment Tag
+		Slot = CreateFrame('Frame', nil, self)
+		Slot:Size(130, 41)
+		Slot:SetFrameLevel(CharacterModelFrame:GetFrameLevel() + 1)
+		Slot.Direction = i%2 == 1 and 'LEFT' or 'RIGHT'
+		Slot.ID, Slot.EmptyTexture = GetInventorySlotInfo(SlotName)
+		Slot:Point(Slot.Direction, _G['Character'..SlotName], Slot.Direction == 'LEFT' and -1 or 1, 0)
+
+		-- Grow each equipment slot's frame level
+		_G['Character'..SlotName]:SetFrameLevel(Slot:GetFrameLevel() + 1)
+
+		-- Gradation
+		Slot.Gradation = Slot:CreateTexture(nil, 'OVERLAY')
+		Slot.Gradation:SetInside()
+		Slot.Gradation:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Gradation')
+		if Slot.Direction == 'LEFT' then
+			Slot.Gradation:SetTexCoord(0, 1, 0, 1)
+		else
+			Slot.Gradation:SetTexCoord(1, 0, 0, 1)
+		end
+
+		if SlotName ~= 'ShirtSlot' and SlotName ~= 'TabardSlot' then
+			-- Item Level
+			KF:TextSetting(Slot, nil, { Tag = 'ItemLevel', FontSize = 10, directionH = Slot.Direction }, 'TOP'..Slot.Direction, _G['Character'..SlotName], 'TOP'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 2 or -2, -1)
+
+			-- Enchantment Name
+			KF:TextSetting(Slot, nil, { Tag = 'ItemEnchant', FontSize = 8, directionH = Slot.Direction }, Slot.Direction, _G['Character'..SlotName], Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 2 or -2, 1)
+			Slot.EnchantWarning = CreateFrame('Button', nil, Slot)
+			Slot.EnchantWarning:Size(12)
+			Slot.EnchantWarning.Texture = Slot.EnchantWarning:CreateTexture(nil, 'OVERLAY')
+			Slot.EnchantWarning.Texture:SetInside()
+			Slot.EnchantWarning.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Warning-Small')
+			Slot.EnchantWarning:Point(Slot.Direction, Slot.ItemEnchant, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 3 or -3, 0)
+			Slot.EnchantWarning:SetScript('OnEnter', self.OnEnter)
+			Slot.EnchantWarning:SetScript('OnLeave', self.OnLeave)
+
+			-- Durability
+			KF:TextSetting(Slot, nil, { Tag = 'Durability', FontSize = 10, directionH = Slot.Direction }, 'BOTTOM'..Slot.Direction, _G['Character'..SlotName], 'BOTTOM'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 2 or -2, 3)
+
+			-- Gem Socket
+			for i = 1, MAX_NUM_SOCKETS do
+				Slot['Socket'..i] = CreateFrame('Frame', nil, Slot)
+				Slot['Socket'..i]:Size(12)
+				Slot['Socket'..i]:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				Slot['Socket'..i]:SetBackdropColor(0, 0, 0, 1)
+				Slot['Socket'..i]:SetBackdropBorderColor(0, 0, 0)
+				Slot['Socket'..i]:SetFrameLevel(CharacterModelFrame:GetFrameLevel() + 1)
+
+				Slot['Socket'..i].SlotName = SlotName
+				Slot['Socket'..i].SocketNumber = i
+
+				Slot['Socket'..i].Socket = CreateFrame('Button', nil, Slot['Socket'..i])
+				Slot['Socket'..i].Socket:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				Slot['Socket'..i].Socket:SetInside()
+				Slot['Socket'..i].Socket:SetFrameLevel(Slot['Socket'..i]:GetFrameLevel() + 1)
+				Slot['Socket'..i].Socket:RegisterForClicks('AnyUp')
+				Slot['Socket'..i].Socket:SetScript('OnEnter', self.OnEnter)
+				Slot['Socket'..i].Socket:SetScript('OnLeave', self.OnLeave)
+				Slot['Socket'..i].Socket:SetScript('OnClick', self.GemSocket_OnClick)
+				Slot['Socket'..i].Socket:SetScript('OnReceiveDrag', self.GemSocket_OnRecieveDrag)
+
+				Slot['Socket'..i].Texture = Slot['Socket'..i].Socket:CreateTexture(nil, 'OVERLAY')
+				Slot['Socket'..i].Texture:SetTexCoord(.1, .9, .1, .9)
+				Slot['Socket'..i].Texture:SetInside()
+			end
+			Slot.Socket2:Point(Slot.Direction, Slot.Socket1, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 1 or -1, 0)
+			Slot.Socket3:Point(Slot.Direction, Slot.Socket2, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 1 or -1, 0)
+
+			Slot.SocketWarning = CreateFrame('Button', nil, Slot)
+			Slot.SocketWarning:Size(12)
+			Slot.SocketWarning:RegisterForClicks('AnyUp')
+			Slot.SocketWarning.Texture = Slot.SocketWarning:CreateTexture(nil, 'OVERLAY')
+			Slot.SocketWarning.Texture:SetInside()
+			Slot.SocketWarning.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Warning-Small')
+			Slot.SocketWarning:SetScript('OnEnter', self.OnEnter)
+			Slot.SocketWarning:SetScript('OnLeave', self.OnLeave)
+
+			-- Transmogrify
+			if Info.Armory_Constants.CanTransmogrifySlot[SlotName] then
+				Slot.TransmogrifyAnchor = CreateFrame('Button', nil, Slot)
+				Slot.TransmogrifyAnchor:Size(12)
+				Slot.TransmogrifyAnchor:SetFrameLevel(Slot:GetFrameLevel() + 2)
+				Slot.TransmogrifyAnchor:Point('BOTTOM'..Slot.Direction, Slot, Slot.Direction == 'LEFT' and -2 or 2, -1)
+				Slot.TransmogrifyAnchor:SetScript('OnEnter', self.Transmogrify_OnEnter)
+				Slot.TransmogrifyAnchor:SetScript('OnLeave', self.Transmogrify_OnLeave)
+				Slot.TransmogrifyAnchor:SetScript('OnClick', self.Transmogrify_OnClick)
+
+				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
+
+				Slot.TransmogrifyAnchor:Hide()
+			end
+		end
+
+		SlotIDList[Slot.ID] = SlotName
+		self[SlotName] = Slot
+	end
+
+	-- GameTooltip for counting gem sockets and getting enchant effects
+	self.ScanTT = CreateFrame('GameTooltip', 'Knight_CharacterArmory_ScanTT', nil, 'GameTooltipTemplate')
+	self.ScanTT:SetOwner(UIParent, 'ANCHOR_NONE')
+
+	self.Setup_CharacterArmory = nil
+end
+
+
+function CA:CharacterArmory_DataSetting()
+	self.NeedUpdate = nil
+
+	if not self.DurabilityUpdated then
+		self.NeedUpdate = self:Update_Durability() or self.NeedUpdate
+	end
+
+	if self.GearUpdated ~= true then
+		self.NeedUpdate = self:Update_Gear() or self.NeedUpdate
+	end
+
+	if not self.NeedUpdate and self:IsShown() then
+		self:SetScript('OnUpdate', nil)
+	elseif self.NeedUpdate then
+		self:SetScript('OnUpdate', self.CharacterArmory_DataSetting)
+	end
+end
+
+
+function CA:Update_Durability()
+	local Slot, R, G, B, CurrentDurability, MaxDurability
+
+	for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+		Slot = self[SlotName]
+		CurrentDurability, MaxDurability = GetInventoryItemDurability(Slot.ID)
+
+		if CurrentDurability and MaxDurability then
+			R, G, B = E:ColorGradient((CurrentDurability / MaxDurability), 1, 0, 0, 1, 1, 0, 0, 1, 0)
+			Slot.Durability:SetFormattedText("%s%.0f%%|r", E:RGBToHex(R, G, B), (CurrentDurability / MaxDurability) * 100)
+			Slot.Socket1:Point('BOTTOM'..Slot.Direction, Slot.Durability, 'BOTTOM'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 3 or -3, -2)
+		elseif Slot.Durability then
+			Slot.Durability:SetText('')
+			Slot.Socket1:Point('BOTTOM'..Slot.Direction, _G['Character'..SlotName], 'BOTTOM'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 3 or -3, 3)
+		end
+	end
+
+	self.DurabilityUpdated = true
+end
+
+
+function CA:ClearTooltip(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
+
+
+function CA:Update_Gear()
+	--[[ Get Player Profession
+
+	local Prof1, Prof2 = GetProfessions()
+	local Prof1_Level, Prof2_Level = 0, 0
+	self.PlayerProfession = {}
+
+	if Prof1 then Prof1, _, Prof1_Level = GetProfessionInfo(Prof1) end
+	if Prof2 then Prof2, _, Prof2_Level = GetProfessionInfo(Prof2) end
+	if Prof1 and Info.Armory_Constants.ProfessionList[Prof1] then self.PlayerProfession[(Info.Armory_Constants.ProfessionList[Prof1].Key)] = Prof1_Level end
+	if Prof2 and Info.Armory_Constants.ProfessionList[Prof2] then self.PlayerProfession[(Info.Armory_Constants.ProfessionList[Prof2].Key)] = Prof2_Level end
+	]]
+	local ErrorDetected, NeedUpdate, NeedUpdateList, R, G, B
+	local Slot, ItemLink, ItemData, ItemRarity, BasicItemLevel, TrueItemLevel, ItemUpgradeID, ItemTexture, IsEnchanted, UsableEffect, CurrentLineText, GemID, GemCount_Default, GemCount_Enable, GemCount_Now, GemCount, IsTransmogrified, TransmogrifyItemID
+
+	for _, SlotName in pairs(self.GearUpdated or Info.Armory_Constants.GearList) do
+		if not (SlotName == 'ShirtSlot' or SlotName == 'TabardSlot') then
+			Slot = self[SlotName]
+			ItemLink = GetInventoryItemLink('player', Slot.ID)
+
+			do --<< Clear Setting >>--
+				NeedUpdate, ErrorDetected, TrueItemLevel, IsEnchanted, UsableEffect, ItemUpgradeID, ItemTexture = nil, nil, nil, nil, nil, nil, nil
+
+				Slot.ItemLevel:SetText(nil)
+				Slot.ItemEnchant:SetText(nil)
+				for i = 1, MAX_NUM_SOCKETS do
+					Slot['Socket'..i].Texture:SetTexture(nil)
+					Slot['Socket'..i].Socket.Link = nil
+					Slot['Socket'..i].GemItemID = nil
+					Slot['Socket'..i].GemType = nil
+					Slot['Socket'..i]:Hide()
+				end
+				Slot.EnchantWarning:Hide()
+				Slot.EnchantWarning.Message = nil
+				Slot.SocketWarning:Point(Slot.Direction, Slot.Socket1)
+				Slot.SocketWarning:Hide()
+				Slot.SocketWarning.Link = nil
+				Slot.SocketWarning.Message = nil
+
+				if Slot.TransmogrifyAnchor then
+					Slot.TransmogrifyAnchor.Link = nil
+					Slot.TransmogrifyAnchor:Hide()
+				end
+			end
+
+			if ItemLink then
+				if not ItemLink:find('%[%]') then -- sometimes itemLink is malformed so we need to update when crashed
+					do --<< Gem Parts >>--
+						ItemData = { strsplit(':', ItemLink) }
+						ItemData[4], ItemData[5], ItemData[6], ItemData[7] = 0, 0, 0, 0
+
+						for i = 1, #ItemData do
+							ItemData.FixedLink = (ItemData.FixedLink and ItemData.FixedLink..':' or '')..ItemData[i]
+						end
+
+						self:ClearTooltip(self.ScanTT)
+						self.ScanTT:SetHyperlink(ItemData.FixedLink)
+
+						GemCount_Default, GemCount_Now, GemCount = 0, 0, 0
+
+						-- First, Counting default gem sockets
+						for i = 1, MAX_NUM_SOCKETS do
+							ItemTexture = _G['Knight_CharacterArmory_ScanTTTexture'..i]:GetTexture()
+
+							if ItemTexture and ItemTexture:find('Interface\\ItemSocketingFrame\\') then
+								GemCount_Default = GemCount_Default + 1
+								Slot['Socket'..GemCount_Default].GemType = strupper(gsub(ItemTexture, 'Interface\\ItemSocketingFrame\\UI--EmptySocket--', ''))
+							end
+						end
+
+						-- Second, Check if slot's item enable to adding a socket
+						GemCount_Enable = GemCount_Default
+						--[[
+						if (SlotName == 'WaistSlot' and UnitLevel('player') >= 70) or -- buckle
+							((SlotName == 'WristSlot' or SlotName == 'HandsSlot') and self.PlayerProfession.BlackSmithing and self.PlayerProfession.BlackSmithing >= 550) then -- BlackSmith
+
+							GemCount_Enable = GemCount_Enable + 1
+							Slot['Socket'..GemCount_Enable].GemType = 'PRISMATIC'
+						end
+						]]
+
+						self:ClearTooltip(self.ScanTT)
+						self.ScanTT:SetInventoryItem('player', Slot.ID)
+
+						-- Apply current item's gem setting
+						for i = 1, MAX_NUM_SOCKETS do
+							ItemTexture = _G['Knight_CharacterArmory_ScanTTTexture'..i]:GetTexture()
+							GemID = select(i, GetInventoryItemGems(Slot.ID))
+
+							if Slot['Socket'..i].GemType and Info.Armory_Constants.GemColor[Slot['Socket'..i].GemType] then
+								R, G, B = unpack(Info.Armory_Constants.GemColor[Slot['Socket'..i].GemType])
+								Slot['Socket'..i].Socket:SetBackdropColor(R, G, B, .5)
+								Slot['Socket'..i].Socket:SetBackdropBorderColor(R, G, B)
+							else
+								Slot['Socket'..i].Socket:SetBackdropColor(1, 1, 1, .5)
+								Slot['Socket'..i].Socket:SetBackdropBorderColor(1, 1, 1)
+							end
+
+							if ItemTexture or GemID 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 GemID then
+									GemCount = GemCount + 1
+									Slot['Socket'..i].GemItemID = GemID
+
+									_, Slot['Socket'..i].Socket.Link, _, _, _, _, _, _, _, ItemTexture = GetItemInfo(GemID)
+
+									if ItemTexture then
+										Slot['Socket'..i].Texture:SetTexture(ItemTexture)
+									else
+										NeedUpdate = true
+									end
+								end
+							end
+						end
+
+						--print(SlotName..' : ', GemCount_Default, GemCount_Enable, GemCount_Now, GemCount)
+						if GemCount_Now < GemCount_Default then -- ItemInfo not loaded
+							NeedUpdate = true
+						end
+					end
+
+					_, _, ItemRarity, BasicItemLevel, _, _, _, _, _, ItemTexture = GetItemInfo(ItemLink)
+					R, G, B = GetItemQualityColor(ItemRarity)
+
+					ItemUpgradeID = ItemLink:match(':(%d+)\124h%[')
+
+					--<< Enchant Parts >>--
+					for i = 1, self.ScanTT:NumLines() do
+						CurrentLineText = _G['Knight_CharacterArmory_ScanTTTextLeft'..i]:GetText()
+
+						if CurrentLineText:find(Info.Armory_Constants.ItemLevelKey_Alt) then
+							TrueItemLevel = tonumber(CurrentLineText:match(Info.Armory_Constants.ItemLevelKey_Alt))
+						elseif CurrentLineText:find(Info.Armory_Constants.ItemLevelKey) then
+							TrueItemLevel = tonumber(CurrentLineText:match(Info.Armory_Constants.ItemLevelKey))
+						elseif CurrentLineText:find(Info.Armory_Constants.EnchantKey) then
+							CurrentLineText = CurrentLineText:match(Info.Armory_Constants.EnchantKey) -- Get enchant string
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_AGILITY_SHORT, AGI)
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_SPIRIT_SHORT, SPI)
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_STAMINA_SHORT, STA)
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_STRENGTH_SHORT, STR)
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_INTELLECT_SHORT, INT)
+							CurrentLineText = gsub(CurrentLineText, ITEM_MOD_CRIT_RATING_SHORT, CRIT_ABBR) -- Critical is too long
+							CurrentLineText = gsub(CurrentLineText, ' + ', '+') -- Remove space
+
+							Slot.ItemEnchant:SetText('|cffceff00'..CurrentLineText)
+
+							IsEnchanted = true
+						elseif CurrentLineText:find(ITEM_SPELL_TRIGGER_ONUSE) then
+							UsableEffect = true
+						end
+					end
+
+					--<< ItemLevel Parts >>--
+					if BasicItemLevel then
+						if ItemUpgradeID then
+							if ItemUpgradeID == '0' then
+								ItemUpgradeID = nil
+							else
+								ItemUpgradeID = TrueItemLevel - BasicItemLevel
+							end
+						end
+
+						Slot.ItemLevel:SetText((not TrueItemLevel or BasicItemLevel == TrueItemLevel) and BasicItemLevel or (Slot.Direction == 'LEFT' and TrueItemLevel or '')..(ItemUpgradeID and (Slot.Direction == 'LEFT' and ' ' or '')..(Info.Armory_Constants.UpgradeColor[ItemUpgradeID] or '|cffaaaaaa')..'(+'..ItemUpgradeID..')|r'..(Slot.Direction == 'RIGHT' and ' ' or '') or '')..(Slot.Direction == 'RIGHT' and TrueItemLevel or ''))
+					end
+
+					if KF.db.Modules.Armory.Character.NoticeMissing ~= false then
+						if not IsEnchanted and Info.Armory_Constants.EnchantableSlots[SlotName] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.ItemEnchant:SetText('|cffff0000'..L['Not Enchanted'])
+						end
+
+						if GemCount_Enable > GemCount_Now or GemCount_Enable > GemCount or GemCount_Now > GemCount then
+							ErrorDetected = true
+
+							Slot.SocketWarning:Show()
+							Slot.SocketWarning.Message = '|cffff5678'..(GemCount_Now - GemCount)..'|r '..L['Empty Socket']
+						end
+					end
+
+					--<< Transmogrify Parts >>--
+					if Slot.TransmogrifyAnchor then
+						IsTransmogrified, _, _, _, _, TransmogrifyItemID = GetTransmogrifySlotInfo(Slot.ID)
+
+						if IsTransmogrified then
+							_, Slot.TransmogrifyAnchor.Link = GetItemInfo(TransmogrifyItemID)
+							Slot.TransmogrifyAnchor:Show()
+						end
+					end
+
+					--[[ Check Error
+					if KF.db.Modules.Armory.Character.NoticeMissing ~= false then
+						if (not IsEnchanted and Info.Armory_Constants.EnchantableSlots[SlotName]) or ((SlotName == 'Finger0Slot' or SlotName == 'Finger1Slot') and self.PlayerProfession.Enchanting and self.PlayerProfession.Enchanting >= 550 and not IsEnchanted) then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.ItemEnchant:SetText('|cffff0000'..L['Not Enchanted'])
+						elseif self.PlayerProfession.Engineering and ((SlotName == 'BackSlot' and self.PlayerProfession.Engineering >= 380) or (SlotName == 'HandsSlot' and self.PlayerProfession.Engineering >= 400) or (SlotName == 'WaistSlot' and self.PlayerProfession.Engineering >= 380)) and not UsableEffect then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110403)..'|r : '..L['Missing Tinkers']
+						elseif SlotName == 'ShoulderSlot' and self.PlayerProfession.Inscription and Info.Armory_EnchantList.Profession_Inscription and self.PlayerProfession.Inscription >= Info.Armory_EnchantList.Profession_Inscription and not KF.Table.ItemEnchant_Profession_Inscription[(ItemData[3])] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110400)..'|r : '..L['This is not profession only.']
+						elseif SlotName == 'WristSlot' and self.PlayerProfession.LeatherWorking and Info.Armory_EnchantList.Profession_LeatherWorking and self.PlayerProfession.LeatherWorking >= Info.Armory_EnchantList.Profession_LeatherWorking and not KF.Table.ItemEnchant_Profession_LeatherWorking[(ItemData[3])] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110423)..'|r : '..L['This is not profession only.']
+						elseif SlotName == 'BackSlot' and self.PlayerProfession.Tailoring and Info.Armory_EnchantList.Profession_Tailoring then
+							for EnchantID, NeedLevel in pairs(Info.Armory_EnchantList.Profession_Tailoring) do
+								if self.PlayerProfession.Tailoring >= NeedLevel then
+									if EnchantID == ItemTable[3] then
+										ErrorDetected = nil
+										break
+									else
+										ErrorDetected = true
+									end
+								end
+							end
+
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110426)..'|r : '..L['This is not profession only.']
+						end
+
+						if GemCount_Enable > GemCount_Now or GemCount_Enable > GemCount or GemCount_Now > GemCount then
+							ErrorDetected = true
+
+							Slot.SocketWarning:Show()
+
+							if GemCount_Enable > GemCount_Now then
+								if SlotName == 'WaistSlot' then
+									if TrueItemLevel < 300 then
+										_, Slot.SocketWarning.Link = GetItemInfo(41611)
+									elseif TrueItemLevel < 417 then
+										_, Slot.SocketWarning.Link = GetItemInfo(55054)
+									else
+										_, Slot.SocketWarning.Link = GetItemInfo(90046)
+									end
+
+									Slot.SocketWarning.Message = L['Missing Buckle']
+
+									Slot.SocketWarning:SetScript('OnClick', function(self, button)
+										local itemName, itemLink
+
+										if TrueItemLevel < 300 then
+											itemName, itemLink = GetItemInfo(41611)
+										elseif TrueItemLevel < 417 then
+											itemName, itemLink = GetItemInfo(55054)
+										else
+											itemName, itemLink = GetItemInfo(90046)
+										end
+
+										if HandleModifiedItemClick(itemLink) then
+										elseif IsShiftKeyDown() then
+											if button == 'RightButton' then
+												SocketInventoryItem(Slot.ID)
+											elseif BrowseName and BrowseName:IsVisible() then
+												AuctionFrameBrowse_Reset(BrowseResetButton)
+												BrowseName:SetText(itemName)
+												BrowseName:SetFocus()
+											end
+										end
+									end)
+								elseif SlotName == 'HandsSlot' then
+									Slot.SocketWarning.Link = GetSpellLink(114112)
+									Slot.SocketWarning.Message = '|cff71d5ff'..GetSpellInfo(110396)..'|r : '..L['Missing Socket']
+								elseif SlotName == 'WristSlot' then
+									Slot.SocketWarning.Link = GetSpellLink(113263)
+									Slot.SocketWarning.Message = '|cff71d5ff'..GetSpellInfo(110396)..'|r : '..L['Missing Socket']
+								end
+							else
+								Slot.SocketWarning.Message = '|cffff5678'..(GemCount_Now - GemCount)..'|r '..L['Empty Socket']
+							end
+						end
+					end
+					]]
+				else
+					NeedUpdate = true
+				end
+			end
+
+			-- Change Gradation
+			if ErrorDetected and KF.db.Modules.Armory.Character.NoticeMissing ~= false then
+				Slot.Gradation:SetVertexColor(1, 0, 0)
+			else
+				Slot.Gradation:SetVertexColor(unpack(KF.db.Modules.Armory.Character.GradationColor))
+			end
+
+			if NeedUpdate then
+				NeedUpdateList = NeedUpdateList or {}
+				NeedUpdateList[#NeedUpdateList + 1] = SlotName
+			end
+		end
+	end
+
+	self.AverageItemLevel:SetText(KF:Color_Value(STAT_AVERAGE_ITEM_LEVEL)..' : '..format('%.2f', select(2, GetAverageItemLevel())))
+
+	if NeedUpdateList then
+		self.GearUpdated = NeedUpdateList
+		return true
+	end
+
+	self.GearUpdated = true
+end
+
+
+KF.Modules[#KF.Modules + 1] = 'CharacterArmory'
+KF.Modules.CharacterArmory = function(RemoveOrder)
+	if not RemoveOrder and KF.db.Enable ~= false and KF.db.Modules.Armory and KF.db.Modules.Armory.Character and KF.db.Modules.Armory.Character.Enable ~= false then
+		Info.CharacterArmory_Activate = true
+
+		-- Setting frame
+		CharacterFrame:SetHeight(444)
+
+		-- Move right equipment slots
+		CharacterHandsSlot:SetPoint('TOPRIGHT', CharacterFrameInsetRight, 'TOPLEFT', -4, -2)
+
+		-- Move bottom equipment slots
+		CharacterMainHandSlot:SetPoint('BOTTOMLEFT', PaperDollItemsFrame, 'BOTTOMLEFT', 185, 14)
+
+		if CA.Setup_CharacterArmory then
+			CA:Setup_CharacterArmory()
+		else
+			CA:Show()
+		end
+		CA:CharacterArmory_DataSetting()
+
+		-- Model Frame
+		CharacterModelFrame:ClearAllPoints()
+		CharacterModelFrame:SetPoint('TOPLEFT', CharacterHeadSlot)
+		CharacterModelFrame:SetPoint('RIGHT', CharacterHandsSlot)
+		CharacterModelFrame:SetPoint('BOTTOM', CharacterMainHandSlot)
+		CharacterModelFrame.BackgroundTopLeft:Hide()
+		CharacterModelFrame.BackgroundTopRight:Hide()
+		CharacterModelFrame.BackgroundBotLeft:Hide()
+		CharacterModelFrame.BackgroundBotRight:Hide()
+
+		if PaperDollFrame:IsShown() then
+			CharacterFrame:SetWidth(CharacterFrame.Expanded and 650 or 448)
+			CharacterFrameInsetRight:SetPoint('TOPLEFT', CharacterFrameInset, 'TOPRIGHT', 110, 0)
+			CharacterFrameExpandButton:SetPoint('BOTTOMRIGHT', CharacterFrameInsetRight, 'BOTTOMLEFT', 0, 1)
+		end
+
+		-- Run KnightArmory
+		CA:RegisterEvent('SOCKET_INFO_SUCCESS')
+		CA:RegisterEvent('PLAYER_EQUIPMENT_CHANGED')
+		CA:RegisterEvent('UNIT_INVENTORY_CHANGED')
+		CA:RegisterEvent('ITEM_UPGRADE_MASTER_UPDATE')
+		CA:RegisterEvent('TRANSMOGRIFY_UPDATE')
+		CA:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
+		CA:RegisterEvent('UPDATE_INVENTORY_DURABILITY')
+		CA:RegisterEvent('PLAYER_ENTERING_WORLD')
+
+		--[[
+		KF_KnightArmory.CheckButton:Show()
+		KF_KnightArmory_NoticeMissing:EnableMouse(true)
+		KF_KnightArmory_NoticeMissing.text:SetTextColor(1, 1, 1)
+		KF_KnightArmory_NoticeMissing.CheckButton:SetTexture('Interface\\Buttons\\UI-CheckBox-Check')
+		]]
+	elseif Info.CharacterArmory_Activate then
+		Info.CharacterArmory_Activate = nil
+
+		-- Setting frame to default
+		CharacterFrame:SetHeight(424)
+		CharacterFrame:SetWidth(PaperDollFrame:IsShown() and CharacterFrame.Expanded and CHARACTERFRAME_EXPANDED_WIDTH or PANEL_DEFAULT_WIDTH)
+		CharacterFrameInsetRight:SetPoint(unpack(InsetDefaultPoint))
+		CharacterFrameExpandButton:SetPoint(unpack(ExpandButtonDefaultPoint))
+
+		-- Move rightside equipment slots to default position
+		CharacterHandsSlot:SetPoint('TOPRIGHT', CharacterFrameInset, 'TOPRIGHT', -4, -2)
+
+		-- Move bottom equipment slots to default position
+		CharacterMainHandSlot:SetPoint('BOTTOMLEFT', PaperDollItemsFrame, 'BOTTOMLEFT', 130, 16)
+
+		-- Model Frame
+		CharacterModelFrame:ClearAllPoints()
+		CharacterModelFrame:Size(231, 320)
+		CharacterModelFrame:SetPoint('TOPLEFT', PaperDollFrame, 'TOPLEFT', 52, -66)
+		CharacterModelFrame.BackgroundTopLeft:Show()
+		CharacterModelFrame.BackgroundTopRight:Show()
+		CharacterModelFrame.BackgroundBotLeft:Show()
+		CharacterModelFrame.BackgroundBotRight:Show()
+
+		-- Turn off ArmoryFrame
+		CA:Hide()
+		CA:UnregisterAllEvents()
+
+		--[[
+		KF_KnightArmory.CheckButton:Hide()
+		KF_KnightArmory_NoticeMissing:EnableMouse(false)
+		KF_KnightArmory_NoticeMissing.text:SetTextColor(0.31, 0.31, 0.31)
+		KF_KnightArmory_NoticeMissing.CheckButton:SetTexture('Interface\\Buttons\\UI-CheckBox-Check-Disabled')
+		]]
+	end
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/CharacterArmory/Load_CharacterArmory.xml b/ElvUI_SLE/modules/Armory/CharacterArmory/Load_CharacterArmory.xml
new file mode 100644
index 0000000..0686a7b
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/CharacterArmory/Load_CharacterArmory.xml
@@ -0,0 +1,4 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/">
+	<Script file="Profile.lua"/>
+	<Script file="CharacterArmory.lua"/>
+</Ui>
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/CharacterArmory/Profile.lua b/ElvUI_SLE/modules/Armory/CharacterArmory/Profile.lua
new file mode 100644
index 0000000..9dcf1d1
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/CharacterArmory/Profile.lua
@@ -0,0 +1,12 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+KF.db.Modules.Armory = KF.db.Modules.Armory or {}
+
+KF.db.Modules.Armory.Character = {
+	Enable = true,
+	NoticeMissing = true,
+
+	GradationColor = { .41, .83, 1 },
+	BackgroundImage = 'Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Space'
+}
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/Constants.lua b/ElvUI_SLE/modules/Armory/Constants.lua
new file mode 100644
index 0000000..04ea495
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/Constants.lua
@@ -0,0 +1,79 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+Info.Armory_Constants = {
+	ItemLevelKey = ITEM_LEVEL:gsub('%%d', '(.+)'),
+	ItemLevelKey_Alt = ITEM_LEVEL_ALT:gsub('%%d', '.+'):gsub('%(.+%)', '%%((.+)%%)'),
+	EnchantKey = ENCHANTED_TOOLTIP_LINE:gsub('%%s', '(.+)'),
+	ItemSetBonusKey = ITEM_SET_BONUS:gsub('%%s', '(.+)'),
+	--TransmogrifiedKey = TRANSMOGRIFIED:gsub('%%s', '(.+)'),
+
+	GearList = {
+		'HeadSlot', 'HandsSlot', 'NeckSlot', 'WaistSlot', 'ShoulderSlot', 'LegsSlot', 'BackSlot', 'FeetSlot', 'ChestSlot', 'Finger0Slot',
+		'ShirtSlot', 'Finger1Slot', 'TabardSlot', 'Trinket0Slot', 'WristSlot', 'Trinket1Slot', 'SecondaryHandSlot', 'MainHandSlot'
+	},
+
+	EnchantableSlots = {
+		NeckSlot = true, BackSlot = true, Finger0Slot = true, Finger1Slot = true, MainHandSlot = true
+	},
+
+	UpgradeColor = {
+		[16] = '|cffff9614',
+		[12] = '|cfff88ef4',
+		[8] = '|cff2eb7e4',
+		[4] = '|cffceff00'
+	},
+
+	GemColor = {
+		RED = { 1, .2, .2, },
+		YELLOW = { .97, .82, .29, },
+		BLUE = { .47, .67, 1, }
+	},
+
+	EmptySocketString = {
+		[EMPTY_SOCKET_BLUE] = true,
+		[EMPTY_SOCKET_COGWHEEL] = true,
+		[EMPTY_SOCKET_HYDRAULIC] = true,
+		[EMPTY_SOCKET_META] = true,
+		[EMPTY_SOCKET_NO_COLOR] = true,
+		[EMPTY_SOCKET_PRISMATIC] = true,
+		[EMPTY_SOCKET_RED] = true,
+		[EMPTY_SOCKET_YELLOW] = true
+	},
+
+	ItemBindString = { -- Usually transmogrify string is located upper than bind string so we need to check this string for adding a transmogrify string in tooltip.
+		[ITEM_BIND_ON_EQUIP] = true,
+		[ITEM_BIND_ON_PICKUP] = true,
+		[ITEM_BIND_TO_ACCOUNT] = true,
+		[ITEM_BIND_TO_BNETACCOUNT] = true
+	},
+
+	CanTransmogrifySlot = {
+		HeadSlot = true, ShoulderSlot = true, BackSlot = true, ChestSlot = true, WristSlot = true,
+		HandsSlot = true, WaistSlot = true, LegsSlot = true, FeetSlot = true, MainHandSlot = true, SecondaryHandSlot = true
+	},
+
+	ProfessionList = {}
+}
+
+for ProfessionID, ProfessionKey in pairs({
+	[105206] = 'Alchemy',
+	[110396] = 'BlackSmithing',
+	[110400] = 'Enchanting',
+	[110403] = 'Engineering',
+	[110417] = 'Inscription',
+	[110420] = 'JewelCrafting',
+	[110423] = 'LeatherWorking',
+	[110426] = 'Tailoring',
+
+	[110413] = 'Herbalism',
+	[102161] = 'Mining',
+	[102216] = 'Skinning'
+}) do
+	local ProfessionName, _, ProfessionTexture = GetSpellInfo(ProfessionID)
+
+	Info.Armory_Constants.ProfessionList[ProfessionName] = {
+		Key = ProfessionKey,
+		Texture = ProfessionTexture
+	}
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/EnchantList.lua b/ElvUI_SLE/modules/Armory/EnchantList.lua
new file mode 100644
index 0000000..eb523a8
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/EnchantList.lua
@@ -0,0 +1,26 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+Info.Armory_EnchantList = {
+	--[[
+	Profession_Inscription = {
+		['4912'] = 600, -- 비밀 소뿔 새김무늬			Secret Ox Horn Inscription
+		['4913'] = 600, -- 비밀 학날개 새김무늬		Secret Crane Wing Inscription
+		['4914'] = 600, -- 비밀 호랑이 발톱 새김무늬	Secret Tiger Claw Inscription
+		['4915'] = 600 -- 비밀 호랑이 송곳니 새김무늬	Secret Tiger Fang Inscription
+	},
+
+	Profession_LeatherWorking = {
+		['4875'] = 575, -- 모피 안감 - 힘				Fur Lining - Strength
+		['4877'] = 575, -- 모피 안감 - 지능			Fur Lining - Intellect
+		['4878'] = 575, -- 모피 안감 - 체력			Fur Lining - Stamina
+		['4879'] = 575 -- 모피 안감 - 민첩성			Fur Lining - Agility
+	},
+
+	Profession_Tailoring = {
+		['4892'] = 550, -- 빛매듭 자수					Lightweave Embroidery
+		['4893'] = 550, -- 암흑빛 자수					Darkglow Embroidery
+		['4894'] = 550 -- 칼날 자수					Swordguard Embroidery
+	}
+	]]
+}
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/InspectArmory/Communication.lua b/ElvUI_SLE/modules/Armory/InspectArmory/Communication.lua
new file mode 100644
index 0000000..9060f24
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/InspectArmory/Communication.lua
@@ -0,0 +1,977 @@
+--------------------------------------------------------------------------------
+--<< AISM : Armory Surpport Module for AddOn Communication Inspecting		>>--
+--------------------------------------------------------------------------------
+local Revision = 1.1
+local AISM = _G['Armory_InspectSupportModule'] or CreateFrame('Frame', 'Armory_InspectSupportModule', UIParent)
+
+if not AISM.Revision or AISM.Revision < Revision then
+	local ItemSetBonusKey = ITEM_SET_BONUS:gsub('%%s', '(.+)')
+	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 playerNumSpecGroup = GetNumSpecGroups()
+	local isHelmDisplayed, isCloakDisplayed
+
+
+	--<< Create Core >>--
+	AISM.Revision = Revision
+
+	AISM.Tooltip = _G['AISM_Tooltip'] or AISM.Tooltip or CreateFrame('GameTooltip', 'AISM_Tooltip', nil, 'GameTooltipTemplate')
+	AISM.Tooltip:SetOwner(UIParent, 'ANCHOR_NONE')
+	AISM.Updater = _G['AISM_Updater'] or AISM.Updater or CreateFrame('Frame', 'AISM_Updater', UIParent)
+	AISM.Updater.elapsed = 0
+
+	AISM.Delay_SendMessage = 2
+	AISM.Delay_Updater = .5
+
+	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(110417)] = 'IS', -- Inscription
+		[GetSpellInfo(110420)] = 'JC', -- JewelCrafting
+		[GetSpellInfo(110423)] = 'LW', -- LeatherWorking
+		[GetSpellInfo(110426)] = 'TL', -- Tailoring
+
+		[GetSpellInfo(110413)] = 'HB', -- Herbalism
+		[GetSpellInfo(102161)] = 'MN', -- Mining
+		[GetSpellInfo(102216)] = 'SK' -- Skinning
+	}
+	AISM.GearList = {
+		HeadSlot = 'HE',
+		NeckSlot = 'NK',
+		ShoulderSlot = 'SD',
+		BackSlot = 'BK',
+		ChestSlot = 'CH',
+		ShirtSlot = 'ST',
+		TabardSlot = 'TB',
+		WristSlot = 'WR',
+		HandsSlot = 'HD',
+		WaistSlot = 'WA',
+		LegsSlot = 'LE',
+		FeetSlot = 'FE',
+		Finger0Slot = 'FG0',
+		Finger1Slot = 'FG1',
+		Trinket0Slot = 'TR0',
+		Trinket1Slot = 'TR1',
+		MainHandSlot = 'MH',
+		SecondaryHandSlot = 'SH'
+	}
+	AISM.CanTransmogrifySlot = {
+		HeadSlot = true,
+		ShoulderSlot = true,
+		BackSlot = true,
+		ChestSlot = true,
+		WristSlot = true,
+		HandsSlot = true,
+		WaistSlot = true,
+		LegsSlot = true,
+		FeetSlot = true,
+		MainHandSlot = true,
+		SecondaryHandSlot = true
+	}
+	AISM.DataTypeTable = {
+		PLI = 'PlayerInfo',
+		GLD = 'GuildInfo',
+		PvP = 'PvPInfo',
+		PF1 = 'Profession',
+		PF2 = 'Profession',
+		ASP = 'ActiveSpec',
+		SID = 'SetItemData'
+	}
+	for groupNum = 1, MAX_TALENT_GROUPS do
+		AISM.DataTypeTable['GL'..groupNum] = 'Glyph'
+		AISM.DataTypeTable['SP'..groupNum] = 'Specialization'
+	end
+	for slotName, keyName in pairs(AISM.GearList) do
+		AISM.DataTypeTable[keyName] = 'Gear'
+		SlotIDList[GetInventorySlotInfo(slotName)] = slotName
+	end
+
+
+	--<< Player Data Updater Core >>--
+	local needUpdate, args
+	AISM.Updater:SetScript('OnUpdate', function(self, elapsed)
+		self.elapsed = self.elapsed + elapsed
+
+		if self.elapsed > 0 then
+			self.elapsed = -AISM.Delay_Updater
+
+			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 self.GearUpdated ~= true then
+				needUpdate = AISM:GetPlayerGearString() or needUpdate
+			end
+
+			if not needUpdate then
+				self.elapsed = 0
+				self:Hide()
+
+				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
+	end)
+	AISM.Updater:SetScript('OnEvent', function(self, Event, ...)
+		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 == '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
+			args = ...
+
+			if args:find(ProfessionLearnKey) or args:find(ProfessionLearnKey2) or args:find(ProfessionUnlearnKey) then
+				self.ProfessionUpdated = nil
+				self:Show()
+			end
+		elseif Event == 'ACTIVE_TALENT_GROUP_CHANGED' or Event == 'PLAYER_SPECIALIZATION_CHANGED' then
+			self.SpecUpdated = nil
+			self:Show()
+		elseif Event == 'GLYPH_ADDED' or Event == 'GLYPH_REMOVED' or Event == 'GLYPH_UPDATED' then
+			self.GlyphUpdated = nil
+			self:Show()
+		elseif Event == 'PLAYER_TALENT_UPDATE' then
+			local args = GetNumSpecGroups()
+
+			if playerNumSpecGroup ~= args then
+				playerNumSpecGroup = args
+				self.SpecUpdated = nil
+				self:Show()
+
+				if args == MAX_TALENT_GROUPS then
+					self:UnregisterEvent('PLAYER_TALENT_UPDATE')
+				end
+			end
+		end
+	end)
+
+	if playerNumSpecGroup ~= MAX_TALENT_GROUPS then
+		AISM.Updater:RegisterEvent('PLAYER_TALENT_UPDATE')
+	end
+
+	function AISM:UpdateHelmDisplaying(value)
+		isHelmDisplayed = value == '1'
+		AISM.Updater.GearUpdated = nil
+		AISM.Updater:Show()
+	end
+	hooksecurefunc('ShowHelm', function(value) AISM:UpdateHelmDisplaying(value) end)
+
+	function AISM:UpdateCloakDisplaying(value)
+		isCloakDisplayed = value == '1'
+		AISM.Updater.GearUpdated = nil
+		AISM.Updater:Show()
+	end
+	hooksecurefunc('ShowCloak', function(value) AISM:UpdateCloakDisplaying(value) end)
+
+
+	--<< 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 >>--
+	local SpecTable = {}
+	function AISM:GetPlayerSpecSetting()
+		local DataString, Spec, Talent, isSelected
+		local ActiveSpec = GetActiveSpecGroup()
+
+		for groupNum = 1, playerNumSpecGroup do
+			DataString = nil
+
+			Spec = GetSpecialization(nil, nil, groupNum)
+			Spec = Spec and GetSpecializationInfo(Spec) or '0'
+
+			if not SpecTable['Spec'..groupNum] or SpecTable['Spec'..groupNum] ~= Spec then
+				SpecTable['Spec'..groupNum] = Spec
+				DataString = Spec
+			end
+
+			for i = 1, MAX_TALENT_TIERS do
+				for k = 1, NUM_TALENT_COLUMNS do
+					Talent, _, _, isSelected = GetTalentInfo(i, k, groupNum)
+
+					Talent = ((i - 1) * NUM_TALENT_COLUMNS + k)..'_'..Talent..(isSelected == true and '_1' or '')
+
+					Spec = Spec..'/'..Talent
+
+					if not SpecTable['Spec'..groupNum..'_Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)] or SpecTable['Spec'..groupNum..'_Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)] ~= Talent then
+						SpecTable['Spec'..groupNum..'_Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)] = Talent
+						DataString = (DataString and DataString..'/' or '')..Talent
+					end
+				end
+			end
+
+			if not self.PlayerData['Spec'..groupNum] or self.PlayerData['Spec'..groupNum] ~= Spec then
+				self.PlayerData['Spec'..groupNum] = Spec
+				self.PlayerData_ShortString['Spec'..groupNum] = Spec
+				self.UpdatedData['Spec'..groupNum] = DataString
+			end
+		end
+
+		if self.PlayerData.ActiveSpec ~= ActiveSpec then
+			self.PlayerData.ActiveSpec = ActiveSpec
+			self.PlayerData_ShortString.ActiveSpec = ActiveSpec
+			self.UpdatedData.ActiveSpec = ActiveSpec
+		end
+
+		self.Updater.SpecUpdated = true
+	end
+	AISM.Updater:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
+	AISM.Updater:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
+
+
+	--<< Glyph String >>--
+	function AISM:GetPlayerGlyphString()
+		local ShortString, FullString
+		local ActiveSpec = GetActiveSpecGroup()
+
+		local SpellID, GlyphID
+		for groupNum = 1, playerNumSpecGroup 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, needUpdate, needUpdateList
+		local CurrentSetItem, GearSetIDList = {}, {}
+
+		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
+				needUpdate = true
+			else
+				if slotLink and self.CanTransmogrifySlot[slotName] then
+					isTransmogrified, _, _, _, _, transmogrifiedItemID = GetTransmogrifySlotInfo(slotID)
+				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)
+
+					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
+								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
+						end
+
+						if checkSpace == 0 then break end
+					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
+
+		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('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')
+
+		TableToSave.PlayerInfo = playerName..'_'..UnitPVPName('player')..'/'..playerRealm..'/'..UnitLevel('player')..'/'..playerClass..'/'..playerClassID..'/'..playerRace..'/'..playerRaceID..'/'..playerSex..(guildName and '/'..guildName..'/'..guildRankName or '')
+
+		if IsInGuild() then
+			TableToSave.GuildInfo = GetTotalAchievementPoints(true)..'/'..GetNumGuildMembers()
+
+			for _, DataString in ipairs({ GetGuildLogoInfo('player') }) do
+				TableToSave.GuildInfo = TableToSave.GuildInfo..'/'..DataString
+			end
+		end
+
+		TableToSave.PvP = GetPVPLifetimeStats()
+
+		local Rating, Played, Won
+		for i, Type in pairs({ '2vs2', '3vs3', '5vs5', 'RB' }) do
+			Rating, _, _, Played, Won = GetPersonalRatedInfo(i)
+
+			if Played > 0 then
+				TableToSave.PvP = TableToSave.PvP..'/'..Type..'_'..Rating..'_'..Played..'_'..Won
+			end
+		end
+	end
+
+
+	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.PlayerInfo then
+			Data[#Data + 1] = 'PLI:'..InputData.PlayerInfo
+		end
+
+		if InputData.GuildInfo then
+			Data[#Data + 1] = 'GLD:'..InputData.GuildInfo
+		end
+
+		if InputData.PvP then
+			Data[#Data + 1] = 'PvP:'..InputData.PvP
+		end
+
+		if InputData.Profession1 then
+			Data[#Data + 1] = 'PF1:'..InputData.Profession1
+		end
+
+		if InputData.Profession2 then
+			Data[#Data + 1] = 'PF2:'..InputData.Profession2
+		end
+
+		if InputData.ActiveSpec then
+			Data[#Data + 1] = 'ASP:'..InputData.ActiveSpec
+		end
+
+		for groupNum = 1, MAX_TALENT_GROUPS do
+			if InputData['Spec'..groupNum] then
+				Data[#Data + 1] = 'SP'..groupNum..':'..InputData['Spec'..groupNum]
+			end
+
+			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
+
+		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'
+			self.GroupMemberData = {}
+		else
+			if IsInRaid() then
+				self.CurrentGroupMode = 'raid'
+			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
+				end
+			end
+		end
+
+		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 needSendData, Name, TableIndex
+	AISM:SetScript('OnUpdate', function(self, elapsed)
+		if self.CurrentGroupMode ~= 'NoGroup' then
+			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 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 needSendData and self.Updater.SpecUpdated and self.Updater.GlyphUpdated and self.Updater.GearUpdated then
+			self.SendDataGroupUpdated = (self.SendDataGroupUpdated or self.Delay_SendMessage) - elapsed
+
+			if self.SendDataGroupUpdated < 0 then
+				needSendData = nil
+				self.SendDataGroupUpdated = nil
+
+				self:SendData(self.PlayerData_ShortString)
+			end
+		end
+
+		if needSendData == nil then
+			self:Hide() -- close function
+		end
+	end)
+
+
+	function AISM:PrepareTableSetting(Prefix, Sender)
+		self.AISMUserList[Sender] = self.AISMUserList[Sender] or true
+
+		if Prefix == 'AISM' then
+			local NeedResponse
+
+			if type(self.GroupMemberData[Sender]) ~= 'table' then
+				self.GroupMemberData[Sender] = {}
+
+				NeedResponse = true
+			end
+
+			return self.GroupMemberData[Sender], NeedResponse
+		else
+			return self.CurrentInspectData[Sender]
+		end
+	end
+
+
+	local SenderRealm
+	function AISM:Receiver(Prefix, Message, Channel, Sender)
+		Sender, SenderRealm = strsplit('-', Sender)
+		SenderRealm = SenderRealm and gsub(SenderRealm,'[%s%-]','') or nil
+		Sender = Sender..(SenderRealm and SenderRealm ~= '' and SenderRealm ~= playerRealm and '-'..SenderRealm or '')
+
+		--print('|cffceff00['..Channel..']|r|cff2eb7e4['..Prefix..']|r '..Sender..' : ')
+		--print(Message)
+
+		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('^.+:(.+)-(.+)$')
+
+				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
+
+			for funcName, func in pairs(self.RegisteredFunction) do
+				func(Sender, Prefix, Message)
+			end
+		else
+			local TableToSave, NeedResponse, Group, stringTable
+
+			TableToSave, NeedResponse = self:PrepareTableSetting(Prefix, Sender)
+
+			if not TableToSave then
+				self.RemainMessage[Sender] = nil
+
+				return
+			else
+				Message = (self.RemainMessage[Sender] or '')..Message
+
+				for DataType, DataString in Message:gmatch('%{(.-):(.-)%}') do
+					if self.DataTypeTable[DataType] then
+						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
+								TableToSave.Profession[Group].Level = 0
+							else
+								for localeName, Key in pairs(self.ProfessionList) do
+									if Key == stringTable[1] then
+										TableToSave.Profession[Group].Name = localeName
+										break
+									end
+								end
+								TableToSave.Profession[Group].Level = stringTable[2]
+							end
+						elseif self.DataTypeTable[DataType] == 'Specialization' then
+							local Spec, Talent, isSelected
+
+							for i = 1, #stringTable do
+								Spec, Talent, isSelected = strsplit('_', stringTable[i])
+
+								if not Talent then
+									TableToSave.Specialization[Group].SpecializationID = stringTable[1]
+								else
+									TableToSave.Specialization[Group]['Talent'..Spec] = { Talent, isSelected and true or false }
+								end
+							end
+						elseif self.DataTypeTable[DataType] == 'ActiveSpec' then
+							TableToSave.Specialization = TableToSave.Specialization or {}
+							TableToSave.Specialization.ActiveSpec = tonumber(DataString)
+						elseif self.DataTypeTable[DataType] == 'Glyph' then
+							local SpellID, GlyphID
+							for i = 1, #stringTable do
+								SpellID, GlyphID = strsplit('_', stringTable[i])
+
+								TableToSave.Glyph[Group]['Glyph'..i..'SpellID'] = tonumber(SpellID)
+								TableToSave.Glyph[Group]['Glyph'..i..'ID'] = tonumber(GlyphID)
+							end
+						elseif self.DataTypeTable[DataType] == 'Gear' then
+							TableToSave.Gear = TableToSave.Gear or {}
+
+							for slotName, keyName in pairs(self.GearList) do
+								if keyName == DataType then
+									DataType = slotName
+									break
+								end
+							end
+
+							TableToSave.Gear[DataType] = {
+								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 {}
+
+							if stringTable[2] ~= 'F' then
+								if type(stringTable[2]) == 'number' then
+									TableToSave.SetItem[(stringTable[1])] = stringTable[2]
+								else
+									TableToSave.SetItem[(stringTable[1])] = {}
+
+									for i = 2, #stringTable do
+										if strlen(stringTable[i]) > 2 then
+											TableToSave.SetItem[(stringTable[1])][i - 1] = stringTable[i]
+										else
+											for k = 1, #stringTable - i + 1 do
+												TableToSave.SetItem[(stringTable[1])]['SetOption'..k] = stringTable[i + k - 1] == 'T' or stringTable[i + k - 1]
+											end
+											break
+										end
+									end
+								end
+							else
+								TableToSave.SetItem[(stringTable[1])] = nil
+							end
+						elseif self.DataTypeTable[DataType] == 'PlayerInfo' then
+							TableToSave.Name, TableToSave.Title = strsplit('_', stringTable[1])
+							TableToSave.Realm = stringTable[2] ~= '' and stringTable[2] ~= playerRealm and stringTable[2] or nil
+							TableToSave.Level = stringTable[3]
+							TableToSave.Class = stringTable[4]
+							TableToSave.ClassID = stringTable[5]
+							TableToSave.Race = stringTable[6]
+							TableToSave.RaceID = stringTable[7]
+							TableToSave.GenderID = stringTable[8]
+							TableToSave.guildName = stringTable[9]
+							TableToSave.guildRankName = stringTable[10]
+						elseif self.DataTypeTable[DataType] == 'GuildInfo' then
+							TableToSave.guildPoint = stringTable[1]
+							TableToSave.guildNumMembers = stringTable[2]
+
+							for i = 3, #stringTable do
+								TableToSave.guildEmblem = TableToSave.guildEmblem or {}
+								TableToSave.guildEmblem[i - 2] = stringTable[i]
+							end
+						elseif self.DataTypeTable[DataType] == 'PvPInfo' then
+							TableToSave.PvP = TableToSave.PvP or {}
+
+							TableToSave.PvP.Honor = stringTable[1]
+
+							local PvPType, Rating, Played, Won
+							for i = 2, #stringTable do
+								PvPType, Rating, Played, Won = strsplit('_', stringTable[i])
+								TableToSave.PvP[PvPType] = { tonumber(Rating), tonumber(Played), tonumber(Won) }
+							end
+						end
+					end
+				end
+
+				if Message == '' then
+					for funcName, func in pairs(self.RegisteredFunction) do
+						func(Sender, Prefix, TableToSave)
+					end
+
+					Message = nil
+				end
+
+				self.RemainMessage[Sender] = Message
+
+				if NeedResponse then
+					self:SendData(self.PlayerData_ShortString, 'AISM', SenderRealm == playerRealm and 'WHISPER' or nil, Sender)
+				end
+			end
+		end
+	end
+
+
+	local Prefix, Message, Channel, Sender, Type
+	AISM:SetScript('OnEvent', function(self, Event, ...)
+		if Event == 'VARIABLES_LOADED' then
+			isHelmDisplayed = ShowingHelm() == 1
+			isCloakDisplayed = ShowingCloak() == 1
+
+			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')
+			end
+			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)
+				SenderRealm = SenderRealm and gsub(SenderRealm, '[%s%-]', '') or nil
+				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
+
+			self.RegisteredFunction[funcName] = function(User, Prefix, UserData)
+				if Func(User, Prefix, UserData) then
+					if not PreserveFunction then
+						self.RegisteredFunction[funcName] = nil
+					end
+				end
+			end
+		end
+	end
+
+	RegisterAddonMessagePrefix('AISM')
+	RegisterAddonMessagePrefix('AISM_Inspect')
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/InspectArmory/InspectArmory.lua b/ElvUI_SLE/modules/Armory/InspectArmory/InspectArmory.lua
new file mode 100644
index 0000000..db7825f
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/InspectArmory/InspectArmory.lua
@@ -0,0 +1,2386 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+--------------------------------------------------------------------------------
+--<< KnightFrame : Upgrade Inspect Frame like Wow-Armory					>>--
+--------------------------------------------------------------------------------
+local IA = InspectArmory or CreateFrame('Frame', 'InspectArmory', E.UIParent)
+local ENI = _G['EnhancedNotifyInspect'] or { CancelInspect = function() end }
+local AISM = _G['Armory_InspectSupportModule']
+local ButtonName = L['Knight Inspect']
+
+local CORE_FRAME_LEVEL = 10
+local SLOT_SIZE = 37
+local TAB_HEIGHT = 22
+local SIDE_BUTTON_WIDTH = 16
+local SPACING = 3
+local INFO_TAB_SIZE = 22
+local TALENT_SLOT_SIZE = 26
+local GLYPH_SLOT_HEIGHT = 22
+
+local HeadSlotItem = 99568
+local BackSlotItem = 102246
+local Default_NotifyInspect, Default_InspectUnit
+
+--<< Key Table >>--
+IA.PageList = { Character = 'CHARACTER', Info = 'INFO', Spec = 'TALENTS' }
+IA.InfoPageCategoryList = { 'Profession', 'PvP', 'Guild' }
+IA.UnitPopupList = { FRIEND = true, GUILD = true, RAID = true, FOCUS = true, PLAYER = true, PARTY = true, RAID_PLAYER = true }
+IA.ModelList = {
+	Human = { RaceID = 1, [2] = { x = 0.02, y = -0.025, z = -0.6 }, [3] = { x = -0.01, y = -0.08, z = -0.6 } },
+	Dwarf = { RaceID = 3, [2] = { x = -0.01, y = -0.23, z = -0.9 }, [3] = { x = -0.03, y = -0.15, z = -0.8 } },
+	NightElf = { RaceID = 4, [2] = { z = -0.7 }, [3] = { x = -0.02, y = -0.04, z = -0.7 }},
+	Gnome = { RaceID = 7, [2] = { y = -0.2, z = -1 }, [3] = { x = -0.01, y = -0.19, z = -0.9 } },
+	Draenei = { RaceID = 11, [2] = { x = -0.04, y = -0.08, z = -0.7 }, [3] = { x = -0.02, y = -0.01, z = -0.6 }},
+	Worgen = { RaceID = 22, [2] = { x = -0.09, y = -0.1, z = -0.4 }, [3] = { x = -0.01, y = 0.01, z = 0.06 }},
+	Orc = { RaceID = 2, [2] = { y = -0.06, z = -1 }, [3] = { x = -0.01, y = -0.05, z = -0.7 }},
+	Scourge = { RaceID = 5, [2] = { y = -0.08, z = -0.7 }, [3] = { y = -0.05, z = -0.6 }},
+	Tauren = { RaceID = 6, [2] = { y = -0.09, z = -0.7 }, [3] = { y = -0.16, z = -0.6 } },
+	Troll = { RaceID = 8, [2] = { y = -0.14, z = -1.1 }, [3] = { y = -0.11, z = -0.8 }},
+	BloodElf = { RaceID = 10, [2] = { x = 0.02, y = -0.01, z = -0.5 }, [3] = { x = 0.04, y = -0.01, z = -0.6 }},
+	Goblin = { RaceID = 9, [2] = { y = -0.23, z = -1.3 }, [3] = { x = -0.01, y = -0.25, z = -1.3 } },
+	Pandaren = { RaceID = 24, [2] = { x = 0.02, y = 0.02, z = -0.6 }, [3] = { x = 0, y = -0.05, z = -1 } },
+}
+IA.CurrentInspectData = {}
+IA.Default_CurrentInspectData = {
+	Gear = {
+		HeadSlot = {}, NeckSlot = {}, ShoulderSlot = {}, BackSlot = {}, ChestSlot = {},
+		ShirtSlot = {}, TabardSlot = {}, WristSlot = {}, MainHandSlot = {},
+
+		HandsSlot = {}, WaistSlot = {}, LegsSlot = {}, FeetSlot = {}, Finger0Slot = {},
+		Finger1Slot = {}, Trinket0Slot = {}, Trinket1Slot = {}, SecondaryHandSlot = {}
+	},
+	SetItem = {},
+	Specialization = { [1] = {}, [2] = {} },
+	Glyph = { [1] = {}, [2] = {} },
+	Profession = { [1] = {}, [2] = {} },
+	PvP = {}
+}
+IA.MainStats = {	-- STR, INT, AGI,
+	WARRIOR = STR,
+	HUNTER = AGI,
+	SHAMAN = {
+		[(L['Spec_Shaman_Elemental'])] = INT,
+		[(L['Spec_Shaman_Enhancement'])] = AGI,
+		[(L['Spec_Shaman_Restoration'])] = INT
+	},
+	MONK = {
+		[(L['Spec_Monk_Brewmaster'])] = AGI,
+		[(L['Spec_Monk_Mistweaver'])] = INT,
+		[(L['Spec_Monk_Windwalker'])] = AGI
+	},
+	ROGUE = AGI,
+	DEATHKNIGHT = STR,
+	MAGE = INT,
+	DRUID = {
+		[(L['Spec_Druid_Balance'])] = INT,
+		[(L['Spec_Druid_Feral'])] = AGI,
+		[(L['Spec_Druid_Guardian'])] = AGI,
+		[(L['Spec_Druid_Restoration'])] = INT
+	},
+	PALADIN = {
+		[(L['Spec_Paladin_Holy'])] = INT,
+		[(L['Spec_Paladin_Protection'])] = STR,
+		[(L['Spec_Paladin_Retribution'])] = STR
+	},
+	PRIEST = INT,
+	WARLOCK = INT
+}
+
+
+do --<< Button Script >>--
+	function IA:OnEnter()
+		if self.Link or self.Message then
+			GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
+
+			self:SetScript('OnUpdate', function()
+				GameTooltip:ClearLines()
+
+				if self.Link then
+					GameTooltip:SetHyperlink(self.Link)
+				end
+
+				if self.Link and self.Message then GameTooltip:AddLine(' ') end -- Line space
+
+				if self.Message then
+					GameTooltip:AddLine(self.Message, 1, 1, 1)
+				end
+
+				GameTooltip:Show()
+			end)
+		end
+	end
+
+
+	function IA:OnLeave()
+		self:SetScript('OnUpdate', nil)
+		GameTooltip:Hide()
+	end
+
+
+	function IA:OnClick()
+		if self.Link then
+			if HandleModifiedItemClick(self.Link) then
+			elseif self.EnableAuctionSearch and BrowseName and BrowseName:IsVisible() then
+				AuctionFrameBrowse_Reset(BrowseResetButton)
+				BrowseName:SetText(self:GetParent().text:GetText())
+				BrowseName:SetFocus()
+			end
+		end
+	end
+
+
+	function IA:Button_OnEnter()
+		self:SetBackdropBorderColor(unpack(E.media.rgbvaluecolor))
+		self.text:SetText(KF:Color_Value(self.ButtonString))
+	end
+
+
+	function IA:Button_OnLeave()
+		self:SetBackdropBorderColor(unpack(E.media.bordercolor))
+		self.text:SetText(self.ButtonString)
+	end
+
+
+	function IA:EquipmentSlot_OnEnter()
+		if Info.Armory_Constants.CanTransmogrifySlot[self.SlotName] and type(self.TransmogrifyLink) == 'number' and not GetItemInfo(self.TransmogrifyLink) then
+			self:SetScript('OnUpdate', function()
+				if GetItemInfo(self.TransmogrifyLink) then
+					IA.EquipmentSlot_OnEnter(self)
+					self:SetScript('OnUpdate', nil)
+				end
+			end)
+			return
+		end
+
+		if self.Link then
+			GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
+			GameTooltip:SetHyperlink(self.Link)
+
+			local CurrentLineText, SetName
+			for i = 1, GameTooltip:NumLines() do
+				CurrentLineText = _G['GameTooltipTextLeft'..i]:GetText()
+
+				SetName = CurrentLineText:match('^(.+) %((%d)/(%d)%)$')
+
+				if SetName then
+					local SetCount = 0
+
+					if type(IA.SetItem[SetName]) == 'table' then
+						for dataType, Data in pairs(IA.SetItem[SetName]) do
+							if type(dataType) == 'string' then -- Means SetOption Data
+
+
+								_G['GameTooltipTextLeft'..(i + #IA.SetItem[SetName] + 1 + dataType:match('^.+(%d)$'))]:SetText(Data)
+								--[[
+								local CurrentLineNum = i + #IA.SetItem[SetName] + 1 + dataType:match('^.+(%d)$')
+								local CurrentText = _G['GameTooltipTextLeft'..CurrentLineNum]:GetText()
+								local CurrentTextType = CurrentText:match("^%((%d)%)%s.+:%s.+$") or true
+
+								if Data ~= CurrentTextType then
+									if Data == true and CurrentTextType ~= true then
+										_G['GameTooltipTextLeft'..CurrentLineNum]:SetText(GREEN_FONT_COLOR_CODE..(strsub(CurrentText, (strlen(CurrentTextType) + 4))))
+									else
+										_G['GameTooltipTextLeft'..CurrentLineNum]:SetText(GRAY_FONT_COLOR_CODE..'('..Data..') '..CurrentText)
+									end
+								end
+								]]
+							else
+								if Data:find(LIGHTYELLOW_FONT_COLOR_CODE) then
+									SetCount = SetCount + 1
+								end
+
+								_G['GameTooltipTextLeft'..(i + dataType)]:SetText(Data)
+							end
+						end
+
+						_G['GameTooltipTextLeft'..i]:SetText(string.gsub(CurrentLineText, ' %(%d/', ' %('..SetCount..'/', 1))
+					end
+
+					break
+				elseif Info.Armory_Constants.CanTransmogrifySlot[self.SlotName] and Info.Armory_Constants.ItemBindString[CurrentLineText] and self.TransmogrifyAnchor.Link then
+					_G['GameTooltipTextLeft'..i]:SetText(E:RGBToHex(1, .5, 1)..TRANSMOGRIFIED_HEADER..'|n'..(GetItemInfo(self.TransmogrifyAnchor.Link) or self.TransmogrifyAnchor.Link)..'|r|n'..CurrentLineText)
+				end
+			end
+
+			GameTooltip:Show()
+		end
+	end
+
+
+	function IA:ScrollFrame_OnMouseWheel(Spinning)
+		local Page = self:GetScrollChild()
+		local PageHeight = Page:GetHeight()
+		local WindowHeight = self:GetHeight()
+
+		if PageHeight > WindowHeight then
+			self.Offset = (self.Offset or 0) - Spinning * 5
+
+			Page:ClearAllPoints()
+			if self.Offset > PageHeight - WindowHeight then
+				self.Offset = PageHeight - WindowHeight
+
+				Page:Point('BOTTOMLEFT', self)
+				Page:Point('BOTTOMRIGHT', self)
+				return
+			elseif self.Offset < 0 then
+				self.Offset = 0
+			end
+		else
+			self.Offset = 0
+		end
+
+		Page:Point('TOPLEFT', self, 0, self.Offset)
+		Page:Point('TOPRIGHT', self, 0, self.Offset)
+	end
+
+
+	function IA:Category_OnClick()
+		self = self:GetParent()
+
+		self.Closed = not self.Closed
+
+		IA:ReArrangeCategory()
+	end
+
+
+	function IA:GemSocket_OnEnter()
+		GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
+
+		local Parent = self:GetParent()
+
+		if Parent.GemItemID then
+			if type(Parent.GemItemID) == 'number' then
+				if GetItemInfo(Parent.GemItemID) then
+					GameTooltip:SetHyperlink(select(2, GetItemInfo(Parent.GemItemID)))
+					self:SetScript('OnUpdate', nil)
+				else
+					self:SetScript('OnUpdate', IA.GemSocket_OnEnter)
+					return
+				end
+			else
+				GameTooltip:ClearLines()
+				GameTooltip:AddLine('|cffffffff'..Parent.GemItemID)
+			end
+		elseif Parent.GemType then
+			GameTooltip:ClearLines()
+			GameTooltip:AddLine('|cffffffff'.._G['EMPTY_SOCKET_'..Parent.GemType])
+		end
+
+		GameTooltip:Show()
+	end
+
+
+	function IA:GemSocket_OnClick()
+		self = self:GetParent()
+
+		if self.GemItemID and type(self.GemItemID) == 'number' then
+			local ItemName, ItemLink = GetItemInfo(self.GemItemID)
+
+			if not IsShiftKeyDown() then
+				SetItemRef(ItemLink, ItemLink, 'LeftButton')
+			else
+				if HandleModifiedItemClick(ItemLink) then
+				elseif BrowseName and BrowseName:IsVisible() then
+					AuctionFrameBrowse_Reset(BrowseResetButton)
+					BrowseName:SetText(ItemName)
+					BrowseName:SetFocus()
+				end
+			end
+		end
+	end
+
+
+	function IA:Transmogrify_OnEnter()
+		self.Texture:SetVertexColor(1, .8, 1)
+
+		if self.Link then
+			if GetItemInfo(self.Link) then
+				self:SetScript('OnUpdate', nil)
+				GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
+				GameTooltip:SetHyperlink(select(2, GetItemInfo(self.Link)))
+				GameTooltip:Show()
+			else
+				self:SetScript('OnUpdate', IA.Transmogrify_OnEnter)
+			end
+		end
+	end
+
+
+	function IA:Transmogrify_OnLeave()
+		self:SetScript('OnUpdate', nil)
+		self.Texture:SetVertexColor(1, .5, 1)
+
+		GameTooltip:Hide()
+	end
+end
+
+
+function IA:ChangePage(Type)
+	for PageType in pairs(self.PageList) do
+		if self[PageType] then
+			if Type == PageType..'Button' then
+				Type = PageType
+				self[PageType]:Show()
+			else
+				self[PageType]:Hide()
+			end
+		end
+	end
+
+	self.MainHandSlot:ClearAllPoints()
+	self.SecondaryHandSlot:ClearAllPoints()
+	if Type == 'Character' then
+		for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+			self[SlotName].ItemLevel:Hide()
+		end
+
+		self.MainHandSlot:Point('BOTTOMRIGHT', self.BP, 'TOP', -2, SPACING)
+		self.SecondaryHandSlot:Point('BOTTOMLEFT', self.BP, 'TOP', 2, SPACING)
+	else
+		for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+			self[SlotName].ItemLevel:Show()
+		end
+
+		self.MainHandSlot:Point('BOTTOMLEFT', self.BP, 'TOPLEFT', 1, SPACING)
+		self.SecondaryHandSlot:Point('BOTTOMRIGHT', self.BP, 'TOPRIGHT', -1, SPACING)
+	end
+
+	if self[Type].Message then
+		self.Message:SetText(self[Type].Message)
+		self.MessageFrame.Page:Width(self.Message:GetWidth())
+		self.MessageFrame.UpdatedTime = nil
+		self.MessageFrame.Offset = 0
+		self.MessageFrame.Page:ClearAllPoints()
+		self.MessageFrame.Page:Point('TOPLEFT', self.MessageFrame)
+		self.MessageFrame.Page:Point('BOTTOMLEFT', self.MessageFrame)
+		self.MessageFrame:Show()
+	else
+		self.MessageFrame:Hide()
+	end
+end
+
+
+function IA:CreateInspectFrame()
+	do --<< Core >>--
+		self:Size(450, 480)
+		self:CreateBackdrop('Transparent')
+		self:SetFrameStrata('DIALOG')
+		self:SetFrameLevel(CORE_FRAME_LEVEL)
+		self:SetMovable(true)
+		self:SetClampedToScreen(true)
+		self:SetScript('OnHide', function()
+			PlaySound('igCharacterInfoClose')
+
+			if self.CurrentInspectData.Name then
+				local TableIndex = self.CurrentInspectData.Name..(IA.CurrentInspectData.Realm and IA.CurrentInspectData.Realm ~= '' and IA.CurrentInspectData.Realm ~= Info.MyRealm and '-'..IA.CurrentInspectData.Realm or '')
+
+				if AISM then
+					AISM.RegisteredFunction.InspectArmory = nil
+				end
+
+				ENI.CancelInspect(TableIndex)
+				IA:UnregisterEvent('INSPECT_READY')
+				IA:UnregisterEvent('INSPECT_HONOR_UPDATE')
+			end
+
+			self.LastDataSetting = nil
+			self.Model:Point('TOPRIGHT', UIParent, 'BOTTOMLEFT')
+		end)
+		self:SetScript('OnShow', function() self.Model:Point('TOPRIGHT', self.HandsSlot) end)
+		self:SetScript('OnEvent', function(self, Event, ...) if self[Event] then self[Event](Event, ...) end end)
+		UIPanelWindows.InspectArmory = { area = 'left', pushable = 1, whileDead = 1 }
+	end
+
+	do --<< Tab >>--
+		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(0, 0, 0)
+		KF:TextSetting(self.Tab, ' |cff2eb7e4Knight Inspect', { FontSize = 10, FontStyle = 'OUTLINE' }, 'LEFT', 6, 1)
+		self.Tab:SetScript('OnMouseDown', function() self:StartMoving() end)
+		self.Tab:SetScript('OnMouseUp', function() self:StopMovingOrSizing() end)
+	end
+
+	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)
+		self.Close:Point('RIGHT', -4, 0)
+		KF:TextSetting(self.Close, 'X', { FontSize = 13, }, 'CENTER', 1, 0)
+		self.Close:SetScript('OnEnter', self.Button_OnEnter)
+		self.Close:SetScript('OnLeave', self.Button_OnLeave)
+		self.Close:SetScript('OnClick', function() HideUIPanel(self) end)
+		self.Close.ButtonString = 'X'
+	end
+
+	do --<< Bottom Panel >>--
+		self.BP = CreateFrame('Frame', nil, self)
+		self.BP:Point('TOPLEFT', self, 'BOTTOMLEFT', SPACING, SPACING + TAB_HEIGHT)
+		self.BP:Point('BOTTOMRIGHT', self, -SPACING, SPACING)
+		self.BP: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.BP:SetBackdropColor(0.09, 0.3, 0.45)
+		self.BP:SetBackdropBorderColor(0, 0, 0)
+		self.BP:SetFrameLevel(CORE_FRAME_LEVEL + 2)
+
+		self.MessageFrame = CreateFrame('ScrollFrame', nil, self.BP)
+		self.MessageFrame:Point('TOPLEFT', self.BP, SPACING * 2 + TAB_HEIGHT, 0)
+		self.MessageFrame:Point('BOTTOMRIGHT', self.BP, -10, 1)
+		self.MessageFrame.UpdateInterval = 3
+		self.MessageFrame.ScrollSpeed = 1
+
+		local PageWidth
+		local VisibleWidth
+		self.MessageFrame:SetScript('OnUpdate', function(self, Elapsed)
+			PageWidth = self.Page:GetWidth()
+			VisibleWidth = self:GetWidth()
+
+			if PageWidth > VisibleWidth then
+				self.UpdatedTime = (self.UpdatedTime or -self.UpdateInterval) + Elapsed
+
+				if self.UpdatedTime > 0 then
+					if self.Offset then
+						self.Offset = self.Offset - self.ScrollSpeed
+					else
+						self.UpdatedTime = nil
+						self.Offset = 0
+					end
+
+					self.Page:ClearAllPoints()
+					if self.Offset < VisibleWidth - PageWidth then
+						self.UpdatedTime = -self.UpdateInterval - 2
+						self.Offset = nil
+						self.Page:Point('TOPRIGHT', self)
+						self.Page:Point('BOTTOMRIGHT', self)
+					else
+						self.Page:Point('TOPLEFT', self, self.Offset, 0)
+						self.Page:Point('BOTTOMLEFT', self, self.Offset, 0)
+					end
+				end
+			end
+		end)
+
+		self.MessageFrame.Icon = self.MessageFrame:CreateTexture(nil, 'OVERLAY')
+		self.MessageFrame.Icon:Size(TAB_HEIGHT)
+		self.MessageFrame.Icon:Point('TOPLEFT', self.BP, 'TOPLEFT', SPACING * 2, -1)
+		self.MessageFrame.Icon:SetTexture('Interface\\HELPFRAME\\HelpIcon-ReportAbuse')
+
+		self.MessageFrame.Page = CreateFrame('Frame', nil, self.MessageFrame)
+		self.MessageFrame:SetScrollChild(self.MessageFrame.Page)
+		self.MessageFrame.Page:Point('TOPLEFT', self.MessageFrame)
+		self.MessageFrame.Page:Point('BOTTOMLEFT', self.MessageFrame)
+		KF:TextSetting(self.MessageFrame.Page, '', { FontSize = 10, FontStyle = 'OUTLINE', directionH = 'LEFT' }, 'LEFT', self.MessageFrame.Page)
+
+		self.Message = self.MessageFrame.Page.text
+	end
+
+	do --<< Background >>--
+		self.BG = self:CreateTexture(nil, 'OVERLAY')
+		self.BG:Point('TOPLEFT', self.Tab, 'BOTTOMLEFT', 0, -38)
+		self.BG:Point('BOTTOMRIGHT', self.BP, 'TOPRIGHT')
+		self.BG:SetTexture(KF.db.Modules.Armory.Inspect.BackgroundImage)
+	end
+
+	do --<< Buttons >>--
+		for ButtonName, ButtonString in pairs(self.PageList) do
+			ButtonName = ButtonName..'Button'
+
+			self[ButtonName] = CreateFrame('Button', nil, self.BP)
+			self[ButtonName]:Size(70, 20)
+			self[ButtonName]: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[ButtonName]:SetBackdropBorderColor(0, 0, 0)
+			self[ButtonName]:SetFrameLevel(CORE_FRAME_LEVEL + 1)
+			KF:TextSetting(self[ButtonName], _G[ButtonString], { FontSize = 9, FontStyle = 'OUTLINE' })
+			self[ButtonName]:SetScript('OnEnter', self.Button_OnEnter)
+			self[ButtonName]:SetScript('OnLeave', self.Button_OnLeave)
+			self[ButtonName]:SetScript('OnClick', function() IA:ChangePage(ButtonName) end)
+			self[ButtonName].ButtonString = _G[ButtonString]
+		end
+		self.CharacterButton:Point('TOPLEFT', self.BP, 'BOTTOMLEFT', SPACING + 1, 2)
+		self.InfoButton:Point('TOPLEFT', self.CharacterButton, 'TOPRIGHT', SPACING, 0)
+		self.SpecButton:Point('TOPLEFT', self.InfoButton, 'TOPRIGHT', SPACING, 0)
+	end
+
+	do --<< Bookmark Star >>--
+		self.Bookmark = CreateFrame('CheckButton', nil, self)
+		self.Bookmark:Size(24)
+		self.Bookmark:EnableMouse(true)
+		self.Bookmark.NormalTexture = self.Bookmark:CreateTexture(nil, 'OVERLAY')
+		self.Bookmark.NormalTexture:SetTexCoord(0.5, 1, 0, 0.5)
+		self.Bookmark.NormalTexture:SetTexture('Interface\\Common\\ReputationStar.tga')
+		self.Bookmark.NormalTexture:SetInside()
+		self.Bookmark:SetNormalTexture(self.Bookmark.NormalTexture)
+		self.Bookmark.HighlightTexture = self.Bookmark:CreateTexture(nil, 'OVERLAY')
+		self.Bookmark.HighlightTexture:SetTexCoord(0, 0.5, 0.5, 1)
+		self.Bookmark.HighlightTexture:SetTexture('Interface\\Common\\ReputationStar.tga')
+		self.Bookmark.HighlightTexture:SetInside()
+		self.Bookmark:SetHighlightTexture(self.Bookmark.HighlightTexture)
+		self.Bookmark.CheckedTexture = self.Bookmark:CreateTexture(nil, 'OVERLAY')
+		self.Bookmark.CheckedTexture:SetTexCoord(0, 0.5, 0, 0.5)
+		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, -34)
+		self.Bookmark:Hide()
+	end
+
+	do --<< Texts >>--
+		KF:TextSetting(self, nil, { Tag = 'Name', FontSize = 22, FontStyle = 'OUTLINE', }, 'LEFT', self.Bookmark, 'RIGHT', 9, 0)
+		KF:TextSetting(self, nil, { Tag = 'Title', FontSize = 9, FontStyle = 'OUTLINE', }, 'BOTTOMLEFT', self.Name, 'TOPLEFT', 2, 5)
+		KF:TextSetting(self, nil, { Tag = 'LevelRace', FontSize = 10, directionH = 'LEFT', }, 'BOTTOMLEFT', self.Name, 'BOTTOMRIGHT', 5, 2)
+		KF:TextSetting(self, nil, { Tag = 'Guild', FontSize = 10, directionH = 'LEFT', }, 'TOPLEFT', self.Name, 'BOTTOMLEFT', 4, -5)
+		self.Guild:Point('RIGHT', self, -44, 0)
+	end
+
+	do --<< Class, Specialization Icon >>--
+		for _, FrameName in pairs({ 'SpecIcon', 'ClassIcon', }) do
+			self[FrameName..'Slot'] = CreateFrame('Frame', nil, self)
+			self[FrameName..'Slot']:Size(24)
+			self[FrameName..'Slot']:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self[FrameName] = self[FrameName..'Slot']:CreateTexture(nil, 'OVERLAY')
+			self[FrameName]:SetTexCoord(unpack(E.TexCoords))
+			self[FrameName]:SetInside()
+		end
+		self.ClassIconSlot:Point('RIGHT', self.Tab, 'BOTTOMRIGHT', -44, -35)
+		self.SpecIconSlot:Point('RIGHT', self.ClassIconSlot, 'LEFT', -SPACING, 0)
+	end
+
+	do --<< Player Model >>--
+		self.Model = CreateFrame('DressUpModel', nil, UIParent)
+		self.Model:SetFrameStrata('DIALOG')
+		self.Model:SetFrameLevel(CORE_FRAME_LEVEL + 1)
+		self.Model:EnableMouse(1)
+		self.Model:EnableMouseWheel(1)
+		self.Model:SetUnit('player')
+		self.Model:TryOn(HeadSlotItem)
+		self.Model:TryOn(BackSlotItem)
+		self.Model:Undress()
+		self.Model:SetScript('OnMouseDown', function(self, button)
+			self.StartX, self.StartY = GetCursorPosition()
+
+			local EndX, EndY, Z, X, Y
+			if button == 'LeftButton' then
+				IA.Model:SetScript('OnUpdate', function(self)
+					EndX, EndY = GetCursorPosition()
+
+					self.rotation = (EndX - self.StartX) / 34 + self:GetFacing()
+					self:SetFacing(self.rotation)
+					self.StartX, self.StartY = GetCursorPosition()
+				end)
+			elseif button == 'RightButton' then
+				IA.Model:SetScript('OnUpdate', function(self)
+					EndX, EndY = GetCursorPosition()
+
+					Z, X, Y = self:GetPosition(Z, X, Y)
+					X = (EndX - self.StartX) / 45 + X
+					Y = (EndY - self.StartY) / 45 + Y
+
+					self:SetPosition(Z, X, Y)
+					self.StartX, self.StartY = GetCursorPosition()
+				end)
+			end
+		end)
+		self.Model:SetScript('OnMouseUp', function(self)
+			self:SetScript('OnUpdate', nil)
+		end)
+		self.Model:SetScript('OnMouseWheel', function(self, spining)
+			local Z, X, Y = self:GetPosition()
+
+			Z = (spining > 0 and Z + 0.5 or Z - 0.5)
+
+			self:SetPosition(Z, X, Y)
+		end)
+	end
+
+	do --<< Equipment Slots >>--
+		self.Character = CreateFrame('Frame', nil, self)
+
+		local Slot
+		for i, SlotName in pairs(Info.Armory_Constants.GearList) do
+			-- Slot
+			Slot = CreateFrame('Button', nil, self)
+			Slot:Size(SLOT_SIZE)
+			Slot:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			Slot:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+			Slot:SetScript('OnEnter', self.EquipmentSlot_OnEnter)
+			Slot:SetScript('OnLeave', self.OnLeave)
+			Slot:SetScript('OnClick', self.OnClick)
+			KF:TextSetting(Slot, '', { FontSize = 12, FontStyle = 'OUTLINE' })
+
+			Slot.SlotName = SlotName
+			Slot.Direction = i%2 == 1 and 'LEFT' or 'RIGHT'
+			Slot.ID, Slot.EmptyTexture = GetInventorySlotInfo(SlotName)
+
+			Slot.Texture = Slot:CreateTexture(nil, 'OVERLAY')
+			Slot.Texture:SetTexCoord(unpack(E.TexCoords))
+			Slot.Texture:SetInside()
+			Slot.Texture:SetTexture(Slot.EmptyTexture)
+
+			Slot.Highlight = Slot:CreateTexture('Frame', nil, self)
+			Slot.Highlight:SetInside()
+			Slot.Highlight:SetTexture(1, 1, 1, 0.3)
+			Slot:SetHighlightTexture(Slot.Highlight)
+
+			KF:TextSetting(Slot, nil, { Tag = 'ItemLevel', FontSize = 10, FontStyle = 'OUTLINE', }, 'TOP', Slot, 0, -3)
+
+			-- Gradation
+			Slot.Gradation = CreateFrame('Frame', nil, self.Character)
+			Slot.Gradation:Size(130, SLOT_SIZE + 4)
+			Slot.Gradation:SetFrameLevel(CORE_FRAME_LEVEL + 2)
+			Slot.Gradation:Point(Slot.Direction, Slot, Slot.Direction == 'LEFT' and -1 or 1, 0)
+			Slot.Gradation.Texture = Slot.Gradation:CreateTexture(nil, 'OVERLAY')
+			Slot.Gradation.Texture:SetInside()
+			Slot.Gradation.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Gradation')
+			if Slot.Direction == 'LEFT' then
+				Slot.Gradation.Texture:SetTexCoord(0, 1, 0, 1)
+			else
+				Slot.Gradation.Texture:SetTexCoord(1, 0, 0, 1)
+			end
+
+			if not (SlotName == 'ShirtSlot' or SlotName == 'TabardSlot') then
+				-- Item Level
+				KF:TextSetting(Slot.Gradation, nil, { Tag = 'ItemLevel', FontSize = 10, directionH = Slot.Direction, }, 'TOP'..Slot.Direction, Slot, 'TOP'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 2 or -2, -1)
+
+				-- Enchantment
+				KF:TextSetting(Slot.Gradation, nil, { Tag = 'ItemEnchant', FontSize = 8, directionH = Slot.Direction, }, Slot.Direction, Slot, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 2 or -2, 2)
+				Slot.EnchantWarning = CreateFrame('Button', nil, Slot.Gradation)
+				Slot.EnchantWarning:Size(12)
+				Slot.EnchantWarning.Texture = Slot.EnchantWarning:CreateTexture(nil, 'OVERLAY')
+				Slot.EnchantWarning.Texture:SetInside()
+				Slot.EnchantWarning.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Warning-Small')
+				Slot.EnchantWarning:Point(Slot.Direction, Slot.Gradation.ItemEnchant, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 3 or -3, 0)
+				Slot.EnchantWarning:SetScript('OnEnter', self.OnEnter)
+				Slot.EnchantWarning:SetScript('OnLeave', self.OnLeave)
+
+				-- Gem Socket
+				for i = 1, MAX_NUM_SOCKETS do
+					Slot['Socket'..i] = CreateFrame('Frame', nil, Slot.Gradation)
+					Slot['Socket'..i]:Size(12)
+					Slot['Socket'..i]:SetBackdrop({
+						bgFile = E.media.blankTex,
+						edgeFile = E.media.blankTex,
+						tile = false, tileSize = 0, edgeSize = E.mult,
+						insets = { left = 0, right = 0, top = 0, bottom = 0}
+					})
+					Slot['Socket'..i]:SetBackdropColor(0, 0, 0, 1)
+					Slot['Socket'..i]:SetBackdropBorderColor(0, 0, 0)
+					Slot['Socket'..i]:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+
+					Slot['Socket'..i].Socket = CreateFrame('Button', nil, Slot['Socket'..i])
+					Slot['Socket'..i].Socket:SetBackdrop({
+						bgFile = E.media.blankTex,
+						edgeFile = E.media.blankTex,
+						tile = false, tileSize = 0, edgeSize = E.mult,
+						insets = { left = 0, right = 0, top = 0, bottom = 0}
+					})
+					Slot['Socket'..i].Socket:SetInside()
+					Slot['Socket'..i].Socket:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+					Slot['Socket'..i].Socket:SetScript('OnEnter', self.GemSocket_OnEnter)
+					Slot['Socket'..i].Socket:SetScript('OnLeave', self.OnLeave)
+					Slot['Socket'..i].Socket:SetScript('OnClick', self.GemSocket_OnClick)
+
+					Slot['Socket'..i].Texture = Slot['Socket'..i].Socket:CreateTexture(nil, 'OVERLAY')
+					Slot['Socket'..i].Texture:SetTexCoord(.1, .9, .1, .9)
+					Slot['Socket'..i].Texture:SetInside()
+				end
+				Slot.Socket1:Point('BOTTOM'..Slot.Direction, Slot, 'BOTTOM'..(Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT'), Slot.Direction == 'LEFT' and 3 or -3, 2)
+				Slot.Socket2:Point(Slot.Direction, Slot.Socket1, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 1 or -1, 0)
+				Slot.Socket3:Point(Slot.Direction, Slot.Socket2, Slot.Direction == 'LEFT' and 'RIGHT' or 'LEFT', Slot.Direction == 'LEFT' and 1 or -1, 0)
+
+				Slot.SocketWarning = CreateFrame('Button', nil, Slot.Gradation)
+				Slot.SocketWarning:Size(12)
+				Slot.SocketWarning.Texture = Slot.SocketWarning:CreateTexture(nil, 'OVERLAY')
+				Slot.SocketWarning.Texture:SetInside()
+				Slot.SocketWarning.Texture:SetTexture('Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Warning-Small')
+				Slot.SocketWarning:SetScript('OnEnter', self.OnEnter)
+				Slot.SocketWarning:SetScript('OnLeave', self.OnLeave)
+
+				if Info.Armory_Constants.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.Direction == 'LEFT' and -3 or 3, -3)
+					Slot.TransmogrifyAnchor:SetScript('OnEnter', self.Transmogrify_OnEnter)
+					Slot.TransmogrifyAnchor:SetScript('OnLeave', self.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
+		end
+
+		-- Slot Location : Left
+		self.HeadSlot:Point('BOTTOMLEFT', self.NeckSlot, 'TOPLEFT', 0, SPACING)
+		self.NeckSlot:Point('BOTTOMLEFT', self.ShoulderSlot, 'TOPLEFT', 0, SPACING)
+		self.ShoulderSlot:Point('BOTTOMLEFT', self.BackSlot, 'TOPLEFT', 0, SPACING)
+		self.BackSlot:Point('BOTTOMLEFT', self.ChestSlot, 'TOPLEFT', 0, SPACING)
+		self.ChestSlot:Point('BOTTOMLEFT', self.ShirtSlot, 'TOPLEFT', 0, SPACING)
+		self.ShirtSlot:Point('BOTTOMLEFT', self.TabardSlot, 'TOPLEFT', 0, SPACING)
+		self.TabardSlot:Point('BOTTOMLEFT', self.WristSlot, 'TOPLEFT', 0, SPACING)
+		self.WristSlot:Point('LEFT', self.BP, 1, 0)
+		self.WristSlot:Point('BOTTOM', self.MainHandSlot, 'TOP', 0, SPACING)
+
+		-- Slot Location : Right
+		self.HandsSlot:Point('BOTTOMRIGHT', self.WaistSlot, 'TOPRIGHT', 0, SPACING)
+		self.WaistSlot:Point('BOTTOMRIGHT', self.LegsSlot, 'TOPRIGHT', 0, SPACING)
+		self.LegsSlot:Point('BOTTOMRIGHT', self.FeetSlot, 'TOPRIGHT', 0, SPACING)
+		self.FeetSlot:Point('BOTTOMRIGHT', self.Finger0Slot, 'TOPRIGHT', 0, SPACING)
+		self.Finger0Slot:Point('BOTTOMRIGHT', self.Finger1Slot, 'TOPRIGHT', 0, SPACING)
+		self.Finger1Slot:Point('BOTTOMRIGHT', self.Trinket0Slot, 'TOPRIGHT', 0, SPACING)
+		self.Trinket0Slot:Point('BOTTOMRIGHT', self.Trinket1Slot, 'TOPRIGHT', 0, SPACING)
+		self.Trinket1Slot:Point('RIGHT', self.BP, -1, 0)
+		self.Trinket1Slot:Point('BOTTOM', self.SecondaryHandSlot, 'TOP', 0, SPACING)
+
+		-- ItemLevel
+		KF:TextSetting(self.Character, nil, { Tag = 'AverageItemLevel', FontSize = 12 }, 'TOP', self.Model)
+	end
+
+	self.Model:Point('TOPLEFT', self.HeadSlot)
+	self.Model:Point('TOPRIGHT', self.HandsSlot)
+	self.Model:Point('BOTTOM', self.BP, 'TOP', 0, SPACING)
+
+	do --<< Information Page >>--
+		self.Info = CreateFrame('ScrollFrame', nil, self)
+		self.Info:SetFrameLevel(CORE_FRAME_LEVEL + 6)
+		self.Info:EnableMouseWheel(1)
+		self.Info:SetScript('OnMouseWheel', self.ScrollFrame_OnMouseWheel)
+
+		self.Info.BG = CreateFrame('Frame', nil, self.Info)
+		self.Info.BG:SetFrameLevel(CORE_FRAME_LEVEL + 2)
+		self.Info.BG:Point('TOPLEFT', self.HeadSlot, 'TOPRIGHT', SPACING, 0)
+		self.Info.BG:Point('RIGHT', self.Trinket1Slot, 'BOTTOMLEFT', -SPACING, 0)
+		self.Info.BG:Point('BOTTOM', self.BP, 'TOP', 0, SPACING)
+		self.Info.BG:SetBackdrop({
+			bgFile = E.media.blankTex,
+			edgeFile = E.media.blankTex,
+			tile = false, tileSize = 0, edgeSize = E.mult,
+			insets = { left = 0, right = 0, top = 0, bottom = 0}
+		})
+		self.Info.BG:SetBackdropColor(0, 0, 0, .7)
+
+		self.Info:Point('TOPLEFT', self.Info.BG, 4, -4)
+		self.Info:Point('BOTTOMRIGHT', self.Info.BG, -4, 7)
+
+		self.Info.Page = CreateFrame('Frame', nil, self.Info)
+		self.Info:SetScrollChild(self.Info.Page)
+		self.Info.Page:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+		self.Info.Page:Point('TOPLEFT', self.Info, 0, 2)
+		self.Info.Page:Point('TOPRIGHT', self.Info, 0, 2)
+
+		for _, CategoryType in pairs(IA.InfoPageCategoryList) do
+			self.Info[CategoryType] = CreateFrame('ScrollFrame', nil, self.Info.Page)
+			self.Info[CategoryType]:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Info[CategoryType]:SetBackdropColor(.08, .08, .08, .8)
+			self.Info[CategoryType]:SetBackdropBorderColor(0, 0, 0)
+			self.Info[CategoryType]:Point('LEFT', self.Info.Page)
+			self.Info[CategoryType]:Point('RIGHT', self.Info.Page)
+			self.Info[CategoryType]:Height(INFO_TAB_SIZE + SPACING * 2)
+
+			self.Info[CategoryType].IconSlot = CreateFrame('Frame', nil, self.Info[CategoryType])
+			self.Info[CategoryType].IconSlot:Size(INFO_TAB_SIZE)
+			self.Info[CategoryType].IconSlot:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Info[CategoryType].IconSlot:Point('TOPLEFT', self.Info[CategoryType], SPACING, -SPACING)
+			self.Info[CategoryType].Icon = self.Info[CategoryType].IconSlot:CreateTexture(nil, 'OVERLAY')
+			self.Info[CategoryType].Icon:SetTexCoord(unpack(E.TexCoords))
+			self.Info[CategoryType].Icon:SetInside()
+
+			self.Info[CategoryType].Tab = CreateFrame('Frame', nil, self.Info[CategoryType])
+			self.Info[CategoryType].Tab:Point('TOPLEFT', self.Info[CategoryType].IconSlot, 'TOPRIGHT', 1, 0)
+			self.Info[CategoryType].Tab:Point('BOTTOMRIGHT', self.Info[CategoryType], 'TOPRIGHT', -SPACING, -(SPACING + INFO_TAB_SIZE))
+			self.Info[CategoryType].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.Info[CategoryType].Tooltip = CreateFrame('Button', nil, self.Info[CategoryType])
+			self.Info[CategoryType].Tooltip:Point('TOPLEFT', self.Info[CategoryType].Icon)
+			self.Info[CategoryType].Tooltip:Point('BOTTOMRIGHT', self.Info[CategoryType].Tab)
+			self.Info[CategoryType].Tooltip:SetFrameLevel(CORE_FRAME_LEVEL + 5)
+			self.Info[CategoryType].Tooltip:SetScript('OnClick', IA.Category_OnClick)
+
+			self.Info[CategoryType].Page = CreateFrame('Frame', nil, self.Info[CategoryType])
+			self.Info[CategoryType]:SetScrollChild(self.Info[CategoryType].Page)
+			self.Info[CategoryType].Page:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+			self.Info[CategoryType].Page:Point('TOPLEFT', self.Info[CategoryType].IconSlot, 'BOTTOMLEFT', 0, -SPACING)
+			self.Info[CategoryType].Page:Point('BOTTOMRIGHT', self.Info[CategoryType], -SPACING, SPACING)
+		end
+
+		do -- Profession Part
+			KF:TextSetting(self.Info.Profession.Tab, TRADE_SKILLS, { FontSize = 10 }, 'LEFT', 6, 1)
+			self.Info.Profession.CategoryHeight = INFO_TAB_SIZE + 34 + SPACING * 3
+			self.Info.Profession.Icon:SetTexture('Interface\\Icons\\Trade_BlackSmithing')
+
+			for i = 1, 2 do
+				self.Info.Profession['Prof'..i] = CreateFrame('Frame', nil, self.Info.Profession.Page)
+				self.Info.Profession['Prof'..i]:Size(20)
+				self.Info.Profession['Prof'..i]:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Info.Profession['Prof'..i]:SetBackdropBorderColor(0, 0, 0)
+
+				self.Info.Profession['Prof'..i].Icon = self.Info.Profession['Prof'..i]:CreateTexture(nil, 'OVERLAY')
+				self.Info.Profession['Prof'..i].Icon:SetTexCoord(unpack(E.TexCoords))
+				self.Info.Profession['Prof'..i].Icon:SetInside()
+
+				self.Info.Profession['Prof'..i].BarFrame = CreateFrame('Frame', nil, self.Info.Profession['Prof'..i])
+				self.Info.Profession['Prof'..i].BarFrame:Size(136, 5)
+				self.Info.Profession['Prof'..i].BarFrame:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Info.Profession['Prof'..i].BarFrame:SetBackdropColor(0, 0, 0)
+				self.Info.Profession['Prof'..i].BarFrame:SetBackdropBorderColor(0, 0, 0)
+				self.Info.Profession['Prof'..i].BarFrame:Point('BOTTOMLEFT', self.Info.Profession['Prof'..i], 'BOTTOMRIGHT', SPACING, 0)
+
+				self.Info.Profession['Prof'..i].Bar = CreateFrame('StatusBar', nil, self.Info.Profession['Prof'..i].BarFrame)
+				self.Info.Profession['Prof'..i].Bar:SetInside()
+				self.Info.Profession['Prof'..i].Bar:SetStatusBarTexture(E.media.normTex)
+				self.Info.Profession['Prof'..i].Bar:SetMinMaxValues(0, 600)
+
+				KF: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)
+
+				KF: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
+
+			self.Info.Profession.Prof1:Point('TOPLEFT', self.Info.Profession.Page, 6, -7)
+			self.Info.Profession.Prof2:Point('TOPLEFT', self.Info.Profession.Page, 'TOP', 6, -7)
+		end
+
+		do -- PvP Category
+			KF:TextSetting(self.Info.PvP.Tab, PVP, { FontSize = 10 }, 'LEFT', 6, 1)
+			self.Info.PvP.CategoryHeight = 90
+			self.Info.PvP.Icon:SetTexture('Interface\\Icons\\achievement_bg_killxenemies_generalsroom')
+
+			self.Info.PvP.PageLeft = CreateFrame('Frame', nil, self.Info.PvP.Page)
+			self.Info.PvP.PageLeft:Point('TOP', self.Info.PvP.Page)
+			self.Info.PvP.PageLeft:Point('LEFT', self.Info.PvP.Page)
+			self.Info.PvP.PageLeft:Point('BOTTOMRIGHT', self.Info.PvP.Page, 'BOTTOM')
+			self.Info.PvP.PageLeft:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+			self.Info.PvP.PageRight = CreateFrame('Frame', nil, self.Info.PvP.Page)
+			self.Info.PvP.PageRight:Point('TOP', self.Info.PvP.Page)
+			self.Info.PvP.PageRight:Point('RIGHT', self.Info.PvP.Page)
+			self.Info.PvP.PageRight:Point('BOTTOMLEFT', self.Info.PvP.Page, 'BOTTOM')
+			self.Info.PvP.PageRight:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+
+			for i = 1, 3 do
+				self.Info.PvP['Bar'..i] = self.Info.PvP.Page:CreateTexture(nil, 'OVERLAY')
+				self.Info.PvP['Bar'..i]:SetTexture(0, 0, 0)
+				self.Info.PvP['Bar'..i]:Width(2)
+			end
+			self.Info.PvP.Bar1:Point('TOP', self.Info.PvP.PageLeft, 0, -SPACING * 2)
+			self.Info.PvP.Bar1:Point('BOTTOM', self.Info.PvP.PageLeft, 0, SPACING * 2)
+			self.Info.PvP.Bar2:Point('TOP', self.Info.PvP.Page, 0, -SPACING * 2)
+			self.Info.PvP.Bar2:Point('BOTTOM', self.Info.PvP.Page, 0, SPACING * 2)
+			self.Info.PvP.Bar3:Point('TOP', self.Info.PvP.PageRight, 0, -SPACING * 2)
+			self.Info.PvP.Bar3:Point('BOTTOM', self.Info.PvP.PageRight, 0, SPACING * 2)
+
+			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 + 5)
+
+				self.Info.PvP[Type].Rank = self.Info.PvP.Page:CreateTexture(nil, 'OVERLAY')
+				self.Info.PvP[Type].Rank:SetTexture('Interface\\ACHIEVEMENTFRAME\\UI-ACHIEVEMENT-SHIELDS')
+				self.Info.PvP[Type].Rank:SetTexCoord(0, .5, 0, .5)
+				self.Info.PvP[Type].Rank:Size(83, 57)
+				self.Info.PvP[Type].Rank:Point('TOP', self.Info.PvP[Type], 0, -10)
+				self.Info.PvP[Type].Rank:Hide()
+				self.Info.PvP[Type].RankGlow = self.Info.PvP.Page:CreateTexture(nil, 'OVERLAY')
+				self.Info.PvP[Type].RankGlow:SetTexture('Interface\\ACHIEVEMENTFRAME\\UI-ACHIEVEMENT-SHIELDS')
+				self.Info.PvP[Type].RankGlow:SetBlendMode('ADD')
+				self.Info.PvP[Type].RankGlow:SetTexCoord(0, .5, 0, .5)
+				self.Info.PvP[Type].RankGlow:Point('TOPLEFT', self.Info.PvP[Type].Rank)
+				self.Info.PvP[Type].RankGlow:Point('BOTTOMRIGHT', self.Info.PvP[Type].Rank)
+				self.Info.PvP[Type].RankGlow:Hide()
+				self.Info.PvP[Type].RankNoLeaf = self.Info.PvP.Page:CreateTexture(nil, 'OVERLAY')
+				self.Info.PvP[Type].RankNoLeaf:SetTexture('Interface\\ACHIEVEMENTFRAME\\UI-Achievement-Progressive-Shield')
+				self.Info.PvP[Type].RankNoLeaf:SetTexCoord(0, .66, 0, .77)
+				self.Info.PvP[Type].RankNoLeaf:Point('CENTER', self.Info.PvP[Type].Rank, 0, 2)
+				self.Info.PvP[Type].RankNoLeaf:SetVertexColor(.2, .4, 1)
+				self.Info.PvP[Type].RankNoLeaf:Size(80, 65)
+
+				KF:TextSetting(self.Info.PvP[Type], nil, { Tag = 'Type', FontSize = 10, FontStyle = 'OUTLINE' }, 'TOPLEFT', self.Info.PvP[Type])
+				self.Info.PvP[Type].Type:Point('TOPRIGHT', self.Info.PvP[Type])
+				self.Info.PvP[Type].Type:SetHeight(22)
+				KF:TextSetting(self.Info.PvP[Type], nil, { Tag = 'Rating', FontSize = 22, FontStyle = 'OUTLINE' }, 'CENTER', self.Info.PvP[Type].Rank, 0, 3)
+				KF:TextSetting(self.Info.PvP[Type], nil, { Tag = 'Record', FontSize = 10, FontStyle = 'OUTLINE' }, 'TOP', self.Info.PvP[Type].Rank, 'BOTTOM', 0, 12)
+			end
+			self.Info.PvP['2vs2']:Point('TOP', self.Info.PvP.Bar1)
+			self.Info.PvP['2vs2']:Point('LEFT', self.Info.PvP.Page)
+			self.Info.PvP['2vs2']:Point('BOTTOMRIGHT', self.Info.PvP.Bar1, 'BOTTOMLEFT', -SPACING, 0)
+			self.Info.PvP['2vs2'].Type:SetText(ARENA_2V2)
+
+			self.Info.PvP['3vs3']:Point('TOPLEFT', self.Info.PvP.Bar1, 'TOPRIGHT', SPACING, 0)
+			self.Info.PvP['3vs3']:Point('BOTTOMRIGHT', self.Info.PvP.Bar2, 'BOTTOMLEFT', -SPACING, 0)
+			self.Info.PvP['3vs3'].Type:SetText(ARENA_3V3)
+
+			self.Info.PvP['5vs5']:Point('TOPLEFT', self.Info.PvP.Bar2, 'TOPRIGHT', SPACING, 0)
+			self.Info.PvP['5vs5']:Point('BOTTOMRIGHT', self.Info.PvP.Bar3, 'BOTTOMLEFT', -SPACING, 0)
+			self.Info.PvP['5vs5'].Type:SetText(ARENA_5V5)
+
+			self.Info.PvP.RB:Point('TOP', self.Info.PvP.Bar3)
+			self.Info.PvP.RB:Point('RIGHT', self.Info.PvP.Page)
+			self.Info.PvP.RB:Point('BOTTOMLEFT', self.Info.PvP.Bar3, 'BOTTOMRIGHT', SPACING, 0)
+			self.Info.PvP.RB.Type:SetText(PVP_RATED_BATTLEGROUNDS)
+		end
+
+		do -- Guild Category
+			KF:TextSetting(self.Info.Guild.Tab, GUILD, { FontSize = 10 }, 'LEFT', 6, 1)
+			self.Info.Guild.CategoryHeight = INFO_TAB_SIZE + 66 + SPACING * 3
+			self.Info.Guild.Icon:SetTexture('Interface\\Icons\\ACHIEVEMENT_GUILDPERK_MASSRESURRECTION')
+
+			self.Info.Guild.Banner = CreateFrame('Frame', nil, self.Info.Guild.Page)
+			self.Info.Guild.Banner:SetInside()
+			self.Info.Guild.Banner:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+
+			self.Info.Guild.BG = self.Info.Guild.Banner:CreateTexture(nil, 'BACKGROUND')
+			self.Info.Guild.BG:Size(33, 44)
+			self.Info.Guild.BG:SetTexCoord(.00781250, .32812500, .01562500, .84375000)
+			self.Info.Guild.BG:SetTexture('Interface\\GuildFrame\\GuildDifficulty')
+			self.Info.Guild.BG:Point('TOP', self.Info.Guild.Page)
+
+			self.Info.Guild.Border = self.Info.Guild.Banner:CreateTexture(nil, 'ARTWORK')
+			self.Info.Guild.Border:Size(33, 44)
+			self.Info.Guild.Border:SetTexCoord(.34375000, .66406250, .01562500, .84375000)
+			self.Info.Guild.Border:SetTexture('Interface\\GuildFrame\\GuildDifficulty')
+			self.Info.Guild.Border:Point('CENTER', self.Info.Guild.BG)
+
+			self.Info.Guild.Emblem = self.Info.Guild.Banner:CreateTexture(nil, 'OVERLAY')
+			self.Info.Guild.Emblem:Size(16)
+			self.Info.Guild.Emblem:SetTexture('Interface\\GuildFrame\\GuildEmblems_01')
+			self.Info.Guild.Emblem:Point('CENTER', self.Info.Guild.BG, 0, 2)
+
+			KF:TextSetting(self.Info.Guild.Banner, nil, { Tag = 'Name', FontSize = 14 }, 'TOP', self.Info.Guild.BG, 'BOTTOM', 0, 7)
+			KF:TextSetting(self.Info.Guild.Banner, nil, { Tag = 'LevelMembers', FontSize = 9 }, 'TOP', self.Info.Guild.Banner.Name, 'BOTTOM', 0, -2)
+		end
+	end
+
+	do --<< Specialization Page >>--
+		self.Spec = CreateFrame('ScrollFrame', nil, self)
+		self.Spec:SetFrameLevel(CORE_FRAME_LEVEL + 6)
+		self.Spec:EnableMouseWheel(1)
+		self.Spec:SetScript('OnMouseWheel', self.ScrollFrame_OnMouseWheel)
+
+		self.Spec.BGFrame = CreateFrame('Frame', nil, self.Spec)
+		self.Spec.BGFrame:SetFrameLevel(CORE_FRAME_LEVEL + 2)
+		self.Spec.BG = self.Spec.BGFrame:CreateTexture(nil, 'BACKGROUND')
+		self.Spec.BG:Point('TOP', self.HeadSlot, 'TOPRIGHT', 0, -28)
+		self.Spec.BG:Point('LEFT', self.WristSlot, 'TOPRIGHT', SPACING, 0)
+		self.Spec.BG:Point('RIGHT', self.Trinket1Slot, 'BOTTOMLEFT', -SPACING, 0)
+		self.Spec.BG:Point('BOTTOM', self.BP, 'TOP', 0, SPACING)
+		self.Spec.BG:SetTexture(0, 0, 0, .7)
+
+		self.Spec:Point('TOPLEFT', self.Spec.BG, 4, -4)
+		self.Spec:Point('BOTTOMRIGHT', self.Spec.BG, -4, 7)
+
+		self.Spec.Page = CreateFrame('Frame', nil, self.Spec)
+		self.Spec:SetScrollChild(self.Spec.Page)
+		self.Spec.Page:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+		self.Spec.Page:Point('TOPLEFT', self.Spec)
+		self.Spec.Page:Point('TOPRIGHT', self.Spec)
+		self.Spec.Page:Height((TALENT_SLOT_SIZE + SPACING * 3) * MAX_TALENT_TIERS + (SPACING + GLYPH_SLOT_HEIGHT) * 3 + 18)
+
+		self.Spec.BottomBorder = self.Spec:CreateTexture(nil, 'OVERLAY')
+		self.Spec.BottomBorder:Point('TOPLEFT', self.Spec.BG, 'BOTTOMLEFT', 0, E.mult)
+		self.Spec.BottomBorder:Point('BOTTOMRIGHT', self.Spec.BG)
+		self.Spec.LeftBorder = self.Spec:CreateTexture(nil, 'OVERLAY')
+		self.Spec.LeftBorder:Point('TOPLEFT', self.Spec.BG)
+		self.Spec.LeftBorder:Point('BOTTOMLEFT', self.Spec.BottomBorder, 'TOPLEFT')
+		self.Spec.LeftBorder:Width(E.mult)
+		self.Spec.RightBorder = self.Spec:CreateTexture(nil, 'OVERLAY')
+		self.Spec.RightBorder:Point('TOPRIGHT', self.Spec.BG)
+		self.Spec.RightBorder:Point('BOTTOMRIGHT', self.Spec.BottomBorder, 'TOPRIGHT')
+		self.Spec.RightBorder:Width(E.mult)
+
+		do -- Specialization Tab
+			for i = 1, MAX_TALENT_GROUPS do
+				self.Spec['Spec'..i] = CreateFrame('Button', nil, self.Spec)
+				self.Spec['Spec'..i]:Size(150, 28)
+				self.Spec['Spec'..i]:SetScript('OnClick', function() self:ToggleSpecializationTab(i, self.CurrentInspectData) end)
+
+				self.Spec['Spec'..i].Tab = CreateFrame('Frame', nil, self.Spec['Spec'..i])
+				self.Spec['Spec'..i].Tab:Size(120, 28)
+				self.Spec['Spec'..i].Tab:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = 0,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Spec['Spec'..i].Tab:SetBackdropColor(0, 0, 0, .7)
+				self.Spec['Spec'..i].Tab:SetBackdropBorderColor(0, 0, 0, 0)
+				self.Spec['Spec'..i].Tab:Point('TOPRIGHT', self.Spec['Spec'..i])
+				KF:TextSetting(self.Spec['Spec'..i].Tab, nil, { FontSize = 10, FontStyle = 'OUTLINE' }, 'TOPLEFT', 0, 0)
+				self.Spec['Spec'..i].Tab.text:Point('BOTTOMRIGHT', 0, -4)
+
+				self.Spec['Spec'..i].Icon = CreateFrame('Frame', nil, self.Spec['Spec'..i].Tab)
+				self.Spec['Spec'..i].Icon:Size(27, 24)
+				self.Spec['Spec'..i].Icon:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Spec['Spec'..i].Icon:SetBackdropColor(0, 0, 0, .7)
+				self.Spec['Spec'..i].Icon:Point('TOPLEFT', self.Spec['Spec'..i])
+
+				self.Spec['Spec'..i].Texture = self.Spec['Spec'..i].Icon:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].Texture:SetTexCoord(.08, .92, .16, .84)
+				self.Spec['Spec'..i].Texture:SetInside()
+
+				self.Spec['Spec'..i].TopBorder = self.Spec['Spec'..i].Tab:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].TopBorder:Point('TOPLEFT', self.Spec['Spec'..i].Tab)
+				self.Spec['Spec'..i].TopBorder:Point('BOTTOMRIGHT', self.Spec['Spec'..i].Tab, 'TOPRIGHT', 0, -E.mult)
+
+				self.Spec['Spec'..i].LeftBorder = self.Spec['Spec'..i].Tab:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].LeftBorder:Point('TOPLEFT', self.Spec['Spec'..i].TopBorder, 'BOTTOMLEFT')
+				self.Spec['Spec'..i].LeftBorder:Point('BOTTOMRIGHT', self.Spec['Spec'..i].Tab, 'BOTTOMLEFT', E.mult, 0)
+
+				self.Spec['Spec'..i].RightBorder = self.Spec['Spec'..i].Tab:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].RightBorder:Point('TOPLEFT', self.Spec['Spec'..i].TopBorder, 'BOTTOMRIGHT', -E.mult, 0)
+				self.Spec['Spec'..i].RightBorder:Point('BOTTOMRIGHT', self.Spec['Spec'..i].Tab)
+
+				self.Spec['Spec'..i].BottomLeftBorder = self.Spec['Spec'..i].Tab:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].BottomLeftBorder:Point('TOPLEFT', self.Spec.BG, 0, E.mult)
+				self.Spec['Spec'..i].BottomLeftBorder:Point('BOTTOMRIGHT', self.Spec['Spec'..i].LeftBorder, 'BOTTOMLEFT')
+
+				self.Spec['Spec'..i].BottomRightBorder = self.Spec['Spec'..i].Tab:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Spec'..i].BottomRightBorder:Point('TOPRIGHT', self.Spec.BG, 0, E.mult)
+				self.Spec['Spec'..i].BottomRightBorder:Point('BOTTOMLEFT', self.Spec['Spec'..i].RightBorder, 'BOTTOMRIGHT')
+			end
+			self.Spec.Spec1:Point('BOTTOMLEFT', self.Spec.BG, 'TOPLEFT', 20, 0)
+			self.Spec.Spec2:Point('BOTTOMRIGHT', self.Spec.BG, 'TOPRIGHT', -20, 0)
+		end
+
+		for i = 1, MAX_TALENT_TIERS do
+			self.Spec['TalentTier'..i] = CreateFrame('Frame', nil, self.Spec.Page)
+			self.Spec['TalentTier'..i]:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Spec['TalentTier'..i]:SetBackdropColor(.08, .08, .08)
+			self.Spec['TalentTier'..i]:SetBackdropBorderColor(0, 0, 0)
+			self.Spec['TalentTier'..i]:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+			self.Spec['TalentTier'..i]:Size(352, TALENT_SLOT_SIZE + SPACING * 2)
+
+			for k = 1, NUM_TALENT_COLUMNS do
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)] = CreateFrame('Frame', nil, self.Spec['TalentTier'..i])
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:Size(114, TALENT_SLOT_SIZE)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon = CreateFrame('Frame', nil, self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)])
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:Size(20)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:SetBackdrop({
+					bgFile = E.media.blankTex,
+					edgeFile = E.media.blankTex,
+					tile = false, tileSize = 0, edgeSize = E.mult,
+					insets = { left = 0, right = 0, top = 0, bottom = 0}
+				})
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture = self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:CreateTexture(nil, 'OVERLAY')
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture:SetTexCoord(unpack(E.TexCoords))
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture:SetInside()
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:Point('LEFT', self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)], SPACING, 0)
+				KF:TextSetting(self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)], nil, { FontSize = 9, directionH = 'LEFT' }, 'TOPLEFT', self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon, 'TOPRIGHT', SPACING, SPACING)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:Point('BOTTOMLEFT', self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon, 'BOTTOMRIGHT', SPACING, -SPACING)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:Point('RIGHT', -SPACING, 0)
+
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip = CreateFrame('Button', nil, self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)])
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip:SetFrameLevel(CORE_FRAME_LEVEL + 5)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip:SetInside()
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip:SetScript('OnClick', self.OnClick)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip:SetScript('OnEnter', self.OnEnter)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip:SetScript('OnLeave', self.OnLeave)
+			end
+
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + 1)]:Point('RIGHT', self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + 2)], 'LEFT', -2, 0)
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + 2)]:Point('CENTER', self.Spec['TalentTier'..i])
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + 3)]:Point('LEFT', self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + 2)], 'RIGHT', 2, 0)
+
+			if i > 1 then
+				self.Spec['TalentTier'..i]:Point('TOP', self.Spec['TalentTier'..(i - 1)], 'BOTTOM', 0, -SPACING)
+			end
+		end
+
+		self.Spec.TalentTier1:Point('TOP', self.Spec.Page)
+
+		for _, groupName in pairs({ 'MAJOR_GLYPH', 'MINOR_GLYPH' }) do
+			self.Spec['GLYPH_'..groupName] = CreateFrame('Frame', nil, self.Spec.Page)
+			self.Spec['GLYPH_'..groupName]:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Spec['GLYPH_'..groupName]:SetBackdropColor(.08, .08, .08)
+			self.Spec['GLYPH_'..groupName]:SetBackdropBorderColor(0, 0, 0)
+			self.Spec['GLYPH_'..groupName]:Height(GLYPH_SLOT_HEIGHT * 3 + SPACING * 3 + 18)
+			KF:TextSetting(self.Spec['GLYPH_'..groupName], '|cffceff00<|r '.._G[groupName]..' |cffceff00>|r', { FontSize = 10 }, 'BOTTOM', self.Spec['GLYPH_'..groupName], 0, 4)
+		end
+
+		for i = 1, NUM_GLYPH_SLOTS do
+			self.Spec['Glyph'..i] = CreateFrame('Button', nil, self.Spec.Page)
+			self.Spec['Glyph'..i]:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Spec['Glyph'..i]:SetFrameLevel(CORE_FRAME_LEVEL + 4)
+			self.Spec['Glyph'..i]:Height(GLYPH_SLOT_HEIGHT)
+
+			self.Spec['Glyph'..i].NeedLevel = (i == 1 or i == 2) and 25 or (i == 3 or i == 4) and 50 or 75
+
+			self.Spec['Glyph'..i].Icon = CreateFrame('Frame', nil, self.Spec['Glyph'..i])
+			self.Spec['Glyph'..i].Icon:Size(16)
+			self.Spec['Glyph'..i].Icon:SetBackdrop({
+				bgFile = E.media.blankTex,
+				edgeFile = E.media.blankTex,
+				tile = false, tileSize = 0, edgeSize = E.mult,
+				insets = { left = 0, right = 0, top = 0, bottom = 0}
+			})
+			self.Spec['Glyph'..i].Icon:SetBackdropColor(.15, .15, .15)
+			self.Spec['Glyph'..i].Icon:SetFrameLevel(CORE_FRAME_LEVEL + 5)
+			self.Spec['Glyph'..i].Icon.Texture = self.Spec['Glyph'..i].Icon:CreateTexture(nil, 'OVERLAY')
+			self.Spec['Glyph'..i].Icon.Texture:SetTexCoord(unpack(E.TexCoords))
+			self.Spec['Glyph'..i].Icon.Texture:SetInside()
+			self.Spec['Glyph'..i].Icon:Point('LEFT', self.Spec['Glyph'..i], SPACING, 0)
+
+			self.Spec['Glyph'..i].Tooltip = CreateFrame('Button', nil, self.Spec['Glyph'..i])
+			self.Spec['Glyph'..i].Tooltip:SetFrameLevel(CORE_FRAME_LEVEL + 6)
+			self.Spec['Glyph'..i].Tooltip:SetInside()
+			self.Spec['Glyph'..i].Tooltip:SetScript('OnClick', self.OnClick)
+			self.Spec['Glyph'..i].Tooltip:SetScript('OnEnter', self.OnEnter)
+			self.Spec['Glyph'..i].Tooltip:SetScript('OnLeave', self.OnLeave)
+			self.Spec['Glyph'..i].Tooltip.EnableAuctionSearch = true
+
+			KF:TextSetting(self.Spec['Glyph'..i], nil, { FontSize = 9, directionH = 'LEFT' }, 'LEFT', self.Spec['Glyph'..i].Icon, 'RIGHT', SPACING, 0)
+			self.Spec['Glyph'..i].text:Point('RIGHT', self.Spec['Glyph'..i], -SPACING, 0)
+		end
+
+		self.Spec.Glyph2:Point('TOP', self.Spec.GLYPH_MAJOR_GLYPH, 0, -SPACING)
+		self.Spec.Glyph2:Point('LEFT', self.Spec.GLYPH_MAJOR_GLYPH, SPACING, 0)
+		self.Spec.Glyph2:Point('RIGHT', self.Spec.GLYPH_MAJOR_GLYPH, -SPACING, 0)
+		self.Spec.Glyph4:Point('TOPLEFT', self.Spec.Glyph2, 'BOTTOMLEFT', 0, -SPACING)
+		self.Spec.Glyph4:Point('TOPRIGHT', self.Spec.Glyph2, 'BOTTOMRIGHT', 0, -SPACING)
+		self.Spec.Glyph6:Point('TOPLEFT', self.Spec.Glyph4, 'BOTTOMLEFT', 0, -SPACING)
+		self.Spec.Glyph6:Point('TOPRIGHT', self.Spec.Glyph4, 'BOTTOMRIGHT', 0, -SPACING)
+
+		self.Spec.Glyph1:Point('TOP', self.Spec.GLYPH_MINOR_GLYPH, 0, -SPACING)
+		self.Spec.Glyph1:Point('LEFT', self.Spec.GLYPH_MINOR_GLYPH, SPACING, 0)
+		self.Spec.Glyph1:Point('RIGHT', self.Spec.GLYPH_MINOR_GLYPH, -SPACING, 0)
+		self.Spec.Glyph3:Point('TOPLEFT', self.Spec.Glyph1, 'BOTTOMLEFT', 0, -SPACING)
+		self.Spec.Glyph3:Point('TOPRIGHT', self.Spec.Glyph1, 'BOTTOMRIGHT', 0, -SPACING)
+		self.Spec.Glyph5:Point('TOPLEFT', self.Spec.Glyph3, 'BOTTOMLEFT', 0, -SPACING)
+		self.Spec.Glyph5:Point('TOPRIGHT', self.Spec.Glyph3, 'BOTTOMRIGHT', 0, -SPACING)
+
+		self.Spec.GLYPH_MAJOR_GLYPH:Point('TOPLEFT', self.Spec['TalentTier'..MAX_TALENT_TIERS], 'BOTTOMLEFT', 0, -SPACING)
+		self.Spec.GLYPH_MAJOR_GLYPH:Point('TOPRIGHT', self.Spec['TalentTier'..MAX_TALENT_TIERS], 'BOTTOM', -2, -SPACING)
+		self.Spec.GLYPH_MINOR_GLYPH:Point('TOPLEFT', self.Spec['TalentTier'..MAX_TALENT_TIERS], 'BOTTOM', 2, -SPACING)
+		self.Spec.GLYPH_MINOR_GLYPH:Point('TOPRIGHT', self.Spec['TalentTier'..MAX_TALENT_TIERS], 'BOTTOMRIGHT', 0, -SPACING)
+	end
+
+	do --<< Scanning Tooltip >>--
+		self.ScanTTForInspecting = CreateFrame('GameTooltip', 'InspectArmoryScanTT_I', nil, 'GameTooltipTemplate')
+		self.ScanTTForInspecting:SetOwner(UIParent, 'ANCHOR_NONE')
+		self.ScanTT = CreateFrame('GameTooltip', 'InspectArmoryScanTT', nil, 'GameTooltipTemplate')
+		self.ScanTT:SetOwner(UIParent, 'ANCHOR_NONE')
+	end
+
+	do --<< UnitPopup Setting >>--
+		InspectArmory_UnitPopup.Highlight = InspectArmory_UnitPopup:CreateTexture(nil, 'BACKGROUND')
+		InspectArmory_UnitPopup.Highlight:SetTexture('Interface\\QuestFrame\\UI-QuestTitleHighlight')
+		InspectArmory_UnitPopup.Highlight:SetBlendMode('ADD')
+		InspectArmory_UnitPopup.Highlight:SetAllPoints()
+		InspectArmory_UnitPopup:SetHighlightTexture(InspectArmory_UnitPopup.Highlight)
+
+		InspectArmory_UnitPopup:SetScript('OnEnter', function()
+			UIDropDownMenu_StopCounting(DropDownList1)
+		end)
+		InspectArmory_UnitPopup:SetScript('OnLeave', function()
+			UIDropDownMenu_StartCounting(DropDownList1)
+		end)
+		InspectArmory_UnitPopup:SetScript('OnHide', function(self)
+			if self.Anchored then
+				self.Anchored = nil
+				self.Data = nil
+				self:SetParent(nil)
+				self:ClearAllPoints()
+				self:Hide()
+			end
+		end)
+		InspectArmory_UnitPopup:SetScript('OnClick', function(self)
+			local SendChannel
+
+			if AISM and AISM.AISMUserList[self.Data.TableIndex] then
+				if self.Data.Realm == Info.MyRealm then
+					SendChannel = 'WHISPER'
+				elseif AISM.AISMUserList[self.Data.TableIndex] == 'GUILD' then
+					SendChannel = 'GUILD'
+				elseif Info.CurrentGroupMode ~= 'NoGroup' then
+					SendChannel = IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and 'INSTANCE_CHAT' or string.upper(Info.CurrentGroupMode)
+				end
+			end
+
+			if AISM and SendChannel then
+				ENI.CancelInspect(self.Data.TableIndex)
+				IA:UnregisterEvent('INSPECT_READY')
+
+				IA.NeedModelSetting = true
+				wipe(IA.CurrentInspectData)
+				E:CopyTable(IA.CurrentInspectData, IA.Default_CurrentInspectData)
+				AISM.CurrentInspectData[self.Data.TableIndex] = {
+					UnitID = self.Data.Unit,
+				}
+
+				local TableIndex = self.Data.TableIndex
+				AISM:RegisterInspectDataRequest(function(User, Prefix, UserData)
+					if Prefix == 'AISM_Inspect' and User == TableIndex then
+						E:CopyTable(IA.CurrentInspectData, UserData)
+						IA:ShowFrame(IA.CurrentInspectData)
+
+						return true
+					end
+				end, 'InspectArmory', true)
+				SendAddonMessage('AISM_Inspect', 'AISM_DataRequestForInspecting:'..self.Data.Name..'-'..self.Data.Realm, SendChannel, self.Data.TableIndex)
+			end
+
+			if self.Data.Unit then
+				IA.InspectUnit(self.Data.Unit, { CancelInspectByManual = 'KnightInspect' })
+			end
+
+			DropDownList1:Hide()
+		end)
+		InspectArmory_UnitPopup:SetScript('OnUpdate', function(self)
+			if not (self:GetPoint() and self:GetParent()) then
+				self:Hide()
+				return
+			end
+
+			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(KF:Color_Value(ButtonName))
+				self:Enable()
+			else
+				self:SetText(ButtonName)
+				self:Disable()
+			end
+		end)
+
+		InspectArmory_UnitPopup.CreateDropDownButton = function(Button, DataTable)
+			if not Button then
+				Button = UIDropDownMenu_CreateInfo()
+				Button.notCheckable = 1
+				UIDropDownMenu_AddButton(Button)
+
+				Button = _G['DropDownList1Button'..DropDownList1.numButtons]
+			end
+
+			Button.value = 'InspectArmory'
+			Button:SetText((' '):rep(strlen(ButtonName)))
+
+			InspectArmory_UnitPopup:Show()
+			InspectArmory_UnitPopup:SetParent('DropDownList1')
+			InspectArmory_UnitPopup:SetFrameStrata(Button:GetFrameStrata())
+			InspectArmory_UnitPopup:SetFrameLevel(Button:GetFrameLevel() + 1)
+			InspectArmory_UnitPopup:ClearAllPoints()
+			InspectArmory_UnitPopup:Point('TOPLEFT', Button)
+			InspectArmory_UnitPopup:Point('BOTTOMRIGHT', Button)
+			InspectArmory_UnitPopup.Anchored = true
+			InspectArmory_UnitPopup.Data = DataTable
+		end
+
+		hooksecurefunc('UnitPopup_ShowMenu', function(Menu, Type, Unit, Name)
+			if Info.InspectArmory_Activate and UIDROPDOWNMENU_MENU_LEVEL == 1 and IA.UnitPopupList[Type] then
+				local Button
+				local DataTable = {
+					Name = Menu.name or Name,
+					Unit = UnitExists(Menu.name) and Menu.name or Unit,
+					Realm = Menu.server ~= '' and Menu.server or Info.MyRealm
+				}
+				DataTable.TableIndex = DataTable.Unit and GetUnitName(DataTable.Unit, 1) or DataTable.Name..(DataTable.Realm and DataTable.Realm ~= '' and DataTable.Realm ~= Info.MyRealm and '-'..DataTable.Realm or '')
+
+				if DataTable.Name == E.myname or 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
+				end
+
+				for i = 1, DropDownList1.numButtons do
+					if _G['DropDownList1Button'..i].value == 'INSPECT' then
+						Button = _G['DropDownList1Button'..i]
+						break
+					end
+				end
+
+				if AISM and not (AISM.AISMUserList[DataTable.TableIndex] or AISM.GroupMemberData[DataTable.TableIndex]) then
+					local isSending
+
+					if DataTable.Unit and not (UnitCanAttack('player', DataTable.Unit) or not UnitIsConnected(DataTable.Unit) or not UnitIsPlayer(DataTable.Unit)) then
+						if DataTable.Realm == Info.MyRealm or Info.CurrentGroupMode ~= 'NoGroup' then
+							isSending = 'AISM_CheckResponse'
+							SendAddonMessage('AISM', 'AISM_Check', DataTable.Realm == Info.MyRealm and 'WHISPER' or IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and 'INSTANCE_CHAT' or string.upper(Info.CurrentGroupMode), DataTable.Name)
+						end
+					elseif Menu.which == 'GUILD' then
+						isSending = 'AISM_GUILD_CheckResponse'
+						SendAddonMessage('AISM', 'AISM_GUILD_Check', DataTable.Realm == Info.MyRealm and 'WHISPER' or 'GUILD', DataTable.Name)
+					elseif DataTable.Realm == Info.MyRealm then
+						isSending = 'AISM_CheckResponse'
+						SendAddonMessage('AISM', 'AISM_Check', 'WHISPER', DataTable.Name)
+					end
+
+					if isSending then
+						AISM:RegisterInspectDataRequest(function(User, _, Message)
+							if User == DataTable.TableIndex and Message == isSending then
+								InspectArmory_UnitPopup.CreateDropDownButton(Button, DataTable)
+
+								return true
+							end
+						end, 'InspectArmory_Checking')
+					end
+				end
+
+				if DataTable.Unit or Button or (AISM and (AISM.AISMUserList[DataTable.TableIndex] or AISM.GroupMemberData[DataTable.TableIndex]))then
+					InspectArmory_UnitPopup.CreateDropDownButton(Button, DataTable)
+				end
+			end
+		end)
+	end
+
+	do --<< Updater >>--
+		self.Updater = CreateFrame('Frame')
+		self.Updater:Hide()
+	end
+
+	HideUIPanel(self)
+
+	self.CreateInspectFrame = nil
+end
+
+
+
+function IA:ClearTooltip(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
+
+
+function IA:INSPECT_HONOR_UPDATE()
+	if self == 'INSPECT_HONOR_UPDATE' or HasInspectHonorData() then
+		for i, Type in pairs({ '2vs2', '3vs3', '5vs5' }) do
+			IA.CurrentInspectData.PvP[Type] = { GetInspectArenaData(i) }
+			for i = 4, #IA.CurrentInspectData.PvP[Type] do
+				IA.CurrentInspectData.PvP[Type][i] = nil
+			end
+		end
+		IA.CurrentInspectData.PvP.RB = { GetInspectRatedBGData() }
+		IA.CurrentInspectData.PvP.Honor = select(5, GetInspectHonorData())
+	end
+
+	if not IA.ForbidUpdatePvPInformation then
+		IA:InspectFrame_PvPSetting(IA.CurrentInspectData)
+	end
+end
+
+
+function IA:INSPECT_READY(InspectedUnitGUID)
+	local TableIndex = IA.CurrentInspectData.Name..(IA.CurrentInspectData.Realm and '-'..IA.CurrentInspectData.Realm or '')
+	local UnitID = TableIndex
+	local Name, Realm = UnitFullName(UnitID)
+
+	if not Name then
+		UnitID = IA.CurrentInspectData.UnitID
+		Name, Realm = UnitFullName(UnitID)
+	end
+
+	if not Name then
+		_, _, _, _, _, Name, Realm = GetPlayerInfoByGUID(InspectedUnitGUID)
+	end
+
+	if not (IA.CurrentInspectData.Name == Name and IA.CurrentInspectData.Realm == Realm) then
+		return
+	elseif HasInspectHonorData() then
+		IA:INSPECT_HONOR_UPDATE()
+	end
+
+	_, _, IA.CurrentInspectData.Race, IA.CurrentInspectData.RaceID, IA.CurrentInspectData.GenderID = GetPlayerInfoByGUID(InspectedUnitGUID)
+
+	local NeedReinspect
+	local CurrentSetItem = {}
+	local Slot, SlotTexture, SlotLink, CheckSpace, R, G, B, TooltipText, TransmogrifiedItem, SetName, SetItemCount, SetItemMax, SetOptionCount
+	for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+		Slot = IA[SlotName]
+		IA.CurrentInspectData.Gear[SlotName] = {}
+
+		SlotTexture = GetInventoryItemTexture(UnitID, Slot.ID)
+
+		if SlotTexture and SlotTexture..'.blp' ~= Slot.EmptyTexture then
+			SlotLink = GetInventoryItemLink(UnitID, Slot.ID)
+
+			if not SlotLink then
+				NeedReinspect = true
+			else
+				IA.CurrentInspectData.Gear[SlotName].ItemLink = SlotLink
+
+				IA:ClearTooltip(IA.ScanTTForInspecting)
+				IA.ScanTTForInspecting:SetInventoryItem(UnitID, Slot.ID)
+
+				TransmogrifiedItem = nil
+				CheckSpace = 2
+				SetOptionCount = 1
+
+				for i = 1, IA.ScanTTForInspecting:NumLines() do
+					TooltipText = _G['InspectArmoryScanTT_ITextLeft'..i]:GetText()
+
+					if not TransmogrifiedItem and TooltipText:match(TRANSMOGRIFIED_HEADER) then -- TooltipText:match(Info.Armory_Constants.TransmogrifiedKey)
+						if type(IA.CurrentInspectData.Gear[SlotName].Transmogrify) ~= 'number' then
+							IA.CurrentInspectData.Gear[SlotName].Transmogrify = _G['InspectArmoryScanTT_ITextLeft'..(i + 1)]:GetText() --TooltipText:match(Info.Armory_Constants.TransmogrifiedKey)
+						end
+
+						TransmogrifiedItem = true
+					end
+
+					SetName, SetItemCount, SetItemMax = TooltipText: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
+							NeedReinspect = true
+
+							break
+						else
+							if not (CurrentSetItem[SetName] or IA.CurrentInspectData.SetItem[SetName]) then
+								NeedReinspect = true
+							end
+
+							CurrentSetItem[SetName] = CurrentSetItem[SetName] or {}
+
+							for k = 1, IA.ScanTTForInspecting:NumLines() do
+								TooltipText = _G['InspectArmoryScanTT_ITextLeft'..(i+k)]:GetText()
+
+								if TooltipText == ' ' then
+									CheckSpace = CheckSpace - 1
+
+									if CheckSpace == 0 then break end
+								elseif CheckSpace == 2 then
+									R, G, B = _G['InspectArmoryScanTT_ITextLeft'..(i+k)]:GetTextColor()
+
+									if R > LIGHTYELLOW_FONT_COLOR.r - .01 and R < LIGHTYELLOW_FONT_COLOR.r + .01 and G > LIGHTYELLOW_FONT_COLOR.g - .01 and G < LIGHTYELLOW_FONT_COLOR.g + .01 and B > LIGHTYELLOW_FONT_COLOR.b - .01 and B < LIGHTYELLOW_FONT_COLOR.b + .01 then
+										TooltipText = LIGHTYELLOW_FONT_COLOR_CODE..TooltipText
+									else
+										TooltipText = GRAY_FONT_COLOR_CODE..TooltipText
+									end
+
+									if CurrentSetItem[SetName][k] and CurrentSetItem[SetName][k] ~= TooltipText then
+										NeedReinspect = true
+									end
+
+									CurrentSetItem[SetName][k] = TooltipText
+								elseif TooltipText:find(Info.Armory_Constants.ItemSetBonusKey) then
+									TooltipText = (E:RGBToHex(_G['InspectArmoryScanTT_ITextLeft'..(i+k)]:GetTextColor()))..TooltipText..'|r'
+									--TooltipText = TooltipText:match("^%((%d)%)%s.+:%s.+$") or true
+
+									if CurrentSetItem[SetName]['SetOption'..SetOptionCount] and CurrentSetItem[SetName]['SetOption'..SetOptionCount] ~= TooltipText then
+										NeedReinspect = true
+									end
+
+									CurrentSetItem[SetName]['SetOption'..SetOptionCount] = TooltipText
+									SetOptionCount = SetOptionCount + 1
+								end
+							end
+							IA.CurrentInspectData.SetItem[SetName] = CurrentSetItem[SetName]
+
+							break
+						end
+					end
+
+					if CheckSpace == 0 then break end
+				end
+			end
+		end
+	end
+
+	if IA.CurrentInspectData.SetItem then
+		for SetName in pairs(IA.CurrentInspectData.SetItem) do
+			if not CurrentSetItem[SetName] then
+				IA.CurrentInspectData.SetItem[SetName] = nil
+			end
+		end
+	end
+
+	-- Specialization
+	IA.CurrentInspectData.Specialization[1].SpecializationID = GetInspectSpecialization(UnitID)
+	local TalentID, isSelected
+	for i = 1, MAX_TALENT_TIERS do
+		for k = 1, NUM_TALENT_COLUMNS do
+			TalentID, _, _, isSelected = GetTalentInfo(i, k, 1, true, UnitID)
+
+			IA.CurrentInspectData.Specialization[1]['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)] = { TalentID, isSelected }
+		end
+	end
+
+	-- Glyph
+	local SpellID, GlyphID
+	for i = 1, NUM_GLYPH_SLOTS do
+		_, _, _, SpellID, _, GlyphID = GetGlyphSocketInfo(i, nil, true, UnitID)
+
+		IA.CurrentInspectData.Glyph[1]['Glyph'..i..'SpellID'] = SpellID or 0
+		IA.CurrentInspectData.Glyph[1]['Glyph'..i..'ID'] = GlyphID or 0
+	end
+
+	-- Guild
+	IA.CurrentInspectData.guildPoint, IA.CurrentInspectData.guildNumMembers = GetInspectGuildInfo(UnitID)
+	IA.CurrentInspectData.guildEmblem = { GetGuildLogoInfo(UnitID) }
+
+	if NeedReinspect then
+		return
+	end
+
+	IA.ForbidUpdatePvPInformation = nil
+	IA:ShowFrame(IA.CurrentInspectData)
+
+	if IA.ReinspectCount > 0 then
+		IA.ReinspectCount = IA.ReinspectCount - 1
+	else
+		ENI.CancelInspect(TableIndex, 'KnightInspect')
+		IA:UnregisterEvent('INSPECT_READY')
+	end
+end
+
+
+IA.InspectUnit = function(UnitID, Properties)
+	if UnitID == 'mouseover' and not UnitExists('mouseover') and UnitExists('target') then
+		UnitID = 'target'
+	end
+
+	if not UnitIsPlayer(UnitID) then
+		return
+	elseif UnitIsDeadOrGhost('player') then
+		print(L['KF']..' : '..L["You can't inspect while dead."])
+		return
+	elseif not UnitIsVisible(UnitID) then
+
+		return
+	else
+		UnitID = NotifyInspect(UnitID, Properties) or UnitID
+
+		wipe(IA.CurrentInspectData)
+		E:CopyTable(IA.CurrentInspectData, IA.Default_CurrentInspectData)
+
+		IA.CurrentInspectData.UnitID = UnitID
+		IA.CurrentInspectData.Title = UnitPVPName(UnitID)
+		IA.CurrentInspectData.Level = UnitLevel(UnitID)
+		IA.CurrentInspectData.Name, IA.CurrentInspectData.Realm = UnitFullName(UnitID)
+		_, IA.CurrentInspectData.Class, IA.CurrentInspectData.ClassID = UnitClass(UnitID)
+		IA.CurrentInspectData.guildName, IA.CurrentInspectData.guildRankName = GetGuildInfo(UnitID)
+
+		IA.CurrentInspectData.Realm = IA.CurrentInspectData.Realm ~= '' and IA.CurrentInspectData.Realm ~= Info.MyRealm and IA.CurrentInspectData.Realm or nil
+
+		IA.ReinspectCount = 1
+		IA.NeedModelSetting = true
+		IA.ForbidUpdatePvPInformation = true
+		IA:RegisterEvent('INSPECT_READY')
+		IA:RegisterEvent('INSPECT_HONOR_UPDATE')
+	end
+end
+
+
+function IA:ShowFrame(DataTable)
+	self.GET_ITEM_INFO_RECEIVED = nil
+	self:UnregisterEvent('GET_ITEM_INFO_RECEIVED')
+
+	for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+		if DataTable.Gear[SlotName] and DataTable.Gear[SlotName].ItemLink and not GetItemInfo(DataTable.Gear[SlotName].ItemLink) then
+			if not self.GET_ITEM_INFO_RECEIVED then
+				self.GET_ITEM_INFO_RECEIVED = function() self:ShowFrame(DataTable) end
+			end
+		end
+	end
+
+	if self.GET_ITEM_INFO_RECEIVED then
+		self:RegisterEvent('GET_ITEM_INFO_RECEIVED')
+		return
+	end
+
+	self.Updater:Show()
+	self.Updater:SetScript('OnUpdate', function()
+		if not self:InspectFrame_DataSetting(DataTable) then
+			self.Updater:SetScript('OnUpdate', nil)
+			self.Updater:Hide()
+
+			self:InspectFrame_PvPSetting(DataTable)
+			ShowUIPanel(InspectArmory)
+		end
+	end)
+end
+
+
+function IA:InspectFrame_DataSetting(DataTable)
+	local Slot, ErrorDetected, NeedUpdate, NeedUpdateList, R, G, B
+	local ItemCount, ItemTotal = 0, 0
+
+	do	--<< Equipment Slot and Enchant, Gem Setting >>--
+		local ItemData, ItemRarity, BasicItemLevel, TrueItemLevel, ItemUpgradeID, ItemTexture, IsEnchanted, CurrentLineText, GemCount_Default, GemCount_Enable, GemCount_Now, GemCount
+
+		-- Setting except shirt and tabard
+		for _, SlotName in pairs(self.GearUpdated or Info.Armory_Constants.GearList) do
+			if SlotName ~= 'ShirtSlot' and SlotName ~= 'TabardSlot' then
+				Slot = self[SlotName]
+
+				do --<< Clear Setting >>--
+					NeedUpdate, ErrorDetected, TrueItemLevel, IsEnchanted, ItemUpgradeID, ItemTexture, R, G, B = nil, nil, nil, nil, nil, nil, 0, 0, 0
+
+					Slot.Link = nil
+					Slot.ILvL = nil
+					Slot.ItemLevel:SetText(nil)
+					Slot.Gradation.ItemLevel:SetText(nil)
+					Slot.Gradation.ItemEnchant:SetText(nil)
+					for i = 1, MAX_NUM_SOCKETS do
+						Slot['Socket'..i].Texture:SetTexture(nil)
+						Slot['Socket'..i].GemItemID = nil
+						Slot['Socket'..i].GemType = nil
+						Slot['Socket'..i]:Hide()
+					end
+					Slot.EnchantWarning:Hide()
+					Slot.EnchantWarning.Message = nil
+					Slot.SocketWarning:Point(Slot.Direction, Slot.Socket1)
+					Slot.SocketWarning:Hide()
+					Slot.SocketWarning.Link = nil
+					Slot.SocketWarning.Message = nil
+				end
+
+				if DataTable.Gear[SlotName].ItemLink then
+					_, Slot.Link = GetItemInfo(DataTable.Gear[SlotName].ItemLink)
+
+					if Slot.Link then
+						do --<< Gem Parts >>--
+							ItemData = { strsplit(':', Slot.Link) }
+							ItemData[4], ItemData[5], ItemData[6], ItemData[7] = 0, 0, 0, 0
+
+							for i = 1, #ItemData do
+								ItemData.FixedLink = (ItemData.FixedLink and ItemData.FixedLink..':' or '')..ItemData[i]
+							end
+
+							self:ClearTooltip(self.ScanTT)
+							self.ScanTT:SetHyperlink(ItemData.FixedLink)
+
+							GemCount_Default, GemCount_Now, GemCount = 0, 0, 0
+
+							-- First, Counting default gem sockets
+							for i = 1, MAX_NUM_SOCKETS do
+								ItemTexture = _G['InspectArmoryScanTTTexture'..i]:GetTexture()
+
+								if ItemTexture and ItemTexture:find('Interface\\ItemSocketingFrame\\') then
+									GemCount_Default = GemCount_Default + 1
+									Slot['Socket'..GemCount_Default].GemType = strupper(gsub(ItemTexture, 'Interface\\ItemSocketingFrame\\UI--EmptySocket--', ''))
+								end
+							end
+
+							-- Second, Check if slot's item enable to adding a socket
+							GemCount_Enable = GemCount_Default
+							--[[
+							if (SlotName == 'WaistSlot' and DataTable.Level >= 70) or -- buckle
+								((SlotName == 'WristSlot' or SlotName == 'HandsSlot') and (DataTable.Profession[1].Name == GetSpellInfo(110396) and DataTable.Profession[1].Level >= 550 or DataTable.Profession[2].Name == GetSpellInfo(110396) and DataTable.Profession[2].Level >= 550)) then -- BlackSmith
+
+								GemCount_Enable = GemCount_Enable + 1
+								Slot['Socket'..GemCount_Enable].GemType = 'PRISMATIC'
+							end
+							]]
+
+							self:ClearTooltip(self.ScanTT)
+							self.ScanTT:SetHyperlink(Slot.Link)
+
+							-- Apply current item's gem setting
+							for i = 1, MAX_NUM_SOCKETS do
+								ItemTexture = _G['InspectArmoryScanTTTexture'..i]:GetTexture()
+
+								if Slot['Socket'..i].GemType and Info.Armory_Constants.GemColor[Slot['Socket'..i].GemType] then
+									R, G, B = unpack(Info.Armory_Constants.GemColor[Slot['Socket'..i].GemType])
+									Slot['Socket'..i].Socket:SetBackdropColor(R, G, B, 0.5)
+									Slot['Socket'..i].Socket:SetBackdropBorderColor(R, G, B)
+								else
+									Slot['Socket'..i].Socket:SetBackdropColor(1, 1, 1, 0.5)
+									Slot['Socket'..i].Socket:SetBackdropBorderColor(1, 1, 1)
+								end
+
+								CurrentLineText = select(2, _G['InspectArmoryScanTTTexture'..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)
+
+									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 Info.Armory_Constants.EmptySocketString[CurrentLineText] then
+										GemCount = GemCount + 1
+										Slot['Socket'..i].GemItemID = CurrentLineText
+										Slot['Socket'..i].Texture:SetTexture(ItemTexture)
+									end
+								end
+							end
+
+							if GemCount_Now < GemCount_Default then -- ItemInfo not loaded
+								NeedUpdate = true
+							end
+						end
+
+						_, _, ItemRarity, BasicItemLevel, _, _, _, _, _, ItemTexture = GetItemInfo(Slot.Link)
+						R, G, B = GetItemQualityColor(ItemRarity)
+
+						ItemUpgradeID = Slot.Link:match(':(%d+)\124h%[')
+
+						--<< Enchant Parts >>--
+						for i = 1, self.ScanTT:NumLines() do
+							CurrentLineText = _G['InspectArmoryScanTTTextLeft'..i]:GetText()
+
+							if CurrentLineText:find(Info.Armory_Constants.ItemLevelKey_Alt) then
+								TrueItemLevel = tonumber(CurrentLineText:match(Info.Armory_Constants.ItemLevelKey_Alt))
+							elseif CurrentLineText:find(Info.Armory_Constants.ItemLevelKey) then
+								TrueItemLevel = tonumber(CurrentLineText:match(Info.Armory_Constants.ItemLevelKey))
+							elseif CurrentLineText:find(Info.Armory_Constants.EnchantKey) then
+								CurrentLineText = CurrentLineText:match(Info.Armory_Constants.EnchantKey) -- Get enchant string
+
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_AGILITY_SHORT, AGI)
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_SPIRIT_SHORT, SPI)
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_STAMINA_SHORT, STA)
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_STRENGTH_SHORT, STR)
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_INTELLECT_SHORT, INT)
+								CurrentLineText = gsub(CurrentLineText, ITEM_MOD_CRIT_RATING_SHORT, CRIT_ABBR) -- Critical is too long
+								CurrentLineText = gsub(CurrentLineText, ' + ', '+') -- Remove space
+
+								Slot.Gradation.ItemEnchant:SetText('|cffceff00'..CurrentLineText)
+
+								IsEnchanted = true
+							end
+						end
+
+						--<< ItemLevel Parts >>--
+						if BasicItemLevel then
+							if ItemUpgradeID then
+								if ItemUpgradeID == '0' then
+									ItemUpgradeID = nil
+								else
+									ItemUpgradeID = TrueItemLevel - BasicItemLevel
+								end
+							end
+
+							Slot.ILvL = TrueItemLevel or BasicItemLevel
+
+							Slot.ItemLevel:SetText((ItemUpgradeID and (Info.Armory_Constants.UpgradeColor[ItemUpgradeID] or '|cffffffff') or '')..TrueItemLevel)
+							Slot.Gradation.ItemLevel:SetText((not TrueItemLevel or BasicItemLevel == TrueItemLevel) and BasicItemLevel or (Slot.Direction == 'LEFT' and TrueItemLevel or '')..(ItemUpgradeID and (Slot.Direction == 'LEFT' and ' ' or '')..(Info.Armory_Constants.UpgradeColor[ItemUpgradeID] or '|cffaaaaaa')..'(+'..ItemUpgradeID..')|r'..(Slot.Direction == 'RIGHT' and ' ' or '') or '')..(Slot.Direction == 'RIGHT' and TrueItemLevel or ''))
+						end
+
+						--print(SlotName..':', Slot.Link, BasicItemLevel, TrueItemLevel)
+
+						--[[
+						-- Check Error
+						if (not IsEnchanted and Info.Armory_Constants.EnchantableSlots[SlotName]) or ((SlotName == 'Finger0Slot' or SlotName == 'Finger1Slot') and (DataTable.Profession[1].Name == GetSpellInfo(110400) and DataTable.Profession[1].Level >= 550 or DataTable.Profession[2].Name == GetSpellInfo(110400) and DataTable.Profession[2].Level >= 550) and not IsEnchanted) then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.Gradation.ItemEnchant:SetText('|cffff0000'..L['Not Enchanted'])
+						elseif SlotName == 'ShoulderSlot' and KF.Table.ItemEnchant_Profession_Inscription and (DataTable.Profession[1].Name == GetSpellInfo(110417) and DataTable.Profession[1].Level >= KF.Table.ItemEnchant_Profession_Inscription.NeedLevel or DataTable.Profession[2].Name == GetSpellInfo(110417) and DataTable.Profession[2].Level >= KF.Table.ItemEnchant_Profession_Inscription.NeedLevel) and not KF.Table.ItemEnchant_Profession_Inscription[enchantID] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110400)..'|r : '..L['This is not profession only.']
+						elseif SlotName == 'WristSlot' and KF.Table.ItemEnchant_Profession_LeatherWorking and (DataTable.Profession[1].Name == GetSpellInfo(110423) and DataTable.Profession[1].Level >= KF.Table.ItemEnchant_Profession_LeatherWorking.NeedLevel or DataTable.Profession[2].Name == GetSpellInfo(110423) and DataTable.Profession[2].Level >= KF.Table.ItemEnchant_Profession_LeatherWorking.NeedLevel) and not KF.Table.ItemEnchant_Profession_LeatherWorking[enchantID] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110423)..'|r : '..L['This is not profession only.']
+						elseif SlotName == 'BackSlot' and KF.Table.ItemEnchant_Profession_Tailoring and (DataTable.Profession[1].Name == GetSpellInfo(110426) and DataTable.Profession[1].Level >= KF.Table.ItemEnchant_Profession_Tailoring.NeedLevel or DataTable.Profession[2].Name == GetSpellInfo(110426) and DataTable.Profession[2].Level >= KF.Table.ItemEnchant_Profession_Tailoring.NeedLevel) and not KF.Table.ItemEnchant_Profession_Tailoring[enchantID] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.EnchantWarning.Message = '|cff71d5ff'..GetSpellInfo(110426)..'|r : '..L['This is not profession only.']
+						end
+						]]
+						if not IsEnchanted and Info.Armory_Constants.EnchantableSlots[SlotName] then
+							ErrorDetected = true
+							Slot.EnchantWarning:Show()
+							Slot.Gradation.ItemEnchant:SetText('|cffff0000'..L['Not Enchanted'])
+						end
+
+						if GemCount_Enable > GemCount_Now or GemCount_Enable > GemCount or GemCount_Now > GemCount then
+							ErrorDetected = true
+
+							Slot.SocketWarning:Show()
+							Slot.SocketWarning.Message = '|cffff5678'..(GemCount_Now - GemCount)..'|r '..L['Empty Socket']
+							--[[
+							if GemCount_Enable > GemCount_Now then
+								if SlotName == 'WaistSlot' then
+									if TrueItemLevel < 300 then
+										_, Slot.SocketWarning.Link = GetItemInfo(41611)
+									elseif TrueItemLevel < 417 then
+										_, Slot.SocketWarning.Link = GetItemInfo(55054)
+									else
+										_, Slot.SocketWarning.Link = GetItemInfo(90046)
+									end
+
+									Slot.SocketWarning.Message = L['Missing Buckle']
+
+									Slot.SocketWarning:SetScript('OnClick', function(self)
+										local itemName, itemLink
+
+										if TrueItemLevel < 300 then
+											itemName, itemLink = GetItemInfo(41611)
+										elseif TrueItemLevel < 417 then
+											itemName, itemLink = GetItemInfo(55054)
+										else
+											itemName, itemLink = GetItemInfo(90046)
+										end
+
+										if HandleModifiedItemClick(itemLink) then
+										elseif IsShiftKeyDown() and BrowseName and BrowseName:IsVisible() then
+											AuctionFrameBrowse_Reset(BrowseResetButton)
+											BrowseName:SetText(itemName)
+											BrowseName:SetFocus()
+										end
+									end)
+								elseif SlotName == 'HandsSlot' then
+									Slot.SocketWarning.Link = GetSpellLink(114112)
+									Slot.SocketWarning.Message = '|cff71d5ff'..GetSpellInfo(110396)..'|r : '..L['Missing Socket']
+								elseif SlotName == 'WristSlot' then
+									Slot.SocketWarning.Link = GetSpellLink(113263)
+									Slot.SocketWarning.Message = '|cff71d5ff'..GetSpellInfo(110396)..'|r : '..L['Missing Socket']
+								end
+							else
+								Slot.SocketWarning.Message = '|cffff5678'..(GemCount_Now - GemCount)..'|r '..L['Empty Socket']
+							end
+							]]
+						end
+
+						--print(SlotName, Slot.Link, TrueItemLevel, ItemTotal)
+					else
+						NeedUpdate = true
+					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 and KF.db.Modules.Armory.Inspect.NoticeMissing ~= false then
+					Slot.Gradation.Texture:SetVertexColor(1, 0, 0)
+				else
+					Slot.Gradation.Texture:SetVertexColor(unpack(KF.db.Modules.Armory.Inspect.GradationColor))
+				end
+
+				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
+
+		for _, SlotName in pairs({ 'ShirtSlot', 'TabardSlot' }) do
+			Slot = self[SlotName]
+			ItemRarity, ItemTexture, R, G, B = nil, nil, 0, 0, 0
+
+			Slot.Link = DataTable.Gear[SlotName].ItemLink
+
+			if Slot.Link then
+				_, _, ItemRarity, _, _, _, _, _, _, ItemTexture = GetItemInfo(Slot.Link)
+				R, G, B = GetItemQualityColor(ItemRarity)
+			end
+
+			Slot.Texture:SetTexture(ItemTexture or self[SlotName].EmptyTexture)
+			Slot:SetBackdropBorderColor(R, G, B)
+		end
+
+		self.SetItem = E:CopyTable({}, self.CurrentInspectData.SetItem)
+	end
+
+	if NeedUpdateList then
+		self.GearUpdated = NeedUpdateList
+
+		return true
+	end
+	self.GearUpdated = nil
+
+	do	--<< Average ItemLevel >>--
+		for _, SlotName in pairs(self.GearUpdated or Info.Armory_Constants.GearList) do
+			if SlotName ~= 'ShirtSlot' and SlotName ~= 'TabardSlot' then
+				Slot = self[SlotName]
+
+				if Slot.ILvL then
+					ItemCount = ItemCount + 1
+					ItemTotal = ItemTotal + Slot.ILvL
+				end
+			end
+		end
+		self.Character.AverageItemLevel:SetText('|c'..RAID_CLASS_COLORS[DataTable.Class].colorStr..STAT_AVERAGE_ITEM_LEVEL..'|r : '..format('%.2f', ItemTotal / ItemCount))
+	end
+
+	R, G, B = RAID_CLASS_COLORS[DataTable.Class].r, RAID_CLASS_COLORS[DataTable.Class].g, RAID_CLASS_COLORS[DataTable.Class].b
+
+	do	--<< Basic Information >>--
+		local Realm = DataTable.Realm and DataTable.Realm ~= Info.MyRealm and DataTable.Realm or ''
+		local Title = DataTable.Title and string.gsub(DataTable.Title, DataTable.Name, '') or ''
+
+		self.Title:SetText(Realm..(Realm ~= '' and Title ~= '' and ' / ' or '')..(Title ~= '' and '|cff93daff'..Title or ''))
+		self.Guild:SetText(DataTable.guildName and '<|cff2eb7e4'..DataTable.guildName..'|r>  [|cff2eb7e4'..DataTable.guildRankName..'|r]' or '')
+	end
+
+	do	--<< Information Page Setting >>--
+		do	-- Profession
+			for i = 1, 2 do
+				if DataTable.Profession[i].Name then
+					self.Info.Profession:Show()
+					self.Info.Profession['Prof'..i].Bar:SetValue(DataTable.Profession[i].Level)
+
+					if Info.Armory_Constants.ProfessionList[DataTable.Profession[i].Name] then
+						self.Info.Profession['Prof'..i].Name:SetText('|cff77c0ff'..DataTable.Profession[i].Name)
+						self.Info.Profession['Prof'..i].Icon:SetTexture(Info.Armory_Constants.ProfessionList[DataTable.Profession[i].Name].Texture)
+						self.Info.Profession['Prof'..i].Level:SetText(DataTable.Profession[i].Level)
+					else
+						self.Info.Profession['Prof'..i].Name:SetText('|cff808080'..DataTable.Profession[i].Name)
+						self.Info.Profession['Prof'..i].Icon:SetTexture('Interface\\ICONS\\INV_Misc_QuestionMark')
+						self.Info.Profession['Prof'..i].Level:SetText(nil)
+					end
+				else
+					self.Info.Profession:Hide()
+					break
+				end
+			end
+		end
+
+		do	-- Guild
+			if DataTable.guildName and DataTable.guildPoint and DataTable.guildNumMembers then
+				self.Info.Guild:Show()
+				self.Info.Guild.Banner.Name:SetText('|cff2eb7e4'..DataTable.guildName)
+				self.Info.Guild.Banner.LevelMembers:SetText('|cff77c0ff'..DataTable.guildPoint..'|r Points'..(DataTable.guildNumMembers > 0 and ' / '..format(INSPECT_GUILD_NUM_MEMBERS:gsub('%%d', '%%s'), '|cff77c0ff'..DataTable.guildNumMembers..'|r ') or ''))
+				SetSmallGuildTabardTextures('player', self.Info.Guild.Emblem, self.Info.Guild.BG, self.Info.Guild.Border, DataTable.guildEmblem)
+			else
+				self.Info.Guild:Hide()
+			end
+		end
+
+		self:ReArrangeCategory()
+	end
+
+	do	--<< Specialization Page Setting >>--
+		local SpecGroup, TalentID, Name, Color, Texture, SpecRole
+
+		if DataTable.Specialization.ActiveSpec then
+			SpecGroup = DataTable.Specialization.ActiveSpec
+
+			for i = 2, MAX_TALENT_GROUPS do
+				self.Spec['Spec'..i]:Show()
+			end
+		else
+			SpecGroup = 1
+
+			for i = 2, MAX_TALENT_GROUPS do
+				self.Spec['Spec'..i]:Hide()
+			end
+		end
+
+		self.SpecIcon:SetTexture('Interface\\ICONS\\INV_Misc_QuestionMark')
+		for groupNum = 1, MAX_TALENT_GROUPS do
+			Color = '|cff808080'
+
+			Name = nil
+
+			if DataTable.Specialization[groupNum].SpecializationID and DataTable.Specialization[groupNum].SpecializationID ~= 0 then
+				_, Name, _, Texture = GetSpecializationInfoByID(DataTable.Specialization[groupNum].SpecializationID)
+
+				if Name then
+					if Info.ClassRole[DataTable.Class][Name] then
+
+						SpecRole = Info.ClassRole[DataTable.Class][Name].Role
+
+						if groupNum == SpecGroup then
+							Color = Info.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
+					else
+						self.Spec.Message = L['Specialization data seems to be crashed. Please inspect again.']
+					end
+				end
+			end
+
+			if not Name then
+				Texture, SpecRole = 'Interface\\ICONS\\INV_Misc_QuestionMark.blp', nil
+				Name = '|cff808080'..L['No Specialization']
+			end
+
+			self.Spec['Spec'..groupNum].Tab.text:SetText(Color..Name)
+			self.Spec['Spec'..groupNum].Texture:SetTexture(Texture)
+			self.Spec['Spec'..groupNum].Texture:SetDesaturated(groupNum ~= SpecGroup)
+		end
+	end
+
+	do	--<< Model and Frame Setting When InspectUnit Changed >>--
+		if DataTable.UnitID and UnitIsVisible(DataTable.UnitID) and self.NeedModelSetting then
+			self.Model:SetUnit(DataTable.UnitID)
+
+			self.Character.Message = nil
+		elseif self.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:Undress()
+
+			for _, SlotName in pairs(Info.Armory_Constants.GearList) do
+				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.']
+		end
+		self.NeedModelSetting = nil
+
+		if not (self.LastDataSetting and self.LastDataSetting == DataTable.Name..(DataTable.Realm and '-'..DataTable.Realm or '')) then
+			--<< Initialize Inspect Page >>--
+			self.Name:SetText('|c'..RAID_CLASS_COLORS[DataTable.Class].colorStr..DataTable.Name)
+			self.LevelRace:SetText(format('|cff%02x%02x%02x%s|r '..LEVEL..'|n%s', GetQuestDifficultyColor(DataTable.Level).r * 255, GetQuestDifficultyColor(DataTable.Level).g * 255, GetQuestDifficultyColor(DataTable.Level).b * 255, DataTable.Level, DataTable.Race))
+			self.ClassIcon:SetTexture('Interface\\ICONS\\ClassIcon_'..DataTable.Class)
+
+			self.Model:SetPosition(self.ModelList[DataTable.RaceID][DataTable.GenderID] and self.ModelList[DataTable.RaceID][DataTable.GenderID].z or 0, self.ModelList[DataTable.RaceID][DataTable.GenderID] and self.ModelList[DataTable.RaceID][DataTable.GenderID].x or 0, self.ModelList[DataTable.RaceID][DataTable.GenderID] and self.ModelList[DataTable.RaceID][DataTable.GenderID].y or 0)
+			self.Model:SetFacing(-5.67)
+			self.Model:SetPortraitZoom(1)
+			self.Model:SetPortraitZoom(0)
+
+			self:ChangePage('CharacterButton')
+
+			do --<< Color Setting >>--
+				self.ClassIconSlot:SetBackdropBorderColor(R, G, B)
+				self.SpecIconSlot:SetBackdropBorderColor(R, G, B)
+
+				self.Info.BG:SetBackdropBorderColor(R, G, B)
+
+				self.Info.Profession.IconSlot:SetBackdropBorderColor(R, G, B)
+				self.Info.Profession.Tab:SetBackdropColor(R, G, B, .3)
+				self.Info.Profession.Tab:SetBackdropBorderColor(R, G, B)
+				self.Info.Profession.Prof1.Bar:SetStatusBarColor(R, G, B)
+				self.Info.Profession.Prof2.Bar:SetStatusBarColor(R, G, B)
+
+				self.Info.Guild.IconSlot:SetBackdropBorderColor(R, G, B)
+				self.Info.Guild.Tab:SetBackdropColor(R, G, B, .3)
+				self.Info.Guild.Tab:SetBackdropBorderColor(R, G, B)
+
+				self.Info.PvP.IconSlot:SetBackdropBorderColor(R, G, B)
+				self.Info.PvP.Tab:SetBackdropColor(R, G, B, .3)
+				self.Info.PvP.Tab:SetBackdropBorderColor(R, G, B)
+			end
+
+			self:ToggleSpecializationTab(DataTable.Specialization.ActiveSpec or 1, DataTable)
+		elseif not (self.LastActiveSpec and self.LastActiveSpec == (DataTable.Specialization.ActiveSpec or 1)) then
+			self:ToggleSpecializationTab(DataTable.Specialization.ActiveSpec or 1, DataTable)
+		end
+	end
+
+	self.LastDataSetting = DataTable.Name..(DataTable.Realm and '-'..DataTable.Realm or '')
+end
+
+
+function IA:InspectFrame_PvPSetting(DataTable)
+	local Rating, Played, Won
+	local NeedExpand = 0
+
+	for _, Type in pairs({ '2vs2', '3vs3', '5vs5', 'RB' }) do
+		if DataTable.PvP[Type] and DataTable.PvP[Type][2] > 0 then
+			Rating = DataTable.PvP[Type][1] or 0
+			Played = DataTable.PvP[Type][2] or 0
+			Won = DataTable.PvP[Type][3] or 0
+
+			if Rating >= 2000 then
+				Rating = '|cffffe65a'..Rating
+				self.Info.PvP[Type].Rank:Show()
+				self.Info.PvP[Type].Rank:SetTexCoord(0, .5, 0, .5)
+				self.Info.PvP[Type].Rank:SetBlendMode('ADD')
+				self.Info.PvP[Type].Rank:SetVertexColor(1, 1, 1)
+				self.Info.PvP[Type].RankGlow:Show()
+				self.Info.PvP[Type].RankGlow:SetTexCoord(0, .5, 0, .5)
+				self.Info.PvP[Type].RankNoLeaf:Hide()
+			elseif Rating >= 1750 then
+				self.Info.PvP[Type].Rank:Show()
+				self.Info.PvP[Type].Rank:SetTexCoord(.5, 1, 0, .5)
+				self.Info.PvP[Type].Rank:SetBlendMode('ADD')
+				self.Info.PvP[Type].Rank:SetVertexColor(1, 1, 1)
+				self.Info.PvP[Type].RankGlow:Show()
+				self.Info.PvP[Type].RankGlow:SetTexCoord(.5, 1, 0, .5)
+				self.Info.PvP[Type].RankNoLeaf:Hide()
+			elseif Rating >= 1550 then
+				Rating = '|cffc17611'..Rating
+				self.Info.PvP[Type].Rank:Show()
+				self.Info.PvP[Type].Rank:SetTexCoord(0, .5, 0, .5)
+				self.Info.PvP[Type].Rank:SetBlendMode('BLEND')
+				self.Info.PvP[Type].Rank:SetVertexColor(.6, .5, 0)
+				self.Info.PvP[Type].RankGlow:Hide()
+				self.Info.PvP[Type].RankNoLeaf:Hide()
+			else
+				Rating = '|cff2eb7e4'..Rating
+				self.Info.PvP[Type].Rank:Hide()
+				self.Info.PvP[Type].RankGlow:Hide()
+				self.Info.PvP[Type].RankNoLeaf:Show()
+			end
+			NeedExpand = NeedExpand < 106 and 106 or NeedExpand
+
+			self.Info.PvP[Type].Rating:SetText(Rating)
+			self.Info.PvP[Type].Record:SetText('|cff77c0ff'..Won..'|r / |cffB24C4C'..(Played - Won))
+		else
+			NeedExpand = NeedExpand < 88 and 88 or NeedExpand
+
+			self.Info.PvP[Type].Rank:Hide()
+			self.Info.PvP[Type].RankGlow:Hide()
+			self.Info.PvP[Type].RankNoLeaf:Hide()
+
+			self.Info.PvP[Type].Rating:SetText('|cff8080800')
+			self.Info.PvP[Type].Record:SetText(nil)
+		end
+	end
+
+	self.Info.PvP.CategoryHeight = NeedExpand > 0 and NeedExpand or INFO_TAB_SIZE + SPACING * 2
+	self:ReArrangeCategory()
+end
+
+
+function IA:ReArrangeCategory()
+	local InfoPage_Height = 0
+	local PrevCategory
+
+	for _, CategoryType in pairs(self.InfoPageCategoryList) do
+		if self.Info[CategoryType]:IsShown() then
+			if self.Info[CategoryType].Closed then
+				self.Info[CategoryType].Page:Hide()
+				InfoPage_Height = InfoPage_Height + INFO_TAB_SIZE + SPACING * 2
+				self.Info[CategoryType]:Height(INFO_TAB_SIZE + SPACING * 2)
+			else
+				self.Info[CategoryType].Page:Show()
+				InfoPage_Height = InfoPage_Height + self.Info[CategoryType].CategoryHeight
+				self.Info[CategoryType]:Height(self.Info[CategoryType].CategoryHeight)
+			end
+
+			if PrevCategory then
+				InfoPage_Height = InfoPage_Height + SPACING * 2
+				self.Info[CategoryType]:Point('TOP', PrevCategory, 'BOTTOM', 0, -SPACING * 2)
+			else
+				self.Info[CategoryType]:Point('TOP', self.Info.Page)
+			end
+
+			PrevCategory = self.Info[CategoryType]
+		end
+	end
+
+	self.Info.Page:Height(InfoPage_Height)
+	self.ScrollFrame_OnMouseWheel(self.Info, 0)
+end
+
+
+function IA:ToggleSpecializationTab(Group, DataTable)
+	if not DataTable.Specialization[Group].SpecializationID then return end
+
+	local R, G, B
+	self.LastActiveSpec = DataTable.Specialization.ActiveSpec or 1
+
+	for i = 1, MAX_TALENT_GROUPS do
+		if i == Group then
+			self.Spec['Spec'..i].BottomLeftBorder:Show()
+			self.Spec['Spec'..i].BottomRightBorder:Show()
+			self.Spec['Spec'..i].Tab:SetFrameLevel(CORE_FRAME_LEVEL + 3)
+			self.Spec['Spec'..i].Tab.text:Point('BOTTOMRIGHT', 0, -10)
+		else
+			self.Spec['Spec'..i].BottomLeftBorder:Hide()
+			self.Spec['Spec'..i].BottomRightBorder:Hide()
+			self.Spec['Spec'..i].Tab:SetFrameLevel(CORE_FRAME_LEVEL + 2)
+			self.Spec['Spec'..i].Tab.text:Point('BOTTOMRIGHT', 0, 0)
+		end
+	end
+
+	if Group == self.LastActiveSpec then
+		R, G, B = RAID_CLASS_COLORS[DataTable.Class].r, RAID_CLASS_COLORS[DataTable.Class].g, RAID_CLASS_COLORS[DataTable.Class].b
+	else
+		R, G, B = .4, .4, .4
+	end
+
+	self.Spec.BottomBorder:SetTexture(R, G, B)
+	self.Spec.LeftBorder:SetTexture(R, G, B)
+	self.Spec.RightBorder:SetTexture(R, G, B)
+
+	local LevelTable = CLASS_TALENT_LEVELS[DataTable.Class] or CLASS_TALENT_LEVELS.DEFAULT
+
+	for i = 1, MAX_TALENT_TIERS do
+		for k = 1, NUM_TALENT_COLUMNS do
+			TalentID, Name, Texture = GetTalentInfoByID(DataTable.Specialization[Group]['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)][1], 1)
+
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture:SetTexture(Texture)
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:SetText(Name)
+			self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Tooltip.Link = GetTalentLink(TalentID)
+
+			if DataTable.Specialization[Group]['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)][2] == true then
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetBackdropColor(R, G, B, .3)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetBackdropBorderColor(R, G, B)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:SetBackdropBorderColor(R, G, B)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture:SetDesaturated(false)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:SetTextColor(1, 1, 1)
+			else
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetBackdropColor(.1, .1, .1)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)]:SetBackdropBorderColor(0, 0, 0)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon:SetBackdropBorderColor(0, 0, 0)
+				self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].Icon.Texture:SetDesaturated(true)
+
+				if DataTable.Level < LevelTable[i] then
+					self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:SetTextColor(.7, .3, .3)
+				else
+					self.Spec['Talent'..((i - 1) * NUM_TALENT_COLUMNS + k)].text:SetTextColor(.5, .5, .5)
+				end
+			end
+		end
+	end
+
+	local Name, Texture
+	for i = 1, NUM_GLYPH_SLOTS do
+		Name, _, Texture = GetSpellInfo(DataTable.Glyph[Group]['Glyph'..i..'SpellID'])
+
+		self.Spec['Glyph'..i].text:SetJustifyH('LEFT')
+		self.Spec['Glyph'..i].text:SetText(Name)
+		self.Spec['Glyph'..i].Icon.Texture:SetTexture(Texture)
+		self.Spec['Glyph'..i].Tooltip.Link = DataTable.Glyph[Group]['Glyph'..i..'ID'] ~= 0 and GetGlyphLinkByID(DataTable.Glyph[Group]['Glyph'..i..'ID'])
+
+		if DataTable.Glyph[Group]['Glyph'..i..'SpellID'] ~= 0 then
+			self.Spec['Glyph'..i]:SetBackdropColor(R, G, B, .3)
+			self.Spec['Glyph'..i]:SetBackdropBorderColor(R, G, B)
+			self.Spec['Glyph'..i].Icon:SetBackdropBorderColor(R, G, B)
+		else
+			self.Spec['Glyph'..i]:SetBackdropColor(.1, .1, .1)
+			self.Spec['Glyph'..i]:SetBackdropBorderColor(0, 0, 0)
+			self.Spec['Glyph'..i].Icon:SetBackdropBorderColor(0, 0, 0)
+
+			if self.Spec['Glyph'..i].NeedLevel > DataTable.Level then
+				self.Spec['Glyph'..i].text:SetJustifyH('CENTER')
+				self.Spec['Glyph'..i].text:SetText(E:RGBToHex(.7, .3, .3)..self.Spec['Glyph'..i].NeedLevel..' '..LEVEL)
+			end
+		end
+	end
+
+	for i = 1, MAX_TALENT_GROUPS do
+		if i == self.LastActiveSpec then
+			R, G, B = RAID_CLASS_COLORS[DataTable.Class].r, RAID_CLASS_COLORS[DataTable.Class].g, RAID_CLASS_COLORS[DataTable.Class].b
+		else
+			R, G, B = .3, .3, .3
+		end
+
+		self.Spec['Spec'..i].TopBorder:SetTexture(R, G, B)
+		self.Spec['Spec'..i].LeftBorder:SetTexture(R, G, B)
+		self.Spec['Spec'..i].RightBorder:SetTexture(R, G, B)
+		self.Spec['Spec'..i].BottomLeftBorder:SetTexture(R, G, B)
+		self.Spec['Spec'..i].BottomRightBorder:SetTexture(R, G, B)
+		self.Spec['Spec'..i].Icon:SetBackdropBorderColor(R, G, B)
+	end
+end
+
+
+KF.Modules[#KF.Modules + 1] = 'InspectArmory'
+KF.Modules.InspectArmory = function(RemoveOrder)
+	if not RemoveOrder and KF.db.Enable ~= false and KF.db.Modules.Armory and KF.db.Modules.Armory.Inspect and KF.db.Modules.Armory.Inspect.Enable ~= false and not Info.InspectArmory_Activate then
+		Default_NotifyInspect = NotifyInspect
+		Default_InspectUnit = InspectUnit
+
+		if IA.CreateInspectFrame then
+			IA:CreateInspectFrame()
+		end
+
+		NotifyInspect = ENI.NotifyInspect or NotifyInspect
+		InspectUnit = IA.InspectUnit
+
+		Info.InspectArmory_Activate = true
+	elseif Info.InspectArmory_Activate then
+		NotifyInspect = Default_NotifyInspect
+		InspectUnit = Default_InspectUnit
+		Default_NotifyInspect = nil
+		Default_InspectUnit = nil
+
+		Info.InspectArmory_Activate = nil
+	end
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/InspectArmory/Load_InspectArmory.xml b/ElvUI_SLE/modules/Armory/InspectArmory/Load_InspectArmory.xml
new file mode 100644
index 0000000..6ed24d6
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/InspectArmory/Load_InspectArmory.xml
@@ -0,0 +1,19 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/">
+	<Script file="Profile.lua"/>
+	<Script file="Communication.lua"/>
+	<Script file="NotifyInspect.lua"/>
+	<Script file="InspectArmory.lua"/>
+
+	<Button name="InspectArmory_UnitPopup" hidden="true" toplevel="true">
+		<ButtonText>
+			<Anchors>
+				<Anchor point="LEFT">
+					<Offset x="0" y="0"/>
+				</Anchor>
+			</Anchors>
+		</ButtonText>
+		<NormalFont style="GameFontHighlightSmallLeft"/>
+		<HighlightFont style="GameFontHighlightSmallLeft"/>
+		<DisabledFont style="GameFontDisableSmallLeft"/>
+	</Button>
+</Ui>
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/InspectArmory/NotifyInspect.lua b/ElvUI_SLE/modules/Armory/InspectArmory/NotifyInspect.lua
new file mode 100644
index 0000000..321904a
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/InspectArmory/NotifyInspect.lua
@@ -0,0 +1,138 @@
+local Revision = 1.5
+local ENI = _G['EnhancedNotifyInspect'] or CreateFrame('Frame', 'EnhancedNotifyInspect', UIParent)
+
+if not ENI.Revision or ENI.Revision < Revision then
+	ENI.InspectList = {}
+	ENI.Revision = Revision
+	ENI.UpdateInterval = 1
+
+	if not ENI.Original_BlizzardNotifyInspect then
+		local BlizNotifyInspect = _G['NotifyInspect']
+		ENI.Original_BlizzardNotifyInspect = BlizNotifyInspect
+	end
+
+	ENI:SetScript('OnEvent', function(self, Event, ...)
+		if self[Event] then
+			self[Event](...)
+		end
+	end)
+	ENI:Hide()
+
+	local playerRealm = gsub(GetRealmName(),'[%s%-]','')
+
+	local UnitID, Count
+	ENI.TryInspect = function()
+		for i = 1, #ENI.InspectList do
+			if ENI.InspectList[(ENI.InspectList[i])] then
+				UnitID = ENI.InspectList[(ENI.InspectList[i])].UnitID
+				Count = ENI.InspectList[(ENI.InspectList[i])].InspectTryCount
+
+				if UnitID and UnitIsConnected(UnitID) and CanInspect(UnitID) and not (Count and Count <= 0) then
+					ENI.CurrentInspectUnitGUID = UnitGUID(UnitID)
+
+					if Count then
+						ENI.InspectList[(ENI.InspectList[i])].InspectTryCount = ENI.InspectList[(ENI.InspectList[i])].InspectTryCount - 1
+					end
+
+					ENI.Original_BlizzardNotifyInspect(UnitID)
+
+					if ENI.InspectList[(ENI.InspectList[i])].CancelInspectByManual then
+						RequestInspectHonorData()
+					end
+
+					return
+				elseif Count and Count <= 0 or not ENI.InspectList[(ENI.InspectList[i])].CancelInspectByManual then
+					ENI.CancelInspect(ENI.InspectList[i])
+					return
+				end
+			end
+		end
+
+		if ENI.NowInspecting and not ENI.NowInspecting._cancelled then
+			ENI.NowInspecting:Cancel()
+		end
+	end
+
+	--[[
+		Properties = {
+			Reservation = boolean,
+			InspectTryCount = number,
+			CancelInspectByManual = Canceller,
+		}
+	]]
+	ENI.NotifyInspect = function(Unit, Properties)
+		if Unit ~= 'target' and UnitIsUnit(Unit, 'target') then
+			Unit = 'target'
+		end
+
+		if Unit ~= 'focus' and UnitIsUnit(Unit, 'focus') then
+			Unit = 'focus'
+		end
+
+		if UnitInParty(Unit) or UnitInRaid(Unit) then
+			Unit = GetUnitName(Unit, true)
+		end
+
+		if UnitIsPlayer(Unit) and CanInspect(Unit) then
+			local TableIndex = GetUnitName(Unit, true)
+
+			if not ENI.InspectList[TableIndex] then
+				if not (Properties and Properties.Reservation) then
+					tinsert(ENI.InspectList, 1, TableIndex)
+				else
+					tinsert(ENI.InspectList, TableIndex)
+				end
+
+				ENI.InspectList[TableIndex] = { UnitID = Unit }
+
+				if Properties then
+					ENI.InspectList[TableIndex].InspectTryCount = Properties.InspectTryCount
+					ENI.InspectList[TableIndex].CancelInspectByManual = Properties.CancelInspectByManual
+				end
+
+				if not ENI.NowInspecting or ENI.NowInspecting._cancelled then
+					ENI.NowInspecting = C_Timer.NewTicker(ENI.UpdateInterval, ENI.TryInspect)
+				end
+
+				ENI:Show()
+			elseif not (Properties and Properties.Reservation) then
+				ENI.CancelInspect(TableIndex)
+				ENI.NotifyInspect(Unit, Properties)
+			end
+		end
+
+		return Unit
+	end
+
+	ENI.CancelInspect = function(Unit, Canceller)
+		if ENI.InspectList[Unit] then
+			for i = 1, #ENI.InspectList do
+				if ENI.InspectList[i] == Unit and not (Canceller and ENI.InspectList[Unit].CancelInspectByManual and ENI.InspectList[Unit].CancelInspectByManual ~= Canceller) then
+					tremove(ENI.InspectList, i)
+					ENI.InspectList[Unit] = nil
+
+					return
+				end
+			end
+		end
+	end
+
+	ENI.INSPECT_READY = function(InspectedUnitGUID)
+		local Name, Realm
+
+		_, _, _, _, _, Name, Realm = GetPlayerInfoByGUID(InspectedUnitGUID)
+
+		if Name then
+			Name = Name..(Realm and Realm ~= '' and Realm ~= playerRealm and '-'..Realm or '')
+
+			if ENI.InspectList[Name] then
+				if ENI.InspectList[Name].CancelInspectByManual then
+					return
+				end
+
+				ENI.CancelInspect(Name, 'INSPECT_READY')
+			end
+		end
+	end
+	ENI:RegisterEvent('INSPECT_READY')
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/InspectArmory/Profile.lua b/ElvUI_SLE/modules/Armory/InspectArmory/Profile.lua
new file mode 100644
index 0000000..c97bdcd
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/InspectArmory/Profile.lua
@@ -0,0 +1,12 @@
+local E, L, V, P, G = unpack(ElvUI)
+local KF, Info, Timer = unpack(ElvUI_KnightFrame)
+
+KF.db.Modules.Armory = KF.db.Modules.Armory or {}
+
+KF.db.Modules.Armory.Inspect = {
+	Enable = true,
+	NoticeMissing = true,
+
+	GradationColor = { .41, .83, 1 },
+	BackgroundImage = 'Interface\\AddOns\\ElvUI_KnightFrame\\Media\\Graphics\\Space'
+}
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/KnightFrame.lua b/ElvUI_SLE/modules/Armory/KnightFrame.lua
new file mode 100644
index 0000000..29f1e1d
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/KnightFrame.lua
@@ -0,0 +1,283 @@
+local E, L, V, P, G = unpack(ElvUI)
+
+if not select(2, GetAddOnInfo('ElvUI_KnightFrame')) and not E:GetModule('KnightFrame') then
+	--<< INITIALIZE >>--
+	local AddOnName, Engine = 'ElvUI_KnightFrame', {}
+
+	local Info = {
+		Name = 'KnightFrame',
+		MyRealm = gsub(E.myrealm,'[%s%-]',''),
+		ClassRole = {
+			WARRIOR = {
+				[(L['Spec_Warrior_Arms'])] = { --무기
+					Color = '|cff9a9a9a',
+					Role = 'Melee'
+				},
+				[(L['Spec_Warrior_Fury'])] = { --분노
+					Color = '|cffb50000',
+					Role = 'Melee'
+				},
+				[(L['Spec_Warrior_Protection'])] = { --방어
+					Color = '|cff088fdc',
+					Role = 'Tank'
+				}
+			},
+			HUNTER = {
+				[(L['Spec_Hunter_Beast'])] = { --야수
+					Color = '|cffffdb00',
+					Role = 'Melee'
+				},
+				[(L['Spec_Hunter_Marksmanship'])] = { --사격
+					Color = '|cffea5455',
+					Role = 'Melee'
+				},
+				[(L['Spec_Hunter_Survival'])] = { --생존
+					Color = '|cffbaf71d',
+					Role = 'Melee'
+				}
+			},
+			SHAMAN = {
+				[(L['Spec_Shaman_Elemental'])] = { --정기
+					Color = '|cff2be5fa',
+					Role = 'Caster'
+				},
+				[(L['Spec_Shaman_Enhancement'])] = { --고양
+					Color = '|cffe60000',
+					Role = 'Melee'
+				},
+				[(L['Spec_Shaman_Restoration'])] = { --복원
+					Color = '|cff00ff0c',
+					Role = 'Healer'
+				}
+			},
+			MONK = {
+				[(L['Spec_Monk_Brewmaster'])] = { --양조
+					Color = '|cffbcae6d',
+					Role = 'Tank'
+				},
+				[(L['Spec_Monk_Mistweaver'])] = { --운무
+					Color = '|cffb6f1b7',
+					Role = 'Healer'
+				},
+				[(L['Spec_Monk_Windwalker'])] = { --풍운
+					Color = '|cffb2c6de',
+					Role = 'Melee'
+				}
+			},
+			ROGUE = {
+				[(L['Spec_Rogue_Assassination'])] = { --암살
+					Color = '|cff129800',
+					Role = 'Melee'
+				},
+				[(L['Spec_Rogue_Combat'])] = { --전투
+					Color = '|cffbc0001',
+					Role = 'Melee'
+				},
+				[(L['Spec_Rogue_Subtlety'])] = { --잠행
+					Color = '|cfff48cba',
+					Role = 'Melee'
+				}
+			},
+			DEATHKNIGHT = {
+				[(L['Spec_DeathKnight_Blood'])] = { --혈기
+					Color = '|cffbc0001',
+					Role = 'Tank'
+				},
+				[(L['Spec_DeathKnight_Frost'])] = { --냉기
+					Color = '|cff1784d1',
+					Role = 'Melee'
+				},
+				[(L['Spec_DeathKnight_Unholy'])] = { --부정
+					Color = '|cff00ff10',
+					Role = 'Melee'
+				}
+			},
+			MAGE = {
+				[(L['Spec_Mage_Arcane'])] = { --비전
+					Color = '|cffdcb0fb',
+					Role = 'Caster'
+				},
+				[(L['Spec_Mage_Fire'])] = { --화염
+					Color = '|cffff3615',
+					Role = 'Caster'
+				},
+				[(L['Spec_Mage_Frost'])] = { --냉기
+					Color = '|cff1784d1',
+					Role = 'Caster'
+				}
+			},
+			DRUID = {
+				[(L['Spec_Druid_Balance'])] = { --조화
+					Color = '|cffff7d0a',
+					Role = 'Caster'
+				},
+				[(L['Spec_Druid_Feral'])] = { --야성
+					Color = '|cffffdb00',
+					Role = 'Melee'
+				},
+				[(L['Spec_Druid_Guardian'])] = { --수호
+					Color = '|cff088fdc',
+					Role = 'Tank'
+				},
+				[(L['Spec_Druid_Restoration'])] = { --회복
+					Color = '|cff64df62',
+					Role = 'Healer'
+				}
+			},
+			PALADIN = {
+				[(L['Spec_Paladin_Holy'])] = { --신성
+					Color = '|cfff48cba',
+					Role = 'Healer'
+				},
+				[(L['Spec_Paladin_Protection'])] = { --보호
+					Color = '|cff84e1ff',
+					Role = 'Tank'
+				},
+				[(L['Spec_Paladin_Retribution'])] = { --징벌
+					Color = '|cffe60000',
+					Role = 'Melee'
+				}
+			},
+			PRIEST = {
+				[(L['Spec_Priest_Discipline'])] = { --수양
+					Color = '|cffffffff',
+					Role = 'Healer'
+				},
+				[(L['Spec_Priest_Holy'])] = { --신성
+					Color = '|cff6bdaff',
+					Role = 'Healer'
+				},
+				[(L['Spec_Priest_Shadow'])] = { --암흑
+					Color = '|cff7e52c1',
+					Role = 'Caster'
+				}
+			},
+			WARLOCK = {
+				[(L['Spec_Warlock_Affliction'])] = { --고통
+					Color = '|cff00ff10',
+					Role = 'Caster'
+				},
+				[(L['Spec_Warlock_Demonology'])] = { --악마
+					Color = '|cff9482c9',
+					Role = 'Caster'
+				},
+				[(L['Spec_Warlock_Destruction'])] = { --파괴
+					Color = '|cffba1706',
+					Role = 'Caster'
+				}
+			}
+		}
+	}
+
+	local KF = E:NewModule(Information.Name, 'AceEvent-3.0', 'AceConsole-3.0', 'AceHook-3.0')
+	local Timer = {}
+
+	Engine[1] = Core
+	Engine[2] = Information
+	Engine[3] = Timer
+
+	_G[AddOnName] = Engine
+
+
+
+
+	--<< TOOLKIT >>--
+	function KF:Color_Value(InputText)
+		return E:RGBToHex(E.media.rgbvaluecolor[1], E.media.rgbvaluecolor[2], E.media.rgbvaluecolor[3])..(InputText and InputText..'|r' or '')
+	end
+
+	function KF:Color_Class(Class, InputText)
+		return (Class and '|c'..RAID_CLASS_COLORS[Class].colorStr or '')..(InputText and InputText..'|r' or '')
+	end
+
+	function KF:TextSetting(self, Text, Style, ...)
+		if Style and Style.Tag then
+			self[Style.Tag] = self[Style.Tag] or self:CreateFontString(nil, 'OVERLAY')
+			self = self[Style.Tag]
+		else
+			Style = Style or {}
+			self.text = self.text or self:CreateFontString(nil, 'OVERLAY')
+			self = self.text
+		end
+
+		self:FontTemplate(Style.Font and E.LSM:Fetch('font', Style.Font), Style.FontSize, Style.FontStyle)
+		self:SetJustifyH(Style.directionH or 'CENTER')
+		self:SetJustifyV(Style.directionV or 'MIDDLE')
+		self:SetText(Text)
+
+		if ... then
+			self:Point(...)
+		else
+			self:SetInside()
+		end
+	end
+
+
+
+
+	--<< GLOBALSTRINGS >>--
+	for ClassName, SpecializationIDTable in pairs({
+		Warrior = {
+			Arms = 71,
+			Fury = 72,
+			Protection = 73
+		},
+		Hunter = {
+			Beast = 253,
+			Marksmanship = 254,
+			Survival = 255
+		},
+		Shaman = {
+			Elemental = 262,
+			Enhancement = 263,
+			Restoration = 264
+		},
+		Monk = {
+			Brewmaster = 268,
+			Mistweaver = 270,
+			Windwalker = 269
+		},
+		Rogue = {
+			Assassination = 259,
+			Combat = 260,
+			Subtlety = 261
+		},
+		DeathKnight = {
+			Blood = 250,
+			Frost = 251,
+			Unholy = 252
+		},
+		Mage = {
+			Arcane = 62,
+			Fire = 63,
+			Frost = 64
+		},
+		Druid = {
+			Balance = 102,
+			Feral = 103,
+			Guardian = 104,
+			Restoration = 105
+		},
+		Paladin = {
+			Holy = 65,
+			Protection = 66,
+			Retribution = 70
+		},
+		Priest = {
+			Discipline = 256,
+			Holy = 257,
+			Shadow = 258
+		},
+		Warlock = {
+			Affliction = 265,
+			Demonology = 266,
+			Destruction = 267
+		}
+	}) do
+		L[ClassName] = KF:Color_Class(string.upper(ClassName), LOCALIZED_CLASS_NAMES_MALE[string.upper(ClassName)])
+
+		for Name, ID in pairs(SpecializationIDTable) do
+			_, L['Spec_'..ClassName..'_'..Name] = GetSpecializationInfoByID(ID)
+		end
+	end
+end
\ No newline at end of file
diff --git a/ElvUI_SLE/modules/Armory/Load_Armory.xml b/ElvUI_SLE/modules/Armory/Load_Armory.xml
new file mode 100644
index 0000000..068cdca
--- /dev/null
+++ b/ElvUI_SLE/modules/Armory/Load_Armory.xml
@@ -0,0 +1,8 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/">
+	<Script file="KnightFrame.lua"/>
+	<Script file="Constants.lua"/>
+	<Script file="EnchantList.lua"/>
+
+	<Include file="CharacterArmory\Load_CharacterArmory.xml"/>
+	<Include file="InspectArmory\Load_InspectArmory.xml"/>
+</Ui>
\ No newline at end of file