changeset 146:543fcf15add7

Handle new itemstring format for item variants. Heroic, warforged, etc, are now additional fields in the itemstring rather than separate item IDs as in the last few expansions. This fixes the tooltip displays for such items; there's nothing yet in place for determining the exact variations (need to finish the list of bonus codes). Some minor efficiency tweaks.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Tue, 30 Dec 2014 17:52:30 -0500
parents e4bfe7a8b1c9
children e1a90e398231
files core.lua
diffstat 1 files changed, 112 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/core.lua	Tue Dec 30 17:45:06 2014 -0500
+++ b/core.lua	Tue Dec 30 17:52:30 2014 -0500
@@ -1,7 +1,7 @@
 local nametag, addon = ...
 
 --[==[
-g_loot's numeric indices are loot entries (including titles, separators,
+g_loot's numeric indices are <Loot> entries (including titles, separators,
 etc); its named indices are:
 - forum         saved text from forum markup window, default nil
 - attend        saved text from raid attendence window, default nil
@@ -55,6 +55,7 @@
                 otherwise
 - itemname      not including square brackets
 - id            itemID as number
+- itemstring    "item:nnnnn" string
 - itemlink      full clickable link
 - itexture      icon path (e.g., Interface\Icons\INV_Misc_Rune_01)
 - quality       [LE_]ITEM_QUALITY_* number
@@ -65,6 +66,8 @@
                 extratext; triggers only for a stack of items, not "the boss
                 dropped double axes today"
 - variant       1 = heroic item, 2 = LFR item; missing otherwise
+                XXX CHANGED FOR WoD:  for now, if present at all, some kind
+				of heroic/warforged/something-extra; missing otherwise
 - cache_miss    if GetItemInfo failed; SHOULD be missing (changes other fields)
 - bcast_from    player's name if received rebroadcast from that player;
                 missing otherwise; can be deleted as a result of in-game
@@ -389,7 +392,7 @@
 	type, select, next, pairs, ipairs, table.insert, table.remove, tostring, tonumber, table.wipe
 
 local pprint, tabledump = addon.pprint, flib.tabledump
-local CopyTable = CopyTable
+local strsplit, CopyTable = strsplit, CopyTable
 local GetNumGroupMembers = GetNumGroupMembers
 local IsInRaid = IsInRaid
 -- En masse forward decls of symbols defined inside local blocks
@@ -470,7 +473,6 @@
 	amusingly, print()'ing the fullstring below as a debugging aid yields
 	another clickable link, yay data reproducability
 	]]
-	local strsplit = strsplit
 	DEFAULT_CHAT_FRAME:HookScript("OnHyperlinkClick", function(self, link, fullstring, mousebutton)
 		local ltype, arg = strsplit(":",link)
 		if ltype ~= "OuroLoot" then return end
@@ -945,12 +947,12 @@
 		local btn = CreateFrame("Button", "OuroLootBindingOpen", nil, "SecureActionButtonTemplate")
 		btn:SetAttribute("type", "macro")
 		btn:SetAttribute("macrotext", "/ouroloot toggle")
-		if SetBindingClick(opts.keybinding_text, "OuroLootBindingOpen") then
+		if SetBindingClick (opts.keybinding_text, "OuroLootBindingOpen") then
 			-- a simple SaveBindings(GetCurrentBindingSet()) occasionally fails when
 			-- GCBS() decides to return neither 1 nor 2 during load, for reasons nobody
 			-- has ever learned
 			local c = GetCurrentBindingSet()
-			if c == ACCOUNT_BINDINGS or c == CHARACTER_BINDINGS then
+			if c == _G.ACCOUNT_BINDINGS or c == _G.CHARACTER_BINDINGS then
 				SaveBindings(c)
 			end
 		else
@@ -966,7 +968,7 @@
 	the slim chance that one of the non-US "delocalizers" needs to mess with
 	the global patterns before we transform them.
 	
-	The SELF variants can be replaced with LOOT_ITEM_PUSHED_SELF[_MULTIPLE] to
+	The SELF patterns can be replaced with LOOT_ITEM_PUSHED_SELF[_MULTIPLE] to
 	trigger on 'receive item' instead, which would detect extracting stuff
 	from mail, or s/PUSHED/CREATED/ for things like healthstones and guild
 	cauldron flasks.
@@ -1037,10 +1039,10 @@
 	InterfaceOptions_AddCategory(bliz)
 
 	-- Maybe load up g_uniques now?
+	-- Calling the memory-querying APIs while in combat instantly triggers
+	-- the "script ran too long" error, see
+	-- http://www.wowinterface.com/forums/showthread.php?t=44812
 	if opts.precache_history_uniques and not InCombatLockdown() then
-		-- Calling the memory-querying APIs while in combat instantly
-		-- triggers the "script ran too long" error, see
-		-- http://www.wowinterface.com/forums/showthread.php?t=44812
 		self:_cache_history_uniques()
 	end
 	self._cache_history_uniques = nil
@@ -1063,7 +1065,7 @@
 	Inherited unchanged:
 	- _add_loot_disposition
 
-	Inherited module variants:
+	Inherited module variations:
 	- OnInitialize, OnEnable
 	- register_text_generator, register_tab_control:  also flag plugin as
 		a text-generating module in main addon
@@ -1110,7 +1112,7 @@
 		end
 		function addon:OnModuleCreated (plugin)
 			local token, code = self.format_hypertext (plugin.moduleName,
-				--[[heirloom]]7, "ModulePrefixClick")
+				LE_ITEM_QUALITY_LEGENDARY, "ModulePrefixClick")
 			chat_prefixes[plugin] = token
 			chat_codes[code] = plugin
 			-- remove the libraries' embedded pointers so that the prototype
@@ -1252,8 +1254,8 @@
 	-- etc.  So firing a callback is delayed ever so briefly by human scales.
 	--
 	-- For data safety, we replace any table arguments with read-only proxies
-	-- before passing them to the callbacks.  The goal is to prevent accidents,
-	-- not fraud.
+	-- before passing them to the callbacks.  It's not supposed to be securing
+	-- the data against tampering; the goal is to prevent accidents, not fraud.
 	local unpack, setmetatable = unpack, setmetatable
 	local mtnewindex = function() --[[local]]error("This table is read-only", 3) end
 	local function make_readonly (t)
@@ -1294,8 +1296,9 @@
 end
 function addon:PLAYER_LOGOUT()
 	-- Can these still fire at the very last instant?
-	self:UnregisterEvent("GROUP_ROSTER_UPDATE")
-	self:UnregisterEvent("PLAYER_ENTERING_WORLD")
+	--self:UnregisterEvent("GROUP_ROSTER_UPDATE")
+	--self:UnregisterEvent("PLAYER_ENTERING_WORLD")
+	self.LOGGING_OUT = true  -- kludge this instead
 
 	local worth_saving = #g_loot > 0 or next(g_loot.raiders)
 	if not worth_saving then for text in self:registered_textgen_iter() do
@@ -1428,6 +1431,7 @@
 	end
 
 	function addon:GROUP_ROSTER_UPDATE (event)
+		if self.LOGGING_OUT then return end
 		if not IsInRaid() then
 			if was_in_raid then
 				-- Leaving a raid group.
@@ -1614,23 +1618,48 @@
 	end
 	local recent_loot = create_new_cache ('loot', comm_cleanup_ttl+3, prefer_local_loots)
 
-	local strsplit, GetItemInfo, GetItemIcon, UnitClass = strsplit, GetItemInfo, GetItemIcon, UnitClass
-
+	local GetItemInfo, GetItemIcon, UnitClass = GetItemInfo, GetItemIcon, UnitClass
+
+	-- 'item' can be any of things passable to GetItemInfo, so we make no
+	--     assumptions but rather base all information off of returns from
+	--     GetItemInfo, including re-extracting the itemstring
+	--     (in the case of local messages, 'item' is an itemstring)
 	-- 'from' only present if this is triggered by a broadcast
-	function _do_loot (self, local_override, recipient, unique, itemid, count, from, extratext)
+	function _do_loot (self, local_override, recipient, unique, item, count, from, extratext)
+		if unique == 0 then unique = nil end
 		local prefix = "_do_loot[" .. counter() .. "]"
-		local itexture = GetItemIcon(itemid)
-		local iname, ilink, iquality = GetItemInfo(itemid)
-		local cache_miss
+
+		--[[
+			iname:		Hearthstone
+			iquality:	integer
+			ilink:		clickable formatted link
+			itemstring:	item:6948:....
+		]]
+		local cache_miss, itemid
+		local iname, ilink, iquality,
+			-- ilvl, minlvl, type, subtype, stacksize, equiploc, texture, sellprice
+			_, _, _, _, _, _, itexture = GetItemInfo(item)
+		if not itexture then
+			-- Fun fact, GetItemIcon behaves oddly on a nil argument, and may
+			-- or may not always work on a non-numerical-itemID argument
+			itemid = tonumber(item)
+			if (itemid) then
+				itexture = GetItemIcon(itemid)
+			end
+		end
 		if (not iname) or (not itexture) then
 			cache_miss = true
 			iname, ilink, iquality, itexture = 
-				UNKNOWN..': '..itemid, 'item:6948', LE_ITEM_QUALITY_COMMON, [[Interface\ICONS\INV_Misc_QuestionMark]]
+				UNKNOWN..': '..item, 'item:6948', LE_ITEM_QUALITY_COMMON,
+				[[Interface\ICONS\INV_Misc_QuestionMark]]
 		end
 		self.dprint('loot',">>"..prefix, "R:", recipient, "U:", unique, "I:",
-			itemid, "C:", count, "frm:", from, "ex:", extratext, "q:", iquality)
-
-		itemid = tonumber(ilink:match("item:(%d+)") or 0)
+			item, "C:", count, "frm:", from, "ex:", extratext,
+			"q:", iquality, "tex:", itexture)
+
+		-- Get a known-good string and integer out of the returned link.
+		local itemstring = ilink:match("item[%-?%d:]+")
+		itemid = tonumber(itemstring:match("^item:(%d+)") or 0)
 
 		-- This is only a 'while' to make jumping out of it easy.
 		local i, unique_okay, replacement, ret1, ret2
@@ -1657,7 +1686,7 @@
 			end
 
 			if (self.rebroadcast and (not from)) and not local_override then
-				self:vbroadcast('loot', recipient, unique, itemid, count)
+				self:vbroadcast('loot', recipient, unique, itemstring, count)
 			end
 			if (not self.enabled) and (not local_override) then break end
 
@@ -1703,13 +1732,14 @@
 				quality		= iquality,
 				itemname	= iname,
 				id			= itemid,
-				itemlink	= ilink,
+				itemstring	= itemstring,
+				itemlink	= ilink,  -- determines the GUI tooltip
 				itexture	= itexture,
 				unique		= replacement or unique,
 				count		= (count and count ~= "") and count or nil,
 				bcast_from	= from,
 				extratext	= extratext,
-				variant		= self:is_variant_item(ilink),
+				variant		= self:is_variant_item(itemstring),
 			}
 			if opts.itemvault[itemid] then
 				i.disposition = 'gvault'
@@ -1757,39 +1787,31 @@
 	function addon:CHAT_MSG_LOOT (event, ...)
 		if (not self.rebroadcast) and (not self.enabled) and (event ~= "manual") then return end
 
-		--[[
-			iname:		Hearthstone
-			iquality:	integer
-			ilink:		clickable formatted link
-			itemstring:	item:6948:....
-			itexture:	inventory icon texture
-		]]
-
 		if event == "CHAT_MSG_LOOT" then
 			local msg = ...
-			local person, itemstring, count
+			local person, itemlink, count
 			--ChatFrame2:AddMessage("original string:  >"..(msg:gsub("\124","\124\124")).."<")
 
 			-- test in most likely order:  other people get more loot than "you" do
-			person, itemstring, count = match(msg,g_LOOT_ITEM_MULTIPLE_sss)
+			person, itemlink, count = match(msg,g_LOOT_ITEM_MULTIPLE_sss)
 			if not person then
-				person, itemstring = match(msg,g_LOOT_ITEM_ss)
+				person, itemlink = match(msg,g_LOOT_ITEM_ss)
 			end
 			if not person then
 				-- Could only do this text if in an LFR... but the restriction
 				-- might apply elsewhere soon enough.
-				person, itemstring = match(msg,g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss)
+				person, itemlink = match(msg,g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss)
 			end
 			if not person then
-				itemstring, count = match(msg,g_LOOT_ITEM_SELF_MULTIPLE_ss)
-				if not itemstring then
-					itemstring = match(msg,g_LOOT_ITEM_SELF_s)
+				itemlink, count = match(msg,g_LOOT_ITEM_SELF_MULTIPLE_ss)
+				if not itemlink then
+					itemlink = match(msg,g_LOOT_ITEM_SELF_s)
 				end
 			end
 
-			if not itemstring then return end    -- "PlayerX selected Greed", etc, not looting
+			if not itemlink then return end    -- "PlayerX selected Greed", etc, not looting
 			self.dprint('loot', "CHAT_MSG_LOOT, person is", person,
-				", itemstring is", itemstring, ", count is", count)
+				", itemlink is", itemlink, ", count is", count)
 
 			-- Name might be colorized, remove the highlighting
 			if person then
@@ -1798,20 +1820,16 @@
 				person = my_name    -- UNIT_YOU / You
 			end
 
-			--local id = tonumber(itemstring:match('|Hitem:(%d+):'))
-			local id,unique,_
-			_,id,_,_,_,_,_,_,unique = strsplit (":", itemstring)
-			if unique == 0 then unique = nil end
-
-			return _do_loot (self, false, person, unique, id, count)
+			return _do_loot (self, --[[override=]]false, person, unique,
+				match(itemlink,"item[%-?%d:]+"), count)
 
 		elseif event == "broadcast" then
-			return _do_loot(self, false, ...)
+			return _do_loot (self, --[[override=]]false, ...)
 
 		elseif event == "manual" then
-			local r,i,n = ...
-			return _do_loot(self, true, r, --[[unique=]]nil, i,
-				--[[count=]]nil, --[[from=]]nil, n)
+			local recip,item,text = ...
+			return _do_loot (self, --[[override=]]true, recip,
+				--[[unique=]]nil, item, --[[count=]]nil, --[[from=]]nil, text)
 		end
 	end
 end
@@ -1873,6 +1891,7 @@
 				kind='boss',reason='kill',bossname="Baron Steamroller",duration=0
 			})
 			self:CHAT_MSG_LOOT ('manual', my_name, 54797)
+			self:CHAT_MSG_LOOT ('manual', my_name, 'item:109948:0:0:0:0:0:0:0:100:0:2:2:499:524')
 			if self.display then
 				self:redisplay()
 			end
@@ -2284,7 +2303,7 @@
 end
 
 do
-	local itt
+	--[[local itt
 	local function create()
 		local tip, lefts = CreateFrame("GameTooltip"), {}
 		for i = 1, 2 do -- scanning idea here also snagged from Talented
@@ -2308,6 +2327,40 @@
 		       or (t == RAID_FINDER and 2)  -- no ITEM_ for this, apparently
 		       or nil
 	end
+	]]
+	local bcodes = {
+		[448] = "Warforged",  -- and 499?
+		[449] = "Heroic",   -- 524?
+		[450] = "Mythic",
+		[451] = "LFR",
+		[15] = "Epic",
+		[171] = "Rare",
+	}
+	function addon:is_variant_item(istr)
+--flib.safeiprint(strsplit (":", istr))
+--flib.safeiprint(select (13, strsplit (":", istr)) )
+		local bonuses = { select (13, strsplit (":", istr)) }
+		if #bonuses < 1 then
+			return -- nil for no bonus
+		end
+		local n = tonumber(bonuses[1]) or 0
+		if n < 1 then
+			return -- nil for no bonus
+		end
+		--@debug@
+print("bonuses has", #bonuses, "entries, size entry is", bonuses[1], "for", istr)
+		table.remove (bonuses, 1)
+		assert (n == #bonuses, "test for variant item on " ..
+			istr .. " extracted count " .. (n or "nil?") ..
+			" but table size is " .. #bonuses)
+		for i = 1, #bonuses do
+			local b = tonumber(bonuses[i])
+print("  bonus ", b, bcodes[b])
+			bonuses[i] = b
+		end
+		--@end-debug@
+		return 42  -- will figure out meaningful value later
+	end
 end
 
 -- Called at the end of OnInit, and then also when a 'clear' is being
@@ -2838,7 +2891,8 @@
 			local msg = [[    Entry %d patched up with %s.]]
 			e.quality = iquality
 			e.itemname = iname
-			e.id = tonumber(ilink:match("item:(%d+)"))
+			e.itemstring = ilink:match("item[%-?%d:]+")
+			e.id = tonumber(e.itemstring:match("^item:(%d+)") or 0)
 			e.itemlink = ilink
 			e.itexture = itexture
 			e.cache_miss = nil
@@ -3767,7 +3821,7 @@
 
 ------ Player communication
 do
-	local select, tconcat, strsplit, unpack = select, table.concat, strsplit, unpack
+	local select, tconcat, unpack = select, table.concat, unpack
 	local function assemble(t,...)
 		local n = select('#',...)
 		if n > 0 then