changeset 2:fe437e761ef8

More safety checks for itemfilter validity. Factor out DBM callbacks into semi-generalized boss mod registration (todo: selection gui).
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 22 Apr 2011 01:34:47 +0000
parents 822b6ca3ef89
children 2753b9763882
files Ouro_Loot.toc bossmods.lua core.lua gui.lua
diffstat 4 files changed, 149 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/Ouro_Loot.toc	Sat Apr 16 06:03:29 2011 +0000
+++ b/Ouro_Loot.toc	Fri Apr 22 01:34:47 2011 +0000
@@ -3,7 +3,6 @@
 ## Version: @project-version@
 ## Notes: Raid loot tracking
 ## Author: Farmbuyer of Kilrogg
-# oldSavedVariables: sv_OLoot, sv_OLoot_hist, sv_OLoot_opts
 ## SavedVariables: OuroLootSV, OuroLootSV_opts, OuroLootSV_hist
 ## OptionalDeps: Ace3, DBM-Core, lib-st, LibFarmbuyer
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bossmods.lua	Fri Apr 22 01:34:47 2011 +0000
@@ -0,0 +1,101 @@
+local addon = select(2,...)
+
+--[[
+Here's the control flow:
+(1) This file or another addon calls :register_boss_mod("Foo",register[,unregister])
+(2) When OL decides it's time to register with a boss mod, it calls
+       register (addon, addon_do_boss)
+    which should do whatever's needed.  This may happen more than once, if OL
+    is turned on/off, etc.
+(2b) If a boss mod is already in place,
+       unregister (addon)
+    will be called first, if such a function was given at the start.
+(3) When the boss mod triggers a callback, this code should call
+       addon_do_boss (.....)
+    with the crapton of data passed as in the DBM-related code below.
+
+NOTA BENE:
+- 'register' will not be called multiple times in a row for the same boss mod.
+- The callback for (3) must check if OL is appropriately active.
+
+------ Constants
+------ Locals
+------ Deadly Boss Mods
+]]
+
+------ Constants
+
+------ Locals
+local flib = LibStub("LibFarmbuyer")
+local pprint, tabledump = addon.pprint, flib.tabledump
+
+-- Lua
+local pairs, ipairs, tinsert, tremove, tonumber = pairs, ipairs, table.insert, table.remove, tonumber
+
+-- WoW
+local GetRaidRosterInfo = GetRaidRosterInfo
+
+-- OL
+local addon_do_boss 
+
+
+------ Deadly Boss Mods
+do
+	local location
+	local function DBMBossCallback (self, reason, mod, ...)
+		if (not self.rebroadcast) and (not self.enabled) then return end
+
+		local name
+		if mod.combatInfo and mod.combatInfo.name then
+			name = mod.combatInfo.name
+		elseif mod.id then
+			name = mod.id
+		else
+			name = "Unknown Boss"
+		end
+
+		local it = location or self.instance_tag()
+		location = nil
+
+		local duration = 0
+		if mod.combatInfo and mod.combatInfo.pull then
+			duration = math.floor (GetTime() - mod.combatInfo.pull)
+		end
+
+		-- attendance:  maybe put people in groups 6,7,8 into a "backup/standby"
+		-- list?  probably too specific to guild practices.
+		local raiders = {}
+		for i = 1, GetNumRaidMembers() do
+			tinsert(raiders, (GetRaidRosterInfo(i)))
+		end
+		table.sort(raiders)
+
+		return addon_do_boss (self, reason, name, it, duration, raiders)
+	end
+
+	local function callback(...) DBMBossCallback(addon,...) end
+
+	local function _registerDBM (self, OL_boss_worker)
+		if _G.DBM then
+			local rev = tonumber(DBM.Revision) or 0
+			if rev < 1503 then
+				self.status_text = "|cffff1010Deadly Boss Mods must be version 1.26 or newer to work with Ouro Loot.|r"
+				return
+			end
+			addon_do_boss = OL_boss_worker
+			local r = _G.DBM:RegisterCallback("kill", callback)
+					  _G.DBM:RegisterCallback("wipe", callback)
+					  _G.DBM:RegisterCallback("pull", function() location = self.instance_tag() end)
+			return r > 0
+		else
+			self.status_text = "|cffff1010Ouro Loot cannot find Deadly Boss Mods, loot will not be grouped by boss.|r"
+		end
+	end
+
+	addon:register_boss_mod ("DBM", _registerDBM)
+end  -- DBM tie-ins
+
+
+-- DXE, BigWigs, etc, need to be researched for this too
+
+-- vim:noet
--- a/core.lua	Sat Apr 16 06:03:29 2011 +0000
+++ b/core.lua	Fri Apr 22 01:34:47 2011 +0000
@@ -52,6 +52,7 @@
 	['no_tracking_wipes'] = false,
 	['snarky_boss'] = true,
 	['keybinding'] = false,
+	['bossmod'] = "DBM",
 	['keybinding_text'] = 'CTRL-SHIFT-O',
 	['forum'] = {
 		['[url]'] = '[url=http://www.wowhead.com/?item=$I]$N[/url]$X - $T',
@@ -128,7 +129,9 @@
 	-- Can change 'loot' to 'item' to trigger on, e.g., extracting stuff from mail.
 	loot_pattern	= "(%S+) receives? loot:.*|cff%x+|H(.-)|h.*|r(.*)%.$"
 
-	dbm_registered	= nil
+	bossmod_registered = nil
+	bossmods = {}
+
 	requesting		= nil   -- for prompting for additional rebroadcasters
 
 	thresholds, quality_hexes = {}, {}
@@ -159,7 +162,7 @@
 local pprint, tabledump = addon.pprint, flib.tabledump
 
 -- En masse forward decls of symbols defined inside local blocks
-local _registerDBM -- break out into separate file
+local _register_bossmod
 local makedate, create_new_cache, _init
 
 -- Hypertext support, inspired by DBM broadcast pizza timers
@@ -378,8 +381,7 @@
 		if SetBindingClick(opts.keybinding_text, "OuroLootBindingOpen") then
 			SaveBindings(GetCurrentBindingSet())
 		else
-			self:Print("Error registering '%s' as a keybinding, check spelling!",
-				opts.keybinding_text)
+			self:Print("Error registering '%s' as a keybinding, check spelling!", opts.keybinding_text)
 		end
 	end
 
@@ -424,7 +426,7 @@
 		if event == "Activate" then
 			-- dispatched manually from Activate
 			self:RegisterEvent "CHAT_MSG_LOOT"
-			_registerDBM(self)
+			_register_bossmod(self)
 		elseif event == "RAID_ROSTER_UPDATE" then
 			-- event registration from onload, joined a raid, maybe show popup
 			if opts.popup_on_join and not self.popped then
@@ -638,7 +640,7 @@
 		self:RAID_ROSTER_UPDATE("Activate")
 	elseif self.debug.notraid then
 		self:RegisterEvent "CHAT_MSG_LOOT"
-		_registerDBM(self)
+		_register_bossmod(self)
 	elseif g_restore_p then
 		g_restore_p = nil
 		if #g_loot == 0 then return end -- only saved texts, not worth verbage
@@ -946,57 +948,50 @@
 		self.loot_clean = first or index-1
 	end
 
-	local GetRaidRosterInfo = GetRaidRosterInfo
-	function addon:DBMBossCallback (reason, mod, ...)
-		if (not self.rebroadcast) and (not self.enabled) then return end
+	function addon:register_boss_mod (name, registration_func, deregistration_func)
+		assert(type(name)=='string')
+		assert(type(registration_func)=='function')
+		if deregistration_func ~= nil then assert(type(deregistration_func)=='function') end
+		self.bossmods[#self.bossmods+1] = {
+			n = name,
+			r = registration_func,
+			d = deregistration_func,
+		}
+	end
 
-		local name
-		if mod.combatInfo and mod.combatInfo.name then
-			name = mod.combatInfo.name
-		elseif mod.id then
-			name = mod.id
-		else
-			name = "Unknown Boss"
+	function _register_bossmod (self, force_p)
+		local x = self.bossmod_registered and self.bossmods[self.bossmod_registered]
+		if x then
+			if x.n == opts.bossmod and not force_p then
+				-- trying to register with already-registered boss mod
+				return
+			else
+				-- deregister
+				if x.d then x.d(self) end
+			end
 		end
 
-		local it = location or instance_tag()
-		location = nil
-
-		local duration = 0
-		if mod.combatInfo and mod.combatInfo.pull then
-			duration = math.floor (GetTime() - mod.combatInfo.pull)
+		x = nil
+		for k,v in ipairs(self.bossmods) do
+			if v.n == opts.bossmod then
+				x = k
+				break
+			end
 		end
 
-		-- attendance:  maybe put people in groups 6,7,8 into a "backup/standby"
-		-- list?  probably too specific to guild practices.
-		local raiders = {}
-		for i = 1, GetNumRaidMembers() do
-			tinsert(raiders, (GetRaidRosterInfo(i)))
+		if not x then
+			self.status_text = "|cffff1010No boss-mod found!|r"
+			self:Print(self.status_text)
+			return
 		end
-		table.sort(raiders)
 
-		return _do_boss (self, reason, name, it, duration, raiders)
-	end
-
-	local callback = function(...) addon:DBMBossCallback(...) end
-	function _registerDBM(self)
-		if DBM then
-			if not self.dbm_registered then
-				local rev = tonumber(DBM.Revision) or 0
-				if rev < 1503 then
-					self.status_text = "|cffff1010Deadly Boss Mods must be version 1.26 or newer to work with Ouro Loot.|r"
-					return
-				end
-				local r = DBM:RegisterCallback("kill", callback)
-						  DBM:RegisterCallback("wipe", callback)
-						  DBM:RegisterCallback("pull", function() location = instance_tag() end)
-				self.dbm_registered = r > 0
-			end
+		if self.bossmods[x].r (self, _do_boss) then
+			self.bossmod_registered = x
 		else
-			self.status_text = "|cffff1010Ouro Loot cannot find Deadly Boss Mods, loot will not be grouped by boss.|r"
+			self:Print("|cffff1010Boss mod registration failed|r")
 		end
 	end
-end  -- DBM tie-ins
+end
 
 -- Adding entries to the loot record, and tracking the corresponding timestamp.
 do
--- a/gui.lua	Sat Apr 16 06:03:29 2011 +0000
+++ b/gui.lua	Fri Apr 22 01:34:47 2011 +0000
@@ -1384,7 +1384,9 @@
 			local list = {}
 			for id in pairs(OuroLootSV_opts.itemfilter) do
 				local iname, _, iquality = GetItemInfo(id)
-				list[id] = addon.quality_hexes[iquality] .. iname .. "|r"
+				if iname then
+					list[id] = addon.quality_hexes[iquality] .. iname .. "|r"
+				end
 			end
 			w = GUI:Create("EditBoxDropDown")
 			w:SetRelativeWidth(0.4)
@@ -1533,8 +1535,9 @@
 	display:SetTitle("Ouro Loot")
 	display:SetStatusText(self.status_text)
 	display:SetLayout("Flow")
-	display:SetStatusTable{width=800}
-	-- prevent resizing, also see ace3 ticket #80
+	display:SetStatusTable{width=900}
+	-- prevent resizing, also see ace3 tickets 80 and 214
+	-- grrrr, no longer works after frame rewrite
 	--[[
 	display.sizer_se:SetScript("OnMouseDown",nil)
 	display.sizer_se:SetScript("OnMouseUp",nil)