changeset 151:42dd3076baaf

Initial attempt at tracking bonus rolls and non-loot items. Add more loot-catching patterns, and generalize them a little more. Bonus rolls are tracked by default, non-loot stuff is not. Bonus rolls don't seem to be working, but non-loot definitely is. (It may be that the patterns for bonus rolls are not actually used by the game client, or rather, that the game client does not issue those events for bonus rolls which are not your own. I have yet to win a bonus roll since implementing the code, but one person in LFR claimed to win a bonus item which simply wasn't visible to me at all. More data needed.)
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 09 Jan 2015 19:14:56 -0500
parents 63bda09d88fe
children b79b1cb6d057
files core.lua options.lua
diffstat 2 files changed, 122 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/core.lua	Thu Jan 08 16:03:55 2015 -0500
+++ b/core.lua	Fri Jan 09 19:14:56 2015 -0500
@@ -148,6 +148,8 @@
 	['chatty_on_changes_frame'] = 1,
 	['itemfilter'] = {},
 	['itemvault'] = {},
+	['track_bonusrolls'] = true,
+	['track_nonloot'] = false,
 } }
 local virgin = "First time loaded?  Hi!  Use the /ouroloot command"
 	.." to show the main display.  You should probably browse the instructions"
@@ -182,8 +184,6 @@
 local version_large			= nil -- defaults to 1, possibly changed by version
 local timestamp_fmt_unique	= '%Y/%m/%dT%H:%M:%S'
 local timestamp_fmt_history	= '%Y/%m/%d %H:%M:%S'
-local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s
-local g_LOOT_ITEM_SELF_MULTIPLE_ss, g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss
 
 
 ------ Addon member data
@@ -401,7 +401,7 @@
 -- En masse forward decls of symbols defined inside local blocks
 local _register_bossmod, makedate, create_new_cache, _init, _log, _do_loot_metas
 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision
-local _notify_about_change, _LFR_suppressing, _add_loot_disposition
+local _notify_about_change, _LFR_suppressing, _add_loot_disposition, _grok
 
 -- Try to extract numbers from the .toc "Version" and munge them into an
 -- integral form for comparison.  The result doesn't need to be meaningful as
@@ -869,6 +869,59 @@
 	g_gui = self.gui_state_pointer
 	self.gui_state_pointer = nil
 	self.load_assert = nil
+
+	--[[
+	The loot format patterns of interest, changed into relatively tight string
+	match patterns.  Done during initialization rather than at load-time
+	against the slim chance that one of the non-US "delocalizers" needs to
+	adjust the global patterns before we transform them.
+	]]
+	local function ss (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)') end
+	local function ssd (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)') end
+	local function s (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)') end
+	local function sd (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)') end
+
+	local loot_patterns = {
+		-- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%.
+		-- LOOT_ITEM_BONUS_ROLL = "%s receives bonus loot: %s." --> (.+) receives bonus loot: (.+)%.
+		-- LOOT_ITEM_PUSHED = "%s receives item: %s." --> (.+) receives item: (.+)%.
+		['LOOT_ss'] = ss(_G.LOOT_ITEM),
+		['BONUS_ss'] = ss(_G.LOOT_ITEM_BONUS_ROLL),
+		['ITEM_ss'] = ss(_G.LOOT_ITEM_PUSHED),
+
+		-- LOOT_ITEM_MULTIPLE = "%s receives loot: %sx%d." --> (.+) receives loot: (.+)(x%d+)%.
+		-- LOOT_ITEM_BONUS_ROLL_MULTIPLE = "%s receives bonus loot: %sx%d." --> (.+) receives bonus loot: (.+)(x%d+)%.
+		-- LOOT_ITEM_PUSHED_MULTIPLE = "%s receives item: %sx%d." --> (.+) receives item: (.+)(x%d+)%.
+		['LOOT_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_MULTIPLE),
+		['BONUS_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_BONUS_ROLL_MULTIPLE),
+		['ITEM_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_PUSHED_MULTIPLE),
+
+		-- LOOT_ITEM_SELF = "You receive loot: %s." --> You receive loot: (.+)%.
+		-- LOOT_ITEM_BONUS_ROLL_SELF = "You receive bonus loot: %s." --> You receive bonus loot: (.+)%.
+		-- LOOT_ITEM_PUSHED_SELF = "You receive item: %s." --> You receive item: (.+)%.
+		['LOOT_SELF_s'] = s(_G.LOOT_ITEM_SELF),
+		['BONUS_SELF_s'] = s(_G.LOOT_ITEM_BONUS_ROLL_SELF),
+		['ITEM_SELF_s'] = s(_G.LOOT_ITEM_PUSHED_SELF),
+
+		-- LOOT_ITEM_SELF_MULTIPLE = "You receive loot: %sx%d." --> You receive loot: (.+)(x%d+)%.
+		-- LOOT_ITEM_BONUS_ROLL_SELF_MULTIPLE = "You receive bonus loot: %sx%d." --> You receive bonus loot: (.+)(x%d+)%.
+		-- LOOT_ITEM_PUSHED_SELF_MULTIPLE = "You receive item: %sx%d." --> You receive item: (.+)(x%d+)%.
+		['LOOT_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_SELF_MULTIPLE),
+		['BONUS_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_BONUS_ROLL_SELF_MULTIPLE),
+		['ITEM_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_PUSHED_SELF_MULTIPLE),
+
+		-- LOOT_ITEM_WHILE_PLAYER_INELIGIBLE is mostly the same as LOOT_ITEM with
+		-- an inline texture and no full stop.  The punctuation in the texture
+		-- path causes fits while matching, so just make that a wildcard rather
+		-- than trying to escape it all.
+		['LOOT_WHILE_PLAYER_INELIGIBLE_ss'] =
+			_G.LOOT_ITEM_WHILE_PLAYER_INELIGIBLE:gsub('\124T%S*\124t','\124T%%S*\124t'):gsub('%%s','(.+)'),
+	}
+	_grok = setfenv (_grok, loot_patterns)
+	for k,v in pairs(loot_patterns) do
+		self.dprint('loot', "Loot pattern", k, "set to", v)
+	end
+
 	self.OnInitialize = nil   -- free up ALL the things!
 end
 
@@ -966,37 +1019,6 @@
 	end
 
 	--[[
-	The five loot format patterns of interest, changed into relatively tight
-	string match patterns.  Done at enable-time rather than load-time against
-	the slim chance that one of the non-US "delocalizers" needs to mess with
-	the global patterns before we transform them.
-	
-	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.
-	]]
-
-	-- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%.
-	g_LOOT_ITEM_ss = LOOT_ITEM:gsub('%.$','%%.'):gsub('%%s','(.+)')
-
-	-- LOOT_ITEM_MULTIPLE = "%s receives loot: %sx%d." --> (.+) receives loot: (.+)(x%d+)%.
-	g_LOOT_ITEM_MULTIPLE_sss = LOOT_ITEM_MULTIPLE:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)')
-
-	-- LOOT_ITEM_SELF = "You receive loot: %s." --> You receive loot: (.+)%.
-	g_LOOT_ITEM_SELF_s = LOOT_ITEM_SELF:gsub('%.$','%%.'):gsub('%%s','(.+)')
-
-	-- LOOT_ITEM_SELF_MULTIPLE = "You receive loot: %sx%d." --> You receive loot: (.+)(x%d+)%.
-	g_LOOT_ITEM_SELF_MULTIPLE_ss = LOOT_ITEM_SELF_MULTIPLE:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)')
-
-	-- LOOT_ITEM_WHILE_PLAYER_INELIGIBLE is mostly the same as LOOT_ITEM with
-	-- an inline texture and no full stop.  The punctuation in the texture
-	-- path causes fits while matching, so just make that a wildcard rather
-	-- than trying to escape it all.
-	g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss = LOOT_ITEM_WHILE_PLAYER_INELIGIBLE:
-		gsub('\124T%S*\124t','\124T%%S*\124t'):gsub('%%s','(.+)')
-
-	--[[
 	Throw in the default disposition types.  This could be called during load
 	were it not for the need to talk to the GUI data (not set up yet).
 
@@ -1692,7 +1714,7 @@
 			end
 
 			if (self.rebroadcast and (not from)) and not local_override then
-				self:vbroadcast('loot', recipient, unique, itemstring, count)
+				self:vbroadcast('loot', recipient, unique, itemstring, count, extratext)
 			end
 			if (not self.enabled) and (not local_override) then break end
 
@@ -1784,40 +1806,64 @@
 			break
 		end
 		self.dprint('loot',"<<"..prefix, "out")
-		return ret1, ret2
+		return ret1, ret2    -- FIXME mostly garbage
+	end
+
+	local match = string.match
+	_grok = function (msg, bonus_p, item_p)
+		local person, itemlink, count, extra
+		while true do
+			extra = "loot"
+			-- test in most likely order:  other people get more loot than you do
+			person, itemlink, count = match (msg, LOOT_MULTIPLE_ssd); if person then break end
+			person, itemlink = match (msg, LOOT_ss); if person then break end
+			-- Could only do this if in an LFR... but the restriction
+			-- might apply elsewhere soon enough.
+			person, itemlink = match (msg, LOOT_WHILE_PLAYER_INELIGIBLE_ss); if person then break end
+
+			-- other people get more bonus loot than you do, too
+			if bonus_p then
+				extra = "bonus"
+				person, itemlink, count = match (msg, BONUS_MULTIPLE_ssd); if person then break end
+				person, itemlink = match (msg, BONUS_ss); if person then break end
+			end
+
+			-- i can haz cheezburgr?
+			extra = "loot"
+			itemlink, count = match (msg, LOOT_SELF_MULTIPLE_sd); if itemlink then break end
+			itemlink = match (msg, LOOT_SELF_s); if itemlink then break end
+
+			-- getting stuff out of the mailbox, the salvage boxes, etc
+			if item_p then
+				extra = "item"
+				person, itemlink, count = match (msg, ITEM_MULTIPLE_ssd); if person then break end
+				person, itemlink = match (msg, ITEM_ss); if person then break end
+				itemlink, count = match (msg, ITEM_SELF_MULTIPLE_sd); if itemlink then break end
+				itemlink = match (msg, ITEM_SELF_s); if itemlink then break end
+			end
+			break
+		end
+		return person, itemlink, count, extra
 	end
 
 	-- Returns the index of the resulting new loot entry, or nil after
 	-- displaying any errors.
-	local match = string.match
 	function addon:CHAT_MSG_LOOT (event, ...)
 		if (not self.rebroadcast) and (not self.enabled) and (event ~= "manual") then return end
 
 		if event == "CHAT_MSG_LOOT" then
 			local msg = ...
-			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, itemlink, count = match(msg,g_LOOT_ITEM_MULTIPLE_sss)
-			if not person then
-				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, itemlink = match(msg,g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss)
-			end
-			if not person then
-				itemlink, count = match(msg,g_LOOT_ITEM_SELF_MULTIPLE_ss)
-				if not itemlink then
-					itemlink = match(msg,g_LOOT_ITEM_SELF_s)
-				end
-			end
+			self.dprint('loot', "CHAT_MSG_LOOT, message is >"..(msg:gsub("\124","\124\124")).."<")
+
+			local person, itemlink, count, extra = _grok (msg, opts.track_bonusrolls, opts.track_nonloot)
 
 			if not itemlink then return end    -- "PlayerX selected Greed", etc, not looting
 			self.dprint('loot', "CHAT_MSG_LOOT, person is", person,
-				", itemlink is", itemlink, ", count is", count)
+				", itemlink is", itemlink, ", count is", count, "extra is", extra)
+			extra = (extra == "bonus") and [[Bonus roll!]] or
+				((extra == "item") and [[Non-loot]] or nil) or
+				nil
 
 			-- Name might be colorized, remove the highlighting
 			if person then
@@ -1827,7 +1873,7 @@
 			end
 
 			return _do_loot (self, --[[override=]]false, person, --[[unique=]]nil,
-				match(itemlink,"item[%-?%d:]+"), count)
+				match(itemlink,"item[%-?%d:]+"), count, --[[from=]]nil, extra)
 
 		elseif event == "broadcast" then
 			return _do_loot (self, --[[override=]]false, ...)
--- a/options.lua	Thu Jan 08 16:03:55 2015 -0500
+++ b/options.lua	Fri Jan 09 19:14:56 2015 -0500
@@ -164,6 +164,25 @@
 		[[Irreverent replacement names for boss events.  See abbreviations.lua for details.]])
 	container:AddChild(w)
 
+	-- (try to) track bonus loot
+	-- For the texture coordinates, see EncounterJournal_SetFlagIcon() and
+	-- http://wow.gamepedia.com/API_EJ_GetSectionInfo
+	w = mktoggle('track_bonusrolls', "Track loot from bonus rolls", stdw,
+		[[Track items received from spending roll tokens (e.g., Seal of Fate).]]
+		.. [[  |cff00ff00Experimental!  May only work when rebroadcast.|r]])
+	--w:SetImage([[Interface\EncounterJournal\UI-EJ-Icons]],
+		-- This is "ID 6", the interruptible lightning icon
+		--0.75, (0.75 + (1/8)), 0, 0.5)
+		-- This is "ID 7", the heroic/skull
+		--3/8, 0.5, 0, 0.5)
+	w:SetImage([[Interface\Scenarios\ScenarioIcon-Boss]])
+	container:AddChild(w)
+
+	-- track receiving arbitrary items
+	w = mktoggle('track_nonloot', "Track non-loot items", stdw,
+		[[Track items received from the mailbox, salvage bags, lockboxes...]])
+	container:AddChild(w)
+
 	-- auto-GOP mode when in LFR
 	w = mktoggle('history_suppress_LFR', "Suppress history in LFR", stdw,
 		[[Do not record anything at all in the History tab while in an LFR raid.  Changes only take effect outside of LFR.]])