Untitled diff

Created Diff never expires
6 removals
716 lines
34 additions
744 lines
-- InspectEquip
-- InspectEquip


InspectEquip = LibStub("AceAddon-3.0"):NewAddon("InspectEquip", "AceConsole-3.0", "AceHook-3.0", "AceTimer-3.0", "AceEvent-3.0")
InspectEquip = LibStub("AceAddon-3.0"):NewAddon("InspectEquip", "AceConsole-3.0", "AceHook-3.0", "AceTimer-3.0", "AceEvent-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale("InspectEquip")
local L = LibStub("AceLocale-3.0"):GetLocale("InspectEquip")
local IE = InspectEquip
local IE = InspectEquip
local IS = InspectEquip_ItemSources --> ItemSources.lua
local IS = InspectEquip_ItemSources --> ItemSources.lua
local WIN = InspectEquip_InfoWindow --> InfoWindow.xml
local WIN = InspectEquip_InfoWindow --> InfoWindow.xml
local TITLE = InspectEquip_InfoWindowTitle
local TITLE = InspectEquip_InfoWindowTitle
local AVGIL = InspectEquip_InfoWindowAvgItemLevel
local AVGIL = InspectEquip_InfoWindowAvgItemLevel
local exMod = nil
local exMod = nil


local mop = select(4, GetBuildInfo()) >= 50000
local mop = select(4, GetBuildInfo()) >= 50000


local ItemUpgradeInfo = LibStub("LibItemUpgradeInfo-1.0")
local ItemUpgradeInfo = LibStub("LibItemUpgradeInfo-1.0")


local slots = { "HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot",
local slots = { "HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot",
"WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot",
"WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot",
"Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "MainHandSlot",
"Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "MainHandSlot",
"SecondaryHandSlot" } -- TabardSlot, ShirtSlot
"SecondaryHandSlot" } -- TabardSlot, ShirtSlot
local noEnchantWarningSlots = {
local noEnchantWarningSlots = {
["NeckSlot"] = true, ["WaistSlot"] = true, ["Finger0Slot"] = true, ["Finger1Slot"] = true,
["NeckSlot"] = true, ["WaistSlot"] = true, ["Finger0Slot"] = true, ["Finger1Slot"] = true,
["Trinket0Slot"] = true, ["Trinket1Slot"] = true, ["SecondaryHandSlot"] = true, ["RangedSlot"] = true,
["Trinket0Slot"] = true, ["Trinket1Slot"] = true, ["SecondaryHandSlot"] = true, ["RangedSlot"] = true,
}
}


local lines = {}
local lines = {}
local numlines = 0
local numlines = 0
local curline = 0
local curline = 0
local curUnit = nil
local curUnit = nil
local curUnitName = nil
local curUnitName = nil
local curUser = nil
local curUser = nil
local curGUID = nil
local curGUID = nil
local cached = false
local cached = false


local headers = {}
local headers = {}
local numheaders = 0
local numheaders = 0


local yoffset = -40
local yoffset = -40
local hooked = false
local hooked = false
local autoHidden = false
local autoHidden = false


local origInspectUnit
local origInspectUnit


local tonumber = tonumber
local tonumber = tonumber
local gmatch = string.gmatch
local gmatch = string.gmatch
local tinsert = table.insert
local tinsert = table.insert
local tsort = table.sort
local tsort = table.sort
local band = bit.band
local band = bit.band
local Examiner = Examiner
local Examiner = Examiner


--local _,_,_,gameToc = GetBuildInfo()
--local _,_,_,gameToc = GetBuildInfo()


local tooltipTimer = nil
local tooltipTimer = nil
local retryTimer = nil
local retryTimer = nil


if mop then
if mop then
noEnchantWarningSlots["HeadSlot"] = true
noEnchantWarningSlots["HeadSlot"] = true
else
else
tinsert(slots, "RangedSlot")
tinsert(slots, "RangedSlot")
end
end




--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------


InspectEquipConfig = {}
InspectEquipConfig = {}
local defaults = {
local defaults = {
tooltips = true,
tooltips = true,
showUnknown = true,
showUnknown = true,
inspectWindow = true,
inspectWindow = true,
charWindow = true,
charWindow = true,
checkEnchants = true,
checkEnchants = true,
listItemLevels = true,
listItemLevels = true,
showAvgItemLevel = true,
showAvgItemLevel = true,
ttR = 1.0,
ttR = 1.0,
ttG = 0.75,
ttG = 0.75,
ttB = 0.0,
ttB = 0.0,
maxSourceCount = 5,
maxSourceCount = 5,
}
}


local options = {
local options = {
name = "InspectEquip",
name = "InspectEquip",
type = "group",
type = "group",
args = {
args = {
tooltips = {
tooltips = {
order = 1, type = "toggle", width = "full",
order = 1, type = "toggle", width = "full",
name = L["Add drop information to tooltips"],
name = L["Add drop information to tooltips"],
desc = L["Add item drop information to all item tooltips"],
desc = L["Add item drop information to all item tooltips"],
get = function() return InspectEquipConfig.tooltips end,
get = function() return InspectEquipConfig.tooltips end,
set = function(_,v) InspectEquipConfig.tooltips = v; if v then IE:HookTooltips() end end,
set = function(_,v) InspectEquipConfig.tooltips = v; if v then IE:HookTooltips() end end,
},
},
showunknown = {
showunknown = {
order = 2, type = "toggle", width = "full",
order = 2, type = "toggle", width = "full",
name = L["Include unknown items in overview"],
name = L["Include unknown items in overview"],
desc = L["Show items that cannot be categorized in a seperate category"],
desc = L["Show items that cannot be categorized in a seperate category"],
get = function() return InspectEquipConfig.showUnknown end,
get = function() return InspectEquipConfig.showUnknown end,
set = function(_,v) InspectEquipConfig.showUnknown = v end,
set = function(_,v) InspectEquipConfig.showUnknown = v end,
},
},
inspectwindow = {
inspectwindow = {
order = 3, type = "toggle", width = "full",
order = 3, type = "toggle", width = "full",
name = L["Attach to inspect window"],
name = L["Attach to inspect window"],
desc = L["Show the equipment list when inspecting other characters"],
desc = L["Show the equipment list when inspecting other characters"],
get = function() return InspectEquipConfig.inspectWindow end,
get = function() return InspectEquipConfig.inspectWindow end,
set = function(_,v) InspectEquipConfig.inspectWindow = v end,
set = function(_,v) InspectEquipConfig.inspectWindow = v end,
},
},
charwindow = {
charwindow = {
order = 4, type = "toggle", width = "full",
order = 4, type = "toggle", width = "full",
name = L["Attach to character window"],
name = L["Attach to character window"],
desc = L["Also show the InspectEquip panel when opening the character window"],
desc = L["Also show the InspectEquip panel when opening the character window"],
get = function() return InspectEquipConfig.charWindow end,
get = function() return InspectEquipConfig.charWindow end,
set = function(_,v) InspectEquipConfig.charWindow = v end,
set = function(_,v) InspectEquipConfig.charWindow = v end,
},
},
checkenchants = {
checkenchants = {
order = 5, type = "toggle", width = "full",
order = 5, type = "toggle", width = "full",
name = L["Check for unenchanted items"],
name = L["Check for unenchanted items"],
desc = L["Display a warning for unenchanted items"],
desc = L["Display a warning for unenchanted items"],
get = function() return InspectEquipConfig.checkEnchants end,
get = function() return InspectEquipConfig.checkEnchants end,
set = function(_,v) InspectEquipConfig.checkEnchants = v end,
set = function(_,v) InspectEquipConfig.checkEnchants = v end,
},
},
listitemlevels = {
listitemlevels = {
order = 6, type = "toggle", width = "full",
order = 6, type = "toggle", width = "full",
name = L["Show item level in equipment list"],
name = L["Show item level in equipment list"],
desc = L["Show the item level of each item in the equipment panel"],
desc = L["Show the item level of each item in the equipment panel"],
get = function() return InspectEquipConfig.listItemLevels end,
get = function() return InspectEquipConfig.listItemLevels end,
set = function(_,v) InspectEquipConfig.listItemLevels = v end,
set = function(_,v) InspectEquipConfig.listItemLevels = v end,
},
},
showavgitemlevel = {
showavgitemlevel = {
order = 7, type = "toggle", width = "full",
order = 7, type = "toggle", width = "full",
name = L["Show average item level in equipment list"],
name = L["Show average item level in equipment list"],
desc = L["Show the average item level of all items in the equipment panel"],
desc = L["Show the average item level of all items in the equipment panel"],
get = function() return InspectEquipConfig.showAvgItemLevel end,
get = function() return InspectEquipConfig.showAvgItemLevel end,
set = function(_,v) InspectEquipConfig.showAvgItemLevel = v end,
set = function(_,v) InspectEquipConfig.showAvgItemLevel = v end,
},
},
tooltipcolor = {
tooltipcolor = {
order = 8, type = "color",
order = 8, type = "color",
name = L["Tooltip text color"],
name = L["Tooltip text color"],
width = "full",
width = "full",
get = function() return InspectEquipConfig.ttR, InspectEquipConfig.ttG, InspectEquipConfig.ttB, 1.0 end,
get = function() return InspectEquipConfig.ttR, InspectEquipConfig.ttG, InspectEquipConfig.ttB, 1.0 end,
set = function(_,r,g,b,a)
set = function(_,r,g,b,a)
InspectEquipConfig.ttR = r
InspectEquipConfig.ttR = r
InspectEquipConfig.ttG = g
InspectEquipConfig.ttG = g
InspectEquipConfig.ttB = b
InspectEquipConfig.ttB = b
end,
end,
},
},
maxsourcecount = {
maxsourcecount = {
order = 9, type = "range",
order = 9, type = "range",
min = 1, max = 20, softMax = 10, step = 1,
min = 1, max = 20, softMax = 10, step = 1,
width = "double",
width = "double",
name = L["Max. amount of sources in tooltips"],
name = L["Max. amount of sources in tooltips"],
desc = L["The maximum amount of sources that are displayed in item tooltips"],
desc = L["The maximum amount of sources that are displayed in item tooltips"],
get = function() return InspectEquipConfig.maxSourceCount end,
get = function() return InspectEquipConfig.maxSourceCount end,
set = function(_,v) InspectEquipConfig.maxSourceCount = v end,
set = function(_,v) InspectEquipConfig.maxSourceCount = v end,
},
},
database = {
database = {
order = 10, type = "group", inline = true,
order = 10, type = "group", inline = true,
name = L["Database"],
name = L["Database"],
args = {
args = {
resetdb = {
resetdb = {
order = 1, type = "execute",
order = 1, type = "execute",
width = "double",
width = "double",
name = L["Reset database"],
name = L["Reset database"],
desc = L["Recreate the database"],
desc = L["Recreate the database"],
func = function() IE:CreateLocalDatabase() end,
func = function() IE:CreateLocalDatabase() end,
},
},
},
},
}
}
},
},
}
}


LibStub("AceConfig-3.0"):RegisterOptionsTable("InspectEquip", options, "/inspectequip")
LibStub("AceConfig-3.0"):RegisterOptionsTable("InspectEquip", options, "/inspectequip")
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("InspectEquip")
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("InspectEquip")


--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------


function IE:OnInitialize()
function IE:OnInitialize()
setmetatable(InspectEquipConfig, {__index = defaults})
setmetatable(InspectEquipConfig, {__index = defaults})


self:SetParent(Examiner or InspectFrame)
self:SetParent(Examiner or InspectFrame)
WIN:Hide()
WIN:Hide()
TITLE:SetText("InspectEquip")
TITLE:SetText("InspectEquip")


if Examiner and Examiner.CreateModule then
if Examiner and Examiner.CreateModule then
exMod = Examiner:CreateModule("InspectEquip")
exMod = Examiner:CreateModule("InspectEquip")
exMod.OnCacheLoaded = function(s, entry, unit)
exMod.OnCacheLoaded = function(s, entry, unit)
if InspectEquipConfig.inspectWindow then
if InspectEquipConfig.inspectWindow then
IE:Inspect("cache", entry)
IE:Inspect("cache", entry)
end
end
end
end
exMod.OnClearInspect = function(s) WIN:Hide() end
exMod.OnClearInspect = function(s) WIN:Hide() end
exMod.OnInspect = function(s, unit)
exMod.OnInspect = function(s, unit)
if InspectEquipConfig.inspectWindow then
if InspectEquipConfig.inspectWindow then
IE:SetParent(Examiner); IE:Inspect(unit)
IE:SetParent(Examiner); IE:Inspect(unit)
end
end
end
end
end
end


self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("ADDON_LOADED")
self:RegisterEvent("ADDON_LOADED")


--self:InitLocalDatabase()
--self:InitLocalDatabase()
end
end


function IE:OnEnable()
function IE:OnEnable()
origInspectUnit = origInspectUnit or InspectUnit
origInspectUnit = origInspectUnit or InspectUnit
InspectUnit = function(...) IE:InspectUnit(...) end
InspectUnit = function(...) IE:InspectUnit(...) end
self:SecureHookScript(PaperDollFrame, "OnShow", "PaperDollFrame_OnShow")
self:SecureHookScript(PaperDollFrame, "OnShow", "PaperDollFrame_OnShow")
self:SecureHookScript(PaperDollFrame, "OnHide", "PaperDollFrame_OnHide")
self:SecureHookScript(PaperDollFrame, "OnHide", "PaperDollFrame_OnHide")
if GearManagerDialog then -- 4.0
if GearManagerDialog then -- 4.0
self:SecureHookScript(GearManagerDialog, "OnShow", "GearManagerDialog_OnShow")
self:SecureHookScript(GearManagerDialog, "OnShow", "GearManagerDialog_OnShow")
self:SecureHookScript(GearManagerDialog, "OnHide", "GearManagerDialog_OnHide")
self:SecureHookScript(GearManagerDialog, "OnHide", "GearManagerDialog_OnHide")
end
end
if OutfitterFrame then
if OutfitterFrame then
self:SecureHookScript(OutfitterFrame, "OnShow", "GearManagerDialog_OnShow")
self:SecureHookScript(OutfitterFrame, "OnShow", "GearManagerDialog_OnShow")
self:SecureHookScript(OutfitterFrame, "OnHide", "GearManagerDialog_OnHide")
self:SecureHookScript(OutfitterFrame, "OnHide", "GearManagerDialog_OnHide")
end
end
self:RegisterEvent("UNIT_INVENTORY_CHANGED")
self:RegisterEvent("UNIT_INVENTORY_CHANGED")
self:RegisterEvent("INSPECT_READY")
self:RegisterEvent("INSPECT_READY")
end
end


function IE:OnDisable()
function IE:OnDisable()
InspectUnit = origInspectUnit
InspectUnit = origInspectUnit
if hooked then
if hooked then
hooked = false
hooked = false
self:Unhook("InspectFrame_UnitChanged")
self:Unhook("InspectFrame_UnitChanged")
end
end
self:UnhookAll()
self:UnhookAll()
self:UnregisterEvent("UNIT_INVENTORY_CHANGED")
self:UnregisterEvent("UNIT_INVENTORY_CHANGED")
self:UnregisterEvent("INSPECT_READY")
self:UnregisterEvent("INSPECT_READY")
self:CancelAllTimers()
self:CancelAllTimers()
WIN:Hide()
WIN:Hide()
end
end


local entered = false
local entered = false


function IE:PLAYER_ENTERING_WORLD()
function IE:PLAYER_ENTERING_WORLD()
entered = true
entered = true
self:ScheduleTooltipHook()
self:ScheduleTooltipHook()
self:InitLocalDatabase()
self:InitLocalDatabase()
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
end
end


function IE:ADDON_LOADED(e, name)
function IE:ADDON_LOADED(e, name)
if entered then
if entered then
self:ScheduleTooltipHook()
self:ScheduleTooltipHook()
end
end
end
end


-- Ugly hack, but some addons override the OnTooltipSetItem handler on
-- Ugly hack, but some addons override the OnTooltipSetItem handler on
-- ItemRefTooltip, breaking IE. Using this timer, IE hopefully hooks after them.
-- ItemRefTooltip, breaking IE. Using this timer, IE hopefully hooks after them.
function IE:ScheduleTooltipHook()
function IE:ScheduleTooltipHook()
if InspectEquipConfig.tooltips then
if InspectEquipConfig.tooltips then
if tooltipTimer then
if tooltipTimer then
self:CancelTimer(tooltipTimer, true)
self:CancelTimer(tooltipTimer, true)
end
end
tooltipTimer = self:ScheduleTimer('HookTooltips', 3)
tooltipTimer = self:ScheduleTimer('HookTooltips', 3)
end
end
end
end


function IE:SetParent(frame)
function IE:SetParent(frame)
WIN:SetParent(frame)
WIN:SetParent(frame)
WIN:ClearAllPoints()
WIN:ClearAllPoints()
if not (frame == Examiner) then
if not (frame == Examiner) then
WIN:SetPoint("TOPLEFT", frame, "TOPRIGHT", 5, 0)
WIN:SetPoint("TOPLEFT", frame, "TOPRIGHT", 5, 0)
else
else
WIN:SetPoint("TOPLEFT", frame, "TOPRIGHT", -25, -13)
WIN:SetPoint("TOPLEFT", frame, "TOPRIGHT", -25, -13)
end
end
end
end


function IE:NewLine()
function IE:NewLine()
local row = CreateFrame("Frame", nil, WIN)
local row = CreateFrame("Frame", nil, WIN)
row:SetHeight(12)
row:SetHeight(12)
row:SetWidth(200)
row:SetWidth(200)


local txt = row:CreateFontString(nil, "ARTWORK")
local txt = row:CreateFontString(nil, "ARTWORK")
txt:SetJustifyH("LEFT")
txt:SetJustifyH("LEFT")
txt:SetFontObject(GameFontHighlightSmall)
txt:SetFontObject(GameFontHighlightSmall)
txt:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
txt:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
row.text = txt
row.text = txt


row.yoffset = yoffset
row.yoffset = yoffset
IE:SetLinePadding(row, 0)
IE:SetLinePadding(row, 0)


yoffset = yoffset - 15
yoffset = yoffset - 15
numlines = numlines + 1
numlines = numlines + 1
lines[numlines] = row
lines[numlines] = row


row:EnableMouse(true)
row:EnableMouse(true)
row:SetScript("OnEnter", IE.Line_OnEnter)
row:SetScript("OnEnter", IE.Line_OnEnter)
row:SetScript("OnLeave", IE.Line_OnLeave)
row:SetScript("OnLeave", IE.Line_OnLeave)
row:SetScript("OnMouseDown", IE.Line_OnClick)
row:SetScript("OnMouseDown", IE.Line_OnClick)
end
end


function IE:SetLinePadding(line, padding)
function IE:SetLinePadding(line, padding)
local padWidth = select(2,line.text:GetFont()) * padding * 0.6
local padWidth = select(2,line.text:GetFont()) * padding * 0.6


line:SetPoint("TOPLEFT", WIN, "TOPLEFT", 15 + padWidth, line.yoffset)
line:SetPoint("TOPLEFT", WIN, "TOPLEFT", 15 + padWidth, line.yoffset)
line.padLeft = padWidth
line.padLeft = padWidth
end
end


function IE:ResetDisplay()
function IE:ResetDisplay()
for i = 1, numlines do
for i = 1, numlines do
lines[i].text:SetText("")
lines[i].text:SetText("")
IE:SetLinePadding(lines[i], 0)
IE:SetLinePadding(lines[i], 0)
lines[i]:Hide()
lines[i]:Hide()
end
end
curline = 0
curline = 0
end
end


function IE:AddLine(padding, text, link, item)
function IE:AddLine(padding, text, link, item)
curline = curline + 1
curline = curline + 1
if curline > numlines then
if curline > numlines then
self:NewLine()
self:NewLine()
end
end
local line = lines[curline]
local line = lines[curline]
line.link = link
line.link = link
line.item = item
line.item = item
line.text:SetText(text)
line.text:SetText(text)
line:SetWidth(line.text:GetStringWidth())
line:SetWidth(line.text:GetStringWidth())
IE:SetLinePadding(line, padding)
IE:SetLinePadding(line, padding)
line:SetFrameLevel(WIN:GetFrameLevel() + 1)
line:SetFrameLevel(WIN:GetFrameLevel() + 1)
line:Show()
line:Show()
end
end


function IE:FullUnitName(name, realm)
function IE:FullUnitName(name, realm)
if realm and realm ~= "" then
if realm and realm ~= "" then
return name .. "-" .. realm
return name .. "-" .. realm
else
else
return name
return name
end
end
end
end


function IE:GetExaminerCache(unit)
function IE:GetExaminerCache(unit)
local name, realm = UnitName(unit)
local name, realm = UnitName(unit)
return Examiner_Cache and Examiner_Cache[self:FullUnitName(name, realm)]
return Examiner_Cache and Examiner_Cache[self:FullUnitName(name, realm)]
end
end


function IE:InspectUnit(unit, ...)
function IE:InspectUnit(unit, ...)
origInspectUnit(unit, ...)
origInspectUnit(unit, ...)


if InspectEquipConfig.inspectWindow then
if InspectEquipConfig.inspectWindow then
self:SetParent(Examiner or InspectFrame)
self:SetParent(Examiner or InspectFrame)
WIN:Hide()
WIN:Hide()
if not hooked and InspectFrame_UnitChanged then
if not hooked and InspectFrame_UnitChanged then
hooked = true
hooked = true
self:SecureHook("InspectFrame_UnitChanged")
self:SecureHook("InspectFrame_UnitChanged")
end
end


self:Inspect(unit)
self:Inspect(unit)
end
end
end
end


function IE:InspectFrame_UnitChanged()
function IE:InspectFrame_UnitChanged()
if InspectFrame.unit and InspectEquipConfig.inspectWindow then
if InspectFrame.unit and InspectEquipConfig.inspectWindow then
self:InspectUnit(InspectFrame.unit)
self:InspectUnit(InspectFrame.unit)
else
else
WIN:Hide()
WIN:Hide()
end
end
end
end


function IE:PaperDollFrame_OnShow()
function IE:PaperDollFrame_OnShow()
if InspectEquipConfig.charWindow then
if InspectEquipConfig.charWindow then
IE:SetParent(CharacterFrame)
IE:SetParent(CharacterFrame)
IE:Inspect("player")
IE:Inspect("player")
end
end
end
end


function IE:PaperDollFrame_OnHide()
function IE:PaperDollFrame_OnHide()
if WIN:GetParent() == CharacterFrame then
if WIN:GetParent() == CharacterFrame then
WIN:Hide()
WIN:Hide()
autoHidden = false
autoHidden = false
end
end
end
end


function IE:GearManagerDialog_OnShow()
function IE:GearManagerDialog_OnShow()
if WIN:GetParent() == CharacterFrame and WIN:IsShown() then
if WIN:GetParent() == CharacterFrame and WIN:IsShown() then
WIN:Hide()
WIN:Hide()
autoHidden = true
autoHidden = true
end
end
end
end


function IE:GearManagerDialog_OnHide()
function IE:GearManagerDialog_OnHide()
if autoHidden and WIN:GetParent() == CharacterFrame then
if autoHidden and WIN:GetParent() == CharacterFrame then
WIN:Show()
WIN:Show()
autoHidden = false
autoHidden = false
end
end
end
end


function IE:UNIT_INVENTORY_CHANGED(event, unit)
function IE:UNIT_INVENTORY_CHANGED(event, unit)
if (unit == "player") and (WIN:IsVisible() or autoHidden) and (WIN:GetParent() == CharacterFrame) then
if (unit == "player") and (WIN:IsVisible() or autoHidden) and (WIN:GetParent() == CharacterFrame) then
IE:Inspect("player")
IE:Inspect("player")
elseif (unit == curUnit) and (UnitName(unit) == curUnitName) and (WIN:IsVisible()) then
elseif (unit == curUnit) and (UnitName(unit) == curUnitName) and (WIN:IsVisible()) then
IE:Inspect(curUnit)
IE:Inspect(curUnit)
end
end
end
end


function IE:INSPECT_READY(event, guid)
function IE:INSPECT_READY(event, guid)
if (guid == curGUID) and (UnitName(curUnit) == curUnitName) then
if (guid == curGUID) and (UnitName(curUnit) == curUnitName) then
IE:Inspect(curUnit)
IE:Inspect(curUnit)
else
else
-- probably mouseover changed... nothing we can do apparently :(
-- probably mouseover changed... nothing we can do apparently :(
-- (inspect by unit name / guid does not work)
-- (inspect by unit name / guid does not work)
end
end
end
end


function IE:Inspect(unit, entry)
function IE:Inspect(unit, entry)
local unitName, unitRealm
local unitName, unitRealm
cached = (unit == "cache")
cached = (unit == "cache")


if retryTimer then
if retryTimer then
-- stop retry timer if present
-- stop retry timer if present
self:CancelTimer(retryTimer, true)
self:CancelTimer(retryTimer, true)
retryTimer = nil
retryTimer = nil
end
end


if (cached and (not entry)) or (not self:IsEnabled()) then
if (cached and (not entry)) or (not self:IsEnabled()) then
WIN:Hide()
WIN:Hide()
return
return
end
end


local cacheItems = cached and entry.Items or nil
local cacheItems = cached and entry.Items or nil


if cached then
if cached then
unitName, unitRealm = entry.name, entry.realm
unitName, unitRealm = entry.name, entry.realm
curGUID = nil
curGUID = nil
else
else
if (not unit or not UnitExists(unit)) then
if (not unit or not UnitExists(unit)) then
unit = "player"
unit = "player"
end
end
unitName, unitRealm = UnitName(unit)
unitName, unitRealm = UnitName(unit)
curGUID = UnitGUID(unit)
curGUID = UnitGUID(unit)


if not CanInspect(unit) then
if not CanInspect(unit) then
entry = self:GetExaminerCache(unit)
entry = self:GetExaminerCache(unit)
if entry then
if entry then
cached = true
cached = true
cacheItems = entry.Items
cacheItems = entry.Items
end
end
else
else
--ClearInspectPlayer()
--ClearInspectPlayer()
--NotifyInspect(unit)
--NotifyInspect(unit)
end
end
end
end
if unitRealm == "" then unitRealm = nil end
if unitRealm == "" then unitRealm = nil end
curUnit = unit
curUnit = unit
curUnitName = unitName
curUnitName = unitName
curUser = self:FullUnitName(unitName, unitRealm)
curUser = self:FullUnitName(unitName, unitRealm)
TITLE:SetText("InspectEquip: " .. curUser .. (cached and " (Cache)" or ""))
TITLE:SetText("InspectEquip: " .. curUser .. (cached and " (Cache)" or ""))


self:ResetDisplay()
self:ResetDisplay()


local items = { cats = {}, items = {} }
local items = { cats = {}, items = {} }
local itemsFound = false
local itemsFound = false
local getItem
local getItem
if cached then
if cached then
getItem = function(slot)
getItem = function(slot)
local istr = cacheItems[slot]
local istr = cacheItems[slot]
if istr then
if istr then
local itemId = tonumber(istr:match("item:(%d+)"))
local itemId = tonumber(istr:match("item:(%d+)"))
return select(2, GetItemInfo(istr)) or ("[" .. itemId .. "]")
return select(2, GetItemInfo(istr)) or ("[" .. itemId .. "]")
else
else
return nil
return nil
end
end
end
end
else
else
getItem = function(slot) return GetInventoryItemLink(unit, GetInventorySlotInfo(slot)) end
getItem = function(slot) return GetInventoryItemLink(unit, GetInventorySlotInfo(slot)) end
end
end


local calciv = InspectEquipConfig.showAvgItemLevel
local calciv = InspectEquipConfig.showAvgItemLevel
local iLevelSum, iCount = 0,0
local iLevelSum, iCount = 0,0


local artifactLevel = 0
local artifactCount = 0

for _,slot in pairs(slots) do
for _,slot in pairs(slots) do
local itemLink = getItem(slot)
local itemLink = getItem(slot)
local isArtifact = false

if itemLink then
if itemLink then
-- get source
-- get source
local source = self:GetItemSourceCategories(itemLink)
local source = self:GetItemSourceCategories(itemLink)
if (not source) and InspectEquipConfig.showUnknown then
if (not source) and InspectEquipConfig.showUnknown then
local _,_,rar = GetItemInfo(itemLink)
local _,_,rar,ilvl = GetItemInfo(itemLink)
if rar and rar >= 2 then
if rar and rar >= 2 then
source = {L["Unknown"]}
if rar == 6 then
source = {L["Artifact"]}
else
source = {L["Unknown"]}
end
end
end

if slot == "MainHandSlot" or slot == "SecondaryHandSlot" then
local _,_,rar,ilvl = GetItemInfo(itemLink)

if rar and rar == 6 then -- artifact found
isArtifact = true
artifactCount = artifactCount + 1 -- count only count, lol. ilvl will be get as usual
end
end
end
end


if source then
if source then
local enchantId = tonumber(itemLink:match("Hitem:%d+:(%d+):"))
local enchantId = tonumber(itemLink:match("Hitem:%d+:(%d+):"))
itemsFound = true
itemsFound = true


-- find category
-- find category
local cat = items
local cat = items
local entry
local entry
for _, entry in pairs(source) do
for _, entry in pairs(source) do
if cat.cats[entry] == nil then
if cat.cats[entry] == nil then
cat.cats[entry] = { count = 0, cats = {}, items = {} }
cat.cats[entry] = { count = 0, cats = {}, items = {} }
end
end
cat = cat.cats[entry]
cat = cat.cats[entry]
cat.count = cat.count + 1
cat.count = cat.count + 1
end
end


-- add item to category
-- add item to category
cat.hasItems = true
cat.hasItems = true
cat.items[cat.count] = {link = itemLink, enchant = enchantId, slot = slot}
cat.items[cat.count] = {link = itemLink, enchant = enchantId, slot = slot}
end
end


-- calculate avg ilvl
-- calculate avg ilvl
if calciv then
if calciv then
local lvl = ItemUpgradeInfo:GetUpgradedItemLevel(itemLink)
local lvl = ItemUpgradeInfo:GetUpgradedItemLevel(itemLink)

if lvl then
if lvl then
iLevelSum = iLevelSum + lvl

iCount = iCount + 1
if isArtifact then
if lvl > artifactLevel then -- find out max artifact level from both items
artifactLevel = lvl
end
else
iLevelSum = iLevelSum + lvl
iCount = iCount + 1
end
end
end
end
end
elseif not cached then
elseif not cached then
local texture = GetInventoryItemTexture(unit, GetInventorySlotInfo(slot))
local texture = GetInventoryItemTexture(unit, GetInventorySlotInfo(slot))
if texture and not retryTimer then
if texture and not retryTimer then
-- item link is not yet available, but item texture is, i.e. the slot is not empty
-- item link is not yet available, but item texture is, i.e. the slot is not empty
-- item link data will become available shortly, so we just try it again in a sec
-- item link data will become available shortly, so we just try it again in a sec
retryTimer = self:ScheduleTimer("Inspect", 1, unit)
retryTimer = self:ScheduleTimer("Inspect", 1, unit)
end
end
end
end
end
end


if itemsFound then
if itemsFound then
self:AddCategory(items, 0)
self:AddCategory(items, 0)
if calciv and iCount > 0 then
if calciv and iCount > 0 then
iLevelSum = iLevelSum + artifactLevel * artifactCount
iCount = iCount + artifactCount

local avgLvl = iLevelSum / iCount
local avgLvl = iLevelSum / iCount
AVGIL:SetText(L["Avg. Item Level"] .. ": " .. string.format("%.2f", avgLvl))
AVGIL:SetText(L["Avg. Item Level"] .. ": " .. string.format("%.2f", avgLvl))
AVGIL:Show()
AVGIL:Show()
else
else
AVGIL:Hide()
AVGIL:Hide()
end
end
self:FixWindowSize()
self:FixWindowSize()
if WIN:GetParent() == CharacterFrame and ((GearManagerDialog and GearManagerDialog:IsVisible()) or (OutfitterFrame and OutfitterFrame:IsVisible())) then
if WIN:GetParent() == CharacterFrame and ((GearManagerDialog and GearManagerDialog:IsVisible()) or (OutfitterFrame and OutfitterFrame:IsVisible())) then
autoHidden = true
autoHidden = true
else
else
WIN:Show()
WIN:Show()
end
end
else
else
WIN:Hide()
WIN:Hide()
end
end
end
end


function IE:AddCategory(cat, padding)
function IE:AddCategory(cat, padding)
-- add items
-- add items
if cat.hasItems then
if cat.hasItems then
self:AddItems(cat.items, padding+1)
self:AddItems(cat.items, padding+1)
end
end


-- sort subcategories by item count
-- sort subcategories by item count
local t = {}
local t = {}
for name, subcat in pairs(cat.cats) do
for name, subcat in pairs(cat.cats) do
tinsert(t, {name = name, subcat = subcat})
tinsert(t, {name = name, subcat = subcat})
end
end
tsort(t, function(a,b) return a.subcat.count > b.subcat.count end)
tsort(t, function(a,b) return a.subcat.count > b.subcat.count end)


-- add subcategories
-- add subcategories
for i = 1, #t do
for i = 1, #t do
local name = t[i].name
local name = t[i].name
local subcat = t[i].subcat
local subcat = t[i].subcat
self:AddLine(padding, name .. " (" .. subcat.count .. ")")
self:AddLine(padding, name .. " (" .. subcat.count .. ")")
self:AddCategory(subcat, padding+1)
self:AddCategory(subcat, padding+1)
end
end
end
end


function IE:AddItems(tab, padding)
function IE:AddItems(tab, padding)
for _, item in pairs(tab) do
for _, item in pairs(tab) do
local suffix = ""
local suffix = ""
local prefix = ""
local prefix = ""
if InspectEquipConfig.listItemLevels then
if InspectEquipConfig.listItemLevels then
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel(item.link)
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel(item.link)
if ilvl then
if ilvl then
prefix = "|cffaaaaaa[" .. ilvl .. "]|r "
prefix = "|cffaaaaaa[" .. ilvl .. "]|r "
end
end
end
end
if InspectEquipConfig.checkEnchants and (item.enchant == 0) and (not noEnchantWarningSlots[item.slot]) then
if InspectEquipConfig.checkEnchants and (item.enchant == 0) and (not noEnchantWarningSlots[item.slot]) then
suffix = "|cffff0000*|r"
suffix = "|cffff0000*|r"
end
end
self:AddLine(padding, prefix .. item.link .. suffix, item.link, item)
self:AddLine(padding, prefix .. item.link .. suffix, item.link, item)
end
end
end
end


function IE:GetItemData(item)
function IE:GetItemData(item)
local id
local id
if type(item) == "number" then
if type(item) == "number" then
id = item
id = item
else -- item string/link
else -- item string/link
id = tonumber(item:match("item:(%d+)"))
id = tonumber(item:match("item:(%d+)"))
end
end


if id then
if id then
local isSrc = IS.Items[id]
local isSrc = IS.Items[id]
local locSrc = InspectEquipLocalDB.Items[id]
local locSrc = InspectEquipLocalDB.Items[id]
if isSrc and locSrc then
if isSrc and locSrc then
-- combine results
-- combine results
return locSrc .. ";" .. isSrc
return locSrc .. ";" .. isSrc
else
else
return isSrc or locSrc
return isSrc or locSrc
end
end
else
else
return nil
return nil
end
end
end
end


function IE:GetZoneName(id)
function IE:GetZoneName(id)
return IS.Zones[id] or InspectEquipLocalDB.Zones[id]
return IS.Zones[id] or InspectEquipLocalDB.Zones[id]
end
end


function IE:GetBossName(id)
function IE:GetBossName(id)
return IS.Bosses[id] or InspectEquipLocalDB.Bosses[id]
return IS.Bosses[id] or InspectEquipLocalDB.Bosses[id]
end
end


function IE:GetItemSourceCategories(itemLink)
function IE:GetItemSourceCategories(itemLink)
local data = IE:GetItemData(itemLink)
local data = IE:GetItemData(itemLink)
if data then
if data then
for entry in gmatch(data, "[^;]+") do
for entry in gmatch(data, "[^;]+") do
local next_field = gmatch(entry, "[^_]+")
local next_field = gmatch(entry, "[^_]+")
local cat = next_field()
local cat = next_field()


if cat == "r" or cat == "d" then
if cat == "r" or cat == "d" then
-- raid/dungeon
-- raid/dungeon
local zone = IE:GetZoneName(tonumber(next_field()))
local zone = IE:GetZoneName(tonumber(next_field()))
local mode = next_field()
local mode = next_field()
local zoneType
local zoneType
if cat == "r" then zoneType = L["Raid"] else zoneType = L["Instances"] end
if cat == "r" then zoneType = L["Raid"] else zoneType = L["Instances"] end
return {zoneType, zone}
return {zoneType, zone}
elseif cat == "v" or cat == "g" then
elseif cat == "v" or cat == "g" then
-- vendor
-- vendor
local mainCat
local mainCat
if cat == "v" then mainCat = L["Vendor"] else mainCat = L["Guild Vendor"] end
if cat == "v" then mainCat = L["Vendor"] else mainCat = L["Guild Vendor"] end
local typ = next_field()
local typ = next_field()
while typ do
while typ do
if typ == "c" then
if typ == "c" then
-- currency
-- currency
local currency = tonumber(next_field())
local currency = tonumber(next_field())
next_field()
next_field()
local curName = GetCurrencyInfo(currency)
local curName = GetCurrencyInfo(currency)
return {mainCat, curName}
return {mainCat, curName}
elseif typ == "i" then
elseif typ == "i" then
-- item
-- item
next_field()
next_field()
elseif typ == "m" then
elseif typ == "m" then
-- money
-- money
next_field()
next_field()
end
end
typ = next_field()
typ = next_field()
end
end
return {mainCat}
return {mainCat}
elseif cat == "f" then
elseif cat == "f" then
-- reputation rewards
-- reputation rewards
return {L["Reputation rewards"]}
return {L["Reputation rewards"]}
elseif cat == "m" then
elseif cat == "m" then
-- darkmoon cards
-- darkmoon cards
return {L["Darkmoon Faire"]}
return {L["Darkmoon Faire"]}
elseif cat == "w" then
elseif cat == "w" then
-- world drops
-- world drops
return {L["World drops"]}
return {L["World drops"]}
elseif cat == "c" then
elseif cat == "c" then
-- crafted
-- crafted
return {L["Crafted"]}
return {L["Crafted"]}
elseif cat == "q" then
elseif cat == "q" then
-- quest rewards
-- quest rewards
return {L["Quest Reward"]}
return {L["Quest Reward"]}
end
end


end
end
end
end
return nil
return nil
end
end


function IE:FixWindowSize()
function IE:FixWindowSize()
local maxwidth = TITLE:GetStringWidth()
local maxwidth = TITLE:GetStringWidth()
for i = 1, numlines do
for i = 1, numlines do
local width = lines[i].text:GetStringWidth() + lines[i].padLeft
local width = lines[i].text:GetStringWidth() + lines[i].padLeft
if maxwidth < width then maxwidth = width end
if maxwidth < width then maxwidth = width end
end
end
local height = (curline * 15) + 55
local height = (curline * 15) + 55
if InspectEquipConfig.showAvgItemLevel then
if InspectEquipConfig.showAvgItemLevel then
height = height + 15
height = height + 15
end
end
WIN:SetWidth(maxwidth + 40)
WIN:SetWidth(maxwidth + 40)
WIN:SetHeight(height)
WIN:SetHeight(height)
end
end


function IE.Line_OnEnter(row)
function IE.Line_OnEnter(row)
if row.link then
if row.link then
-- anchor on the correct side based on where there's more room
-- anchor on the correct side based on where there's more room
GameTooltip:SetOwner(row, "ANCHOR_NONE")
GameTooltip:SetOwner(row, "ANCHOR_NONE")
local ycenter = select(2, row:GetCenter()) * row:GetEffectiveScale()
local ycenter = select(2, row:GetCenter()) * row:GetEffectiveScale()
if ycenter > select(2, UIParent:GetCenter()) * UIParent:GetScale() then
if ycenter > select(2, UIParent:GetCenter()) * UIParent:GetScale() then
GameTooltip:SetPoint("TOPLEFT", row, "BOTTOMLEFT")
GameTooltip:SetPoint("TOPLEFT", row, "BOTTOMLEFT")
else
else
GameTooltip:SetPoint("BOTTOMLEFT", row, "TOPLEFT")
GameTooltip:SetPoint("BOTTOMLEFT", row, "TOPLEFT")
end
end
if (not cached) and (UnitName(curUnit) == curUnitName) then
if (not cached) and (UnitName(curUnit) == curUnitName) then
row.link = GetInventoryItemLink(curUnit, GetInventorySlotInfo(row.item.slot)) or row.link
row.link = GetInventoryItemLink(curUnit, GetInventorySlotInfo(row.item.slot)) or row.link
end
end
GameTooltip:SetHyperlink(row.link)
GameTooltip:SetHyperlink(row.link)
if row.item and InspectEquipConfig.checkEnchants and (row.item.enchant == 0) and (not noEnchantWarningSlots[row.item.slot]) then
if row.item and InspectEquipConfig.checkEnchants and (row.item.enchant == 0) and (not noEnchantWarningSlots[row.item.slot]) then
GameTooltip:AddLine(" ")
GameTooltip:AddLine(" ")
GameTooltip:AddLine("|cffff0000" .. L["Item is not enchanted"] .. "|r")
GameTooltip:AddLine("|cffff0000" .. L["Item is not enchanted"] .. "|r")
end
end
GameTooltip:Show()
GameTooltip:Show()
end
end
end
end


function IE.Line_OnLeave(row)
function IE.Line_OnLeave(row)
GameTooltip:Hide()
GameTooltip:Hide()
end
end


function IE.Line_OnClick(row, button)
function IE.Line_OnClick(row, button)
if row.link then
if row.link then
if IsControlKeyDown() then
if IsControlKeyDown() then
DressUpItemLink(row.link)
DressUpItemLink(row.link)
elseif IsShiftKeyDown() then
elseif IsShiftKeyDown() then
ChatEdit_InsertLink(row.link)
ChatEdit_InsertLink(row.link)
end
end
end
end
end
end