WoWInterface SVN hoverinfo

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

trunk/HoverInfo.lua File deleted
trunk/HoverInfo.toc File deleted
trunk/HoverInfo/HoverInfo.toc New file
0,0 → 1,7
## Interface: 40000
## Revision: $Rev: 0 $
## Title: HoverInfo
## Notes: Show target's specs and ilevel in tooltip
## Author: Aledara (wowi AT jocosoft DOT com)
 
HoverInfo.lua
trunk/HoverInfo/HoverInfo.lua New file
0,0 → 1,341
-- Constants
local CACHE_SIZE = 0 -- Max. # of characters in cache
local CACHE_EXPIRE = 60 -- Cached entries will expire after this # of seconds
local INSPECT_DELAY = 0.1 -- Time to hover over unit before NotifyInspect() is called
local TXT_LOADING = "Loading items..."
 
LoadAddOn("Blizzard_InspectUI")
 
--[[
This is a workaround for a bug in blizzard's UI code, that popups
an error when inspecting a unit when the actual inspection window
is not open. Supposidely fixed in 4.1
 
Alternatively, install InspectFix:
http://wow.curse.com/downloads/wow-addons/details/inspectfix.aspx
]]
local function patch()
local oldfunc1=InspectPaperDollFrame_SetLevel;
InspectPaperDollFrame_SetLevel=function(...)
if InspectFrame.unit and UnitExists(InspectFrame.unit) then
return oldfunc1(...);
end
end;
 
local oldfunc2=InspectGuildFrame_Update;
InspectGuildFrame_Update=function(...)
if InspectFrame.unit and UnitExists(InspectFrame.unit) then
return oldfunc2(...);
end
end;
end
 
if IsAddOnLoaded("Blizzard_InspectUI") then
patch();
else
local eframe=CreateFrame("Frame");
eframe:RegisterEvent("ADDON_LOADED");
eframe:SetScript("OnEvent",function(self,event,arg)
if event=="ADDON_LOADED" and arg=="Blizzard_InspectUI" then
self:UnregisterEvent(event);
patch();
end
end);
end
--[[
End of workaround. When fixed, delete this whole block.
]]
 
 
local Cache = {new = function()
local self = {}
self.data = {}
self.remove = function(guid)
for i=1,#self.data do
if guid==self.data[i].guid then
tremove(self.data,i)
break
end
end
end
self.removeExpired = function()
local exptime=GetTime()-CACHE_EXPIRE
local i=1
while i<=#self.data do
if self.data[i].time<exptime then
tremove(self.data,i)
else
i=i+1
end
end
end
self.limitSize = function()
while #self.data>CACHE_SIZE do
tremove(self.data,1)
end
end
self.add = function(guid,ilvl,missing,spec1,spec2)
-- If unit is already in cache, remove it
self.remove(guid)
 
-- Add unit to end of cache
self.data[#self.data+1] = {
["guid"] = guid,
["ilvl"] = ilvl,
["missing"] = missing,
["spec1"] = spec1,
["spec2"] = spec2,
["time"] = GetTime()
}
end
self.find = function(guid)
self.removeExpired()
if CACHE_SIZE > 0 then
for i=1,#self.data do
if guid==self.data[i].guid then
return self.data[i].ilvl, self.data[i].missing, self.data[i].spec1, self.data[i].spec2
end
end
end
return nil
end
return self
end}
 
 
 
local function levelColor(iLevel)
local max=360
local H=1-iLevel/max
if H<0 then
H=0
end
 
-- Now we have the hue, convert this to rgb, then convert that to hex
 
local R,G,B=0,0,0
var_h=H*6
if var_h==6 then
var_h=0
end
var_i=math.floor(var_h)
var_3=var_h-var_i
 
if var_i==0 then
R=1
G=var_3
elseif var_i==1 then
R=1-var_3
G=1
elseif var_i==2 then
G=1
B=var_3
elseif var_i==3 then
G=1-var_3
B=1
elseif var_i==4 then
R=var_3
B=1
else
R=1
B=1-var_3
end
return format("%02x%02x%02x", (R*255), (G*255), (B*255) );
end
 
local function getItemLevel(target)
local total=0
local count=0
local missing=0
for i=1,18 do
-- Skip shirt slot
if i~=4 then
-- If no item is equiped in a slot, count it as ilvl 0
-- An exception would be offhand when a two-hander
-- is equipped.
 
local level=0
local item=GetInventoryItemLink(target,i)
if item ~= nil then
_,_,_,level,_,_,_,_,loc = GetItemInfo(item)
if loc=="INVTYPE_2HWEAPON" then
count=count-1
missing=missing-1
end
else
missing=missing+1
end
total=total+level
count=count+1
end
end
if count>0 then
return math.floor(total/count,1),missing
else
return 0,missing
end
end
 
local function specInfo(group)
local treename = "None"
local primary = GetPrimaryTalentTree(true,false,group)
if primary then
_,treename = GetTalentTabInfo(primary,true,false,group)
end
local _,_,_,_,p1 = GetTalentTabInfo(1,true,false,group)
local _,_,_,_,p2 = GetTalentTabInfo(2,true,false,group)
local _,_,_,_,p3 = GetTalentTabInfo(3,true,false,group)
return format( "%s (%d/%d/%d)",treename or "none",p1 or 0,p2 or 0,p3 or 0 )
end
 
c = CreateFrame("Frame")
c.TimeSinceLastUpdate = 0
c.currentGUID = nil -- GUID of unit that triggered NotifyInspect() call
c.currentUnit = nil
c.currentTime = nil
c.inspectCache = Cache:new()
c.inspectTime = nil
-- c:RegisterEvent("INSPECT_READY")
 
c:SetScript("OnEvent",function(self,event,guid,...)
if event=="INSPECT_READY" then
self:UnregisterEvent("INSPECT_READY")
 
-- Now, because this fires prematurely 9 out of 10 times,
-- and itemdata is using the streaming system, we start
-- a timer, that will keep checking if we have everything yet.
-- Only when we do, we can inspect the unit...
-- This is handled in the OnUpdate event!
-- Don't you just love how useful some events are? This event
-- should be renamed INSPECT_KINDASORTA_READY_BUTNOTREALLY
-- It would be just as useful, but at least have an accurate
-- name...
 
local active = GetActiveTalentGroup(true, false)
if active~=1 then offspec=1 else offspec=2 end
local spec1 = specInfo(active)
local spec2 = specInfo(offspec)
 
GameTooltip:AddLine( "Current Spec: "..spec1 )
GameTooltip:AddLine( "Alt. Spec: "..spec2 )
GameTooltip:AddLine( TXT_LOADING )
GameTooltip:Show()
 
self.inspectTime = GetTime() + 0.2
end
end)
 
c:SetScript("OnUpdate",function(self,elapsed)
local now = GetTime()
 
if self.inspectTime and now >= self.inspectTime then
local _,unit = GameTooltip:GetUnit()
if unit then
guid = UnitGUID(unit)
if guid==self.currentGUID then
-- Determine if iteminfo is complete yet
local done = true
for i=1,18 do
if GetInventoryItemTexture(unit, i) and not GetInventoryItemLink(unit, i) then
-- GetTexture always return stuff but GetLink is not.
done = false
break
end
end
 
 
if done then
ile,missing=getItemLevel(unit)
local offspec=2
local active = GetActiveTalentGroup(true, false)
if active~=1 then offspec=1 end
local spec1 = specInfo(active)
local spec2 = specInfo(offspec)
ClearInspectPlayer()
 
self.inspectCache.add(guid,ile,missing,spec1,spec2)
 
-- Replace the "Loading iLvls..." text with item level info
for i=2, GameTooltip:NumLines() do
if (_G["GameTooltipTextLeft"..i]:GetText() or "") == TXT_LOADING then
_G["GameTooltipTextLeft"..i]:SetFormattedText("%s", getTTilevel(ile,missing) );
end
end
GameTooltip:Show()
 
self.inspectTime = nil
else
-- Nope try again in 0.2 secs
-- print( "Data still loading..." )
-- Would be nice if we can do some animation
-- in the tooltip...
self.inspectTime = now + 0.2
end
 
else
-- Current tooltip is for different unit
-- print( "Aborting inspection: Data is for differnt unit than target" )
self.inspectTime = nil
end
else
-- No tooltip, no unit....
-- print( "Aborting inspection: No unit targeted" )
self.inspectTime = nil
end
end
 
 
if (c.currentTime == nil) or ((now - c.currentTime) < INSPECT_DELAY) then return end
 
-- If current tooltip is still for the requested unit,
-- fire a notify request for it
local _,unit = GameTooltip:GetUnit()
if unit and (unit==self.currentUnit) and UnitIsPlayer(unit) and CheckInteractDistance(unit,1) and CanInspect(unit) then
guid = UnitGUID(unit)
if guid==self.currentGUID then
-- it SEEMS that calling this several times reduces
-- missing items. Still happens though:(
 
self:RegisterEvent("INSPECT_READY")
NotifyInspect(unit)
end
else
-- print ("Cannot inspect unit")
end
c.currentTime = nil
end)
 
function getTTilevel(ilevel,missing)
local color=levelColor(ilevel)
 
local s = "iLevel: |cff"..color..tostring(ilevel).."|r"
if missing>0 then
s = s.." (|cffff0000"..missing.."|r items missing)"
end
return s
end
 
GameTooltip:HookScript("OnTooltipSetUnit",function(self,...)
local _,unit = self:GetUnit();
if (not unit) then
local mFocus = GetMouseFocus()
if (mFocus) and (mFocus.unit) then
unit=mFocus.unit
end
end
 
if unit and UnitIsPlayer(unit) then
guid = UnitGUID(unit)
ilvl,missing,spec1,spec2 = c.inspectCache.find(guid)
if ilvl then
GameTooltip:AddLine( "Current Spec: "..spec1 )
GameTooltip:AddLine( "Alt. Spec: "..spec2 )
GameTooltip:AddLine( getTTilevel(ilvl,missing) )
GameTooltip:Show()
else
c.currentGUID = guid
c.currentUnit = unit
c.currentTime = GetTime()
end
end
end);