View Single Post
01-15-15, 11:41 AM   #2
EKE
An Aku'mai Servant
 
EKE's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2011
Posts: 37
this is an update from villiv's EquippedItemLevel, edit by nj55top

but cant use with freebtip because they get lua code conflict.

Code:
--[[ Equipped Item Level v121025 villiv ]]--

-- decimal places of the equipped average item level. to assign '2' will show it like '123.45'
local DECIMAL_PLACES = 2

-- additional strings. if you don't like it just assign 'nil'. but do not delete these variables themselves.
local UPDATED = CANNOT_COOPERATE_LABEL -- '*'
local WAITING = CONTINUED -- '...'
local PENDING = CONTINUED .. CONTINUED -- '......'

-- output prefix. has to have unique strings to update the tooltip correctly
local PREFIX = STAT_FORMAT:format(STAT_AVERAGE_ITEM_LEVEL) .. '|Heqppditmlvl|h |h' .. HIGHLIGHT_FONT_COLOR_CODE


local f = CreateFrame('Frame')
f:SetScript('OnEvent', function(self, event, ...) return self[event](self, event, ...) end)
f:Hide()

local playerGUID, inCombat, updateTimer
local currentUnit, currentGUID
local isDelayed, isForced, isNotified, isReady

local function GetTipUnit ()
	local _, unit = GameTooltip:GetUnit()
	if ( not unit ) then
		local mouseFocus = GetMouseFocus()
		unit = mouseFocus and (mouseFocus.unit or mouseFocus:GetAttribute('unit'))
	end

	return unit and UnitIsPlayer(unit) and unit
end

local SetTipText
do
	local function search (line, numLines)
		if ( line > numLines ) then return end

		local fontString = _G['GameTooltipTextLeft' .. line]
		local stringText = fontString and fontString:GetText()
		if ( stringText and stringText:match(PREFIX) ) then	return fontString end

		return search(line + 1, numLines)
	end

	function SetTipText (text)
		if ( not text ) then return end

		local fontString = search(1, GameTooltip:NumLines())
		if ( fontString ) then
			fontString:SetText(PREFIX .. text)
		else
			GameTooltip:AddLine(PREFIX .. text)
		end

		return GameTooltip:Show()
	end
end

local CanSafeInspect -- 6 times per 10 secs
do
	local limit, period = 6, 11
	local count, startTime = 0, 0

	hooksecurefunc('NotifyInspect', function ()
		local currentTime = GetTime()
		if ( currentTime - startTime > period ) then
			count, startTime = 1, currentTime
			return
		end

		count = count + 1
	end)

	function CanSafeInspect (unit)
		if ( not CanInspect(unit) or InspectFrame and InspectFrame:IsShown() or Examiner and Examiner:IsShown() ) then return end

		local pending = count > limit and period - (GetTime() - startTime)
		return true, pending and pending > 0 and pending
	end
end

local UnitItemLevel
do
	local formatString = '%.' .. DECIMAL_PLACES .. 'f'

	local function scan (unit, slot, total, count, twoHanded, incomplete)
		if ( slot > INVSLOT_LAST_EQUIPPED ) then
			return formatString:format(total / (twoHanded and count - 2 or count-1)), incomplete
		end

		if ( slot == INVSLOT_BODY or slot == INVSLOT_TABARD ) then
			return scan(unit, slot + 1, total, count, twoHanded, incomplete)
		end

		local hasItem = GetInventoryItemTexture(unit, slot) and true
		local _, level, equipLoc

		local link = hasItem and GetInventoryItemLink(unit, slot)
		if ( link ) then
			repeat
				_, _, _, level, _, _, _, _, equipLoc = GetItemInfo(link)
			until level and equipLoc

			total = total + level
		end

		-- two-handed weapon and Titan's Grip
		if ( slot == INVSLOT_MAINHAND ) then
			twoHanded = equipLoc == 'INVTYPE_2HWEAPON' and 1 or not hasItem and 0
		elseif ( slot == INVSLOT_OFFHAND ) then
			twoHanded = twoHanded == 1 and not hasItem or twoHanded == 0 and equipLoc == 'INVTYPE_2HWEAPON'
		end

		local failed = hasItem and not link
		return scan(unit, slot + 1, total, failed and count or count + 1, twoHanded, incomplete or failed)
	end

	function UnitItemLevel (unit)
		if ( unit == 'player' or UnitIsUnit(unit, 'player') ) then
			local _, level = GetAverageItemLevel()
			return formatString:format(level)
		end

		return scan(unit, INVSLOT_FIRST_EQUIPPED, 0, 0)
	end
end

local UpdateItemLevel
do
	local cache = {}
	local cachedLevel

	local function update (unit, guid)
		local level, incomplete = UnitItemLevel(unit)

		if ( incomplete ) then
			updateTimer = TOOLTIP_UPDATE_TIME
			f:Show()
			level = cachedLevel or level
			return SetTipText(WAITING and level .. WAITING or level)
		end

		if ( isReady ) then
			cache[guid] = level
			return SetTipText(UPDATED and level .. UPDATED or level)
		end

		level = cachedLevel or level
		return SetTipText(WAITING and level .. WAITING or level)
	end

	function UpdateItemLevel ()
		cachedLevel = cache[currentGUID]

		if ( inCombat ) then return SetTipText(cachedLevel) end

		if ( isReady ) then return update(currentUnit, currentGUID) end

		if ( not isForced and cachedLevel ) then return SetTipText(cachedLevel) end

		if ( currentGUID == playerGUID ) then
			local level = UnitItemLevel('player')
			cache[playerGUID] = level
			return SetTipText(level)
		end

		local canInspect, pending = CanSafeInspect(currentUnit)
		if ( not canInspect ) then return SetTipText(cachedLevel) end

		if ( pending ) then
			updateTimer = pending
			f:Show()
			return SetTipText(cachedLevel and cachedLevel .. PENDING or PENDING)
		end

		if ( not isDelayed ) then
			isDelayed = true
			updateTimer = TOOLTIP_UPDATE_TIME
			f:Show()
			return SetTipText(cachedLevel and (WAITING and cachedLevel .. WAITING or cachedLevel) or PENDING)
		end

		if ( not isNotified ) then
			isNotified = true
			NotifyInspect(currentUnit)
		end

		return update(currentUnit, currentGUID)
	end
end

local function OnTooltipSetUnit ()
	currentUnit, currentGUID, isDelayed, isForced, isNotified, isReady = GetTipUnit(), nil, nil, nil, nil, nil
	if ( not currentUnit ) then return end

	currentGUID, isForced = UnitGUID(currentUnit), UnitIsUnit(currentUnit, 'target')

	return UpdateItemLevel()
end
GameTooltip:HookScript('OnTooltipSetUnit', OnTooltipSetUnit)

f:SetScript('OnUpdate', function (self, elapsed)
	updateTimer = updateTimer - elapsed
	if ( updateTimer > 0 ) then return end
	self:Hide()

	if ( not currentGUID ) then return end

	local tipUnit = GetTipUnit()
	if ( not tipUnit or UnitGUID(tipUnit) ~= currentGUID ) then return end

	return UpdateItemLevel()
end)

function f:INSPECT_READY (_, guid)
	if ( not currentGUID or guid ~= currentGUID ) then return end

	local tipUnit = GetTipUnit()
	if ( not tipUnit or UnitGUID(tipUnit) ~= currentGUID ) then return end

	isReady = true

	return UpdateItemLevel()
end
f:RegisterEvent('INSPECT_READY')

function f:UNIT_INVENTORY_CHANGED (_, unit)
	if ( not currentGUID or UnitGUID(unit) ~= currentGUID ) then return end

	local tipUnit = GetTipUnit()
	if ( not tipUnit or UnitGUID(tipUnit) ~= currentGUID ) then return end

	isForced, isNotified, isReady = true, nil, nil

	return UpdateItemLevel()
end
f:RegisterEvent('UNIT_INVENTORY_CHANGED')

function f:PLAYER_TARGET_CHANGED ()
	return self:UNIT_INVENTORY_CHANGED (nil, 'target')
end
f:RegisterEvent('PLAYER_TARGET_CHANGED')

function f:PLAYER_REGEN_DISABLED ()
	inCombat = true
end
f:RegisterEvent('PLAYER_REGEN_DISABLED')

function f:PLAYER_REGEN_ENABLED ()
	inCombat = nil
end
f:RegisterEvent('PLAYER_REGEN_ENABLED')

function f:PLAYER_LOGIN ()
	self:UnregisterEvent('PLAYER_LOGIN')
	self.PLAYER_LOGIN = nil

	playerGUID = UnitGUID('player')
end

if ( IsLoggedIn() ) then
	f:PLAYER_LOGIN()
	inCombat = InCombatLockdown()
	return OnTooltipSetUnit()
end

return f:RegisterEvent('PLAYER_LOGIN')

Last edited by EKE : 01-15-15 at 04:15 PM. Reason: Don't link to off-site downloads.
  Reply With Quote