All pastes #221084 Raw Edit

Stuff

public lua v1 · immutable
#221084 ·published 2006-10-25 14:31 UTC
rendered paste body
--[[Name: ParserLibRevision: $Revision: 15117 $Author(s): rophy (rophy123@gmail.com)Website: http://www.wowace.com/index.php/ParserLibDocumentation: http://www.wowace.com/index.php/ParserLibSVN: http://svn.wowace.com/root/trunk/ParserLibDescription: An embedded combat log parser, which works on all localizations.Dependencies: CompostLib (optional) or Compost-2.0 (optional).]]-----------------------------------------------------------------------------	To Get an instance of ParserLib, call this:-- 	local parser = ParserLib:GetInstance(version)-- 	where the version is the variable 'vmajor' you see here.---------------------------------------------------------------------------local vmajor, vminor = "1.1", tonumber(string.sub("$Revision: 15117 $", 12, -3))local stubvarname = "TekLibStub"local libvarname = "ParserLib"-- Check to see if an update is needed-- if not then just return out now before we do anythinglocal libobj = getglobal(libvarname)if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then return endlocal function print(msg, r, g, b)	ChatFrame1:AddMessage(string.format("<%s-%s-%s> %s", libvarname, vmajor, vminor, msg), r, g, b)end----------------------------------------------------------------------------- Embedded Library Registration Stub-- Written by Iriel <iriel@vigilance-committee.org>-- Version 0.1 - 2006-03-05-- Modified by Tekkub <tekkub@gmail.com>---------------------------------------------------------------------------local stubobj = getglobal(stubvarname)if not stubobj then	stubobj = {}	setglobal(stubvarname, stubobj)	-- Instance replacement method, replace contents of old with that of new	function stubobj:ReplaceInstance(old, new)		 for k,v in pairs(old) do old[k]=nil end		 for k,v in pairs(new) do old[k]=v end	end	-- Get a new copy of the stub	function stubobj:NewStub(name)		local newStub = {}		self:ReplaceInstance(newStub, self)		newStub.libName = name		newStub.lastVersion = ''		newStub.versions = {}		return newStub	end	-- Get instance version	function stubobj:NeedsUpgraded(vmajor, vminor)		local versionData = self.versions[vmajor]		if not versionData or versionData.minor < vminor then return true end	end	-- Get instance version	function stubobj:GetInstance(version)		if not version then version = self.lastVersion end		local versionData = self.versions[version]		if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end		return versionData.instance	end	-- Register new instance	function stubobj:Register(newInstance)		 local version,minor = newInstance:GetLibraryVersion()		 self.lastVersion = version		 local versionData = self.versions[version]		 if not versionData then				-- This one is new!				versionData = {					instance = newInstance,					minor = minor,					old = {},				}				self.versions[version] = versionData				newInstance:LibActivate(self)				return newInstance		 end		 -- This is an update		 local oldInstance = versionData.instance		 local oldList = versionData.old		 versionData.instance = newInstance		 versionData.minor = minor		 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList)		 table.insert(oldList, oldInstance)		 if not skipCopy then				for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end		 end		 return newInstance	endendif not libobj then	libobj = stubobj:NewStub(libvarname)	setglobal(libvarname, libobj)endlocal lib = {}-- Return the library's current versionfunction lib:GetLibraryVersion()	return vmajor, vminorend-- Activate a new instance of this libraryfunction lib:LibActivate(stub, oldLib, oldList)	local maj, min = self:GetLibraryVersion()	if oldLib then		local omaj, omin = oldLib:GetLibraryVersion()		----------------------------------------------------		-- ********************************************** --		-- **** Copy over any old data you need here **** --		-- ********************************************** --		----------------------------------------------------		self.frame = oldLib.frame		self:OnLoad()		if omin < 11 and oldLib.clients then			for event in pairs(oldLib.clients) do				for i in pairs(oldLib.clients[event]) do					if type(oldLib.clients[event][i]["func"]) == "string" then						oldLib.clients[event][i]["func"] = getglobal(oldLib.clients[event][i]["func"])					end				end			end		end		self.clients = oldLib.clients			else		---------------------------------------------------		-- ********************************************* --		-- **** Do any initialization you need here **** --		-- ********************************************* --		---------------------------------------------------		self:OnLoad()	end	-- nil return makes stub do object copyend------------------------------------------------	*ParserLib Public Methods*      -------------------------------------------------- Register an event to ParserLib.function lib:RegisterEvent(addonID, event, handler)	local eventExist	for i, v in pairs(self.supportedEvents) do		if v == event then			eventExist = true			break		end	end		if not eventExist then		self:Print( string.format("Event %s is not supported. (AddOnID %s)", event, addonID), 1, 0, 0 )		return	end		-- self:Print(string.format("Registering %s for addon %s.", event, addonID) );	 -- debug	if type(handler) == "string" then handler = getglobal(handler) end		-- if not handler then self:Print("nil handler from " .. addonID, 1, 0, 0) end -- debug	if self.clients[event] == nil then		self.clients[event] = {};		end		-- load pattern list & info when event is registering	self:PreLoadPatternInfo(event);		table.insert(self.clients[event], { ["id"]=addonID, ["func"]=handler } );	self.frame:RegisterEvent(event);end-- Check if you have registered an event.function lib:IsEventRegistered(addonID, event)	if self.clients[event] then		for i, v in ipairs(self.clients[event]) do			if v.id == addonID then return true end		end	endend-- Unregister an event.function lib:UnregisterEvent(addonID, event)	local empty = true			if not self.clients[event] then return end		for i, v in ipairs(self.clients[event]) do		if v.id == addonID then			-- self:Print( format("Removing %s from %s", v.id, event) )		 -- debug			table.remove(self.clients[event], i)		else			empty = false		end	end		if empty then		-- self:Print("Unregistering event " .. event) -- debug		self.frame:UnregisterEvent(event)		self.clients[event] = nil	endend-- Unregister all events.function lib:UnregisterAllEvents(addonID)	local event, index, empty;		for event in pairs(self.clients) do		empty = true;				for i, v in ipairs(self.clients[event]) do			if v.id == addonID then				-- self:Print( format("Removing %s for %s", v.id, event) ) -- debug				table.remove(self.clients[event], i)--				self.clients[event][index] = nil;			else				empty = false;			end		end				if empty then			-- self:Print("Unregistering event " .. event) -- debug			self.frame:UnregisterEvent(event);			self.clients[event] = nil;		end			end	end-- Parse custom messages, check documentation.html for more info.function lib:Deformat(text, pattern)	if not self.customPatterns then self.customPatterns = {} end			if not self.customPatterns[pattern] then		self.customPatterns[pattern] = self:Curry(pattern)	end	return self.customPatterns[pattern](text)end---------------------------------------------------------- Methods to control ParserLib behaviour ------------------------------------------------------------ Use CompostLib or not?-- Not that at 1.1-23 CompostLib no longer slows down the speed of ParserLib, --   because I found out that I was calling CompostLib:Recycle too frequently, which can be avoided.function lib:UseCompost(flag)	self.vars.noCompost = not flagend-----------------------------------------------------	*End of ParserLib Public Methods* -----------------------------------------------------------------------------------------------------	ParserLib Private Methods------------------------------------------------ ConstantsParserLib_SELF = 103ParserLib_MELEE = 112ParserLib_DAMAGESHIELD = 113-- lib.timing = true -- timer-- Stub function called by frame.OnEventlocal function ParserOnEvent() lib:OnEvent() end-- Sort the pattern so that they can be parsed in a correct sequence, will only do once for each registered event.local function PatternCompare(a, b)		local pa = getglobal(a)	local pb = getglobal(b)		if not pa then ChatFrame1:AddMessage("|cffff0000Nil pattern: ".. a.."|r") end	if not pb then ChatFrame1:AddMessage("|cffff0000Nil pattern: ".. b.."|r") end			local ca=0	for _ in string.gmatch(pa, "%%%d?%$?[sd]") do ca=ca+1 end	local cb=0	for _ in string.gmatch(pb, "%%%d?%$?[sd]") do cb=cb+1 end	pa = string.gsub(pa, "%%%d?%$?[sd]", "")		pb = string.gsub(pb, "%%%d?%$?[sd]", "")		if string.len(pa) == string.len(pb) then		return  ca < cb;	else		return string.len(pa) > string.len(pb)	end	endlocal FindString = {	[0] = function(m,p,t) return string.find(m,p), t end,	[1] = function(m,p,t) _,_,t[1] = string.find(m,p) if t[1] then return true, t else return false, t end end,	[2] = function(m,p,t) _,_,t[1],t[2] = string.find(m,p) if t[2] then return true, t else return false, t end end,	[3] = function(m,p,t) _,_,t[1],t[2],t[3] = string.find(m,p) if t[3] then return true, t else return false, t end end,	[4] = function(m,p,t) _,_,t[1],t[2],t[3],t[4] = string.find(m,p) if t[4] then return true, t else return false, t end end,	[5] = function(m,p,t) _,_,t[1],t[2],t[3],t[4],t[5] = string.find(m,p) if t[5] then return true, t else return false, t end end,	[6] = function(m,p,t) _,_,t[1],t[2],t[3],t[4],t[5],t[6] = string.find(m,p) if t[6] then return true, t else return false, t end end,	[7] = function(m,p,t) _,_,t[1],t[2],t[3],t[4],t[5],t[6],t[7] = string.find(m,p) if t[7] then return true, t else return false, t end end,	[8] = function(m,p,t) _,_,t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8] = string.find(m,p) if t[8] then return true, t else return false, t end end,	[9] = function(m,p,t) _,_,t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9] = string.find(m,p) if t[9] then return true, t else return false, t end end,}-- Currently supported event list.lib.supportedEvents = {	"CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS",	"CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES",	"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS",	"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES",	"CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS",	"CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES",	"CHAT_MSG_COMBAT_FACTION_CHANGE",	"CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",	"CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES",	"CHAT_MSG_COMBAT_FRIENDLY_DEATH",	"CHAT_MSG_COMBAT_HONOR_GAIN",	"CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS",	"CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES",	"CHAT_MSG_COMBAT_HOSTILE_DEATH",	"CHAT_MSG_COMBAT_PARTY_HITS",	"CHAT_MSG_COMBAT_PARTY_MISSES",	"CHAT_MSG_COMBAT_PET_HITS",	"CHAT_MSG_COMBAT_PET_MISSES",	"CHAT_MSG_COMBAT_SELF_HITS",	"CHAT_MSG_COMBAT_SELF_MISSES",	"CHAT_MSG_COMBAT_XP_GAIN",	"CHAT_MSG_SPELL_AURA_GONE_OTHER",	"CHAT_MSG_SPELL_AURA_GONE_SELF",	"CHAT_MSG_SPELL_AURA_GONE_PARTY",	"CHAT_MSG_SPELL_BREAK_AURA",	"CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF",	"CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE",	"CHAT_MSG_SPELL_CREATURE_VS_PARTY_BUFF",	"CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE",	"CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF",	"CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE",	"CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS",	"CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF",	"CHAT_MSG_SPELL_FAILED_LOCALPLAYER",	"CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF",	"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",	"CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF",	"CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE",	"CHAT_MSG_SPELL_ITEM_ENCHANTMENTS",	"CHAT_MSG_SPELL_PARTY_BUFF",	"CHAT_MSG_SPELL_PARTY_DAMAGE",	"CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS",	"CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE",	"CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS",	"CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE",	"CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS",	"CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE",	"CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS",	"CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE",	"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS",	"CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE",	"CHAT_MSG_SPELL_PET_BUFF",	"CHAT_MSG_SPELL_PET_DAMAGE",	"CHAT_MSG_SPELL_SELF_BUFF",	"CHAT_MSG_SPELL_SELF_DAMAGE",	"CHAT_MSG_SPELL_TRADESKILLS",}function lib:GetCompost()	if self.vars.noCompost then			if not self.myCompost then			self.myCompost = {				Recycle = function() return {} end,				Acquire = function() return {} end,				Reclaim = function() end,			}							end		return self.myCompost	else			if not self.compost then			if AceLibrary and AceLibrary:HasInstance("Compost-2.0") then				self.compost = AceLibrary:GetInstance("Compost-2.0")			elseif CompostLib then				self.compost = CompostLib:GetInstance("compost-1")			else				-- Cannot find the existance of CompostLib				self.vars.noCompost = true				return self:GetCompost()			end					end		return self.compost	end	end-- Convert "%s hits %s for %d." to "(.+) hits (.+) for (%d+)."-- Will additionaly return the sequence of tokens, for example:	                    --  "%2$s reflects %3$d %4$s damage to %1$s."   will return: --    "(.-) reflects (%+) (.-) damage to (.-)%.",  4 1 2 3. --  (    [1]=2,[2]=3,[3]=4,[4]=1  Reverting indexes and become  [1]=4, [2]=[1],[3]=2,[4]=3. )function lib:ConvertPattern(pattern, anchor)	local seq	-- Add % to escape all magic characters used in LUA pattern matching, except $ and %	pattern = string.gsub(pattern,"([%^%(%)%.%[%]%*%+%-%?])","%%%1");		-- Do these AFTER escaping the magic characters.	pattern = string.gsub(pattern,"%%s","(.-)"); -- %s to (.-)	pattern = string.gsub(pattern,"%%d","(%-?%%d+)"); -- %d to (%d+)				if string.find(pattern,"%$") then		seq = {}; -- fills with ordered list of $s as they appear		local idx = 1; -- incremental index into field[]		local tmpSeq = {}		for i in string.gmatch(pattern,"%%(%d)%$.") do			tmpSeq[idx] = tonumber(i);			idx = idx + 1		end		for i, j in ipairs(tmpSeq) do			seq[j] = i		end		table.setn(seq, table.getn(tmpSeq))		pattern = string.gsub(pattern,"%%%d%$s","(.-)"); -- %1$s to (.-)		pattern = string.gsub(pattern,"%%%d%$d","(%-?%%d+)"); -- %1$d to (%d+)	end	-- Escape $ now.	pattern = string.gsub(pattern,"%$","%%$");	-- Anchor tag can improve string.find() performance by 100%.	if anchor then pattern = "^"..pattern end			-- If the pattern ends with (.-), replace it with (.+), or the capsule will be lost.	if string.sub(pattern, -4) == "(.-)" then		pattern = string.sub(pattern, 0, -5) .. "(.+)";	end		if not seq then return pattern end		return pattern, seq[1], seq[2], seq[3], seq[4], seq[5], seq[6], seq[7], seq[8], seq[9], seq[10]endfunction lib:OnLoad()	-- Both table starts out empty, and load the data only when required.	self.eventTable = {}	self.patternTable = {}			self.vars = {}		if self.timing then		self.timer = {			ParseMessage_LoadPatternList = 0,			ParseMessage_FindPattern = 0,			ParseMessage_FindPattern_Regexp = 0,			ParseMessage_FindPattern_Regexp_FindString = 0,			ParseMessage_FindPattern_LoadPatternInfo = 0,						ParseMessage_ParseInformation = 0,			ParseMessage_ParseTrailers = 0,			ParseMessage_ConvertTypes = 0,			NotifyClients = 0,			Compost_Acquire = 0,			Compost_Recycle = 0,			Compost_Reclaim = 0,		}	end	if not self.clients then self.clients = {} end		if not self.frame then		self.frame = CreateFrame("FRAME", "ParserLibFrame")		self.frame:SetScript("OnEvent", ParserOnEvent )		self.frame:Hide()	end		end	function lib:OnEvent(e, a1)	if not e then e = event end	if not a1 then a1 = arg1 end	-- self:Print("Event: |cff3333ff"..e.."|r") -- debug		-- Titan Honor+ was changing the global events... just change it back.	if e == "CHAT_MSG_HONORPLUS" then e = "CHAT_MSG_COMBAT_HONOR_GAIN" end		if self:ParseMessage(a1, e) then		-- 		local timer = GetTime() -- timer		self:NotifyClients(e)-- 		self.timer.NotifyClients = self.timer.NotifyClients + GetTime() - timer -- timer					end	endfunction lib:NotifyClients(event)	if not self.clients or not self.clients[event] then 		-- self:Print(event .. " has no client to notify.") -- debug		return 	end		-- Noneed to recycle the table if there is only one client.	if table.getn(self.clients[event]) == 1 then		-- self:Print(event .. ", calling " .. self.clients[event][1].id) -- debug		self.clients[event][1].func(event, self.info)		return	end-- 	local timer = GetTime() -- timer	local info = self:GetCompost():Acquire()	-- 	self.timer.Compost_Acquire = GetTime() - timer + self.timer.Compost_Acquire -- timer	for i, client in ipairs(self.clients[event]) do		-- self:Print(event .. ", calling " .. client.id) -- debug						-- I can just do a compost:Recycle() here, but I hope this can improve the performance.		for j in ipairs(info) do if not self.info[j] then info[j] = nil end end		for j, v in ipairs(self.info) do info[j] = v end				client.func(event, info)	end	-- 	timer = GetTime() -- timer	self:GetCompost():Reclaim(info)-- 	self.timer.reclaim = GetTime() - timer + self.timer.reclaim -- timerendlib.Print = print-- load pattern list & infofunction lib:PreLoadPatternInfo(event)	if not event then return end		if not self.eventTable[event] then self.eventTable[event] = self:LoadPatternList(event) end	local list = self.eventTable[event]	if list then		for i, v in ipairs(list) do			if not self.patternTable[v] then self.patternTable[v] = self:LoadPatternInfo(v) end		end	endend-- message : the arg1 in the event-- event : name says it all.-- info : the table which will store the passed result, so THIS IS THE OUTPUT.-- return : true if pattern found and parsed, nil otherwise.function lib:ParseMessage(message, event)-- --	local currTime -- timer	-- 	currTime = GetTime() -- timer	if not self.eventTable[event] then self.eventTable[event] = self:LoadPatternList(event) end -- loaded by registering already	local list = self.eventTable[event]-- 	self.timer.ParseMessage_LoadPatternList = self.timer.ParseMessage_LoadPatternList + GetTime() - currTime -- timer		if not list then return end	-- Get the table to store parsed results.	if not self.info then -- 		timer = GetTime() -- timer		self.info = self:GetCompost():Acquire() -- 		self.timer.Compost_Acquire = GetTime() - timer + self.timer.Compost_Acquire -- timer	else -- 		timer = GetTime() -- timer		self.info = self:GetCompost():Recycle(self.info) -- 		self.timer.Compost_Recycle = GetTime() - timer + self.timer.Compost_Recycle -- timer	end	-- 	currTime = GetTime() -- timer	local pattern = self:FindPattern(message, list)-- 	self.timer.ParseMessage_FindPattern = GetTime() - currTime + self.timer.ParseMessage_FindPattern -- timer		if not pattern then 		-- create "unknown" event type.		self.info.type = "unknown"		self.info.message = message				return true	end	-- 	currTime = GetTime() -- timer	self:ParseInformation(pattern)-- 	self.timer.ParseMessage_ParseInformation = GetTime() - currTime + self.timer.ParseMessage_ParseInformation -- timer		-- 	currTime = GetTime() -- timer	if self.info.type == "hit" or self.info.type == "environment" then		self:ParseTrailers(message)	end-- 	self.timer.ParseMessage_ParseTrailers = GetTime() - currTime + self.timer.ParseMessage_ParseTrailers -- timer	-- 	currTime = GetTime() -- timer	self:ConvertTypes(self.info)-- 	self.timer.ParseMessage_ConvertTypes = GetTime() - currTime + self.timer.ParseMessage_ConvertTypes -- timer	return true	end-- Search for pattern in 'patternList' which matches 'message', parsed tokens will be stored in table self.infofunction lib:FindPattern(message, patternList)		local pt, timer, found	for i, v in ipairs(patternList) do	-- 		timer = GetTime() -- timer		if not self.patternTable[v] then self.patternTable[v] = self:LoadPatternInfo(v) end -- loaded by registering already-- 		self.timer.ParseMessage_FindPattern_LoadPatternInfo = GetTime() - timer + self.timer.ParseMessage_FindPattern_LoadPatternInfo -- timer				pt = self.patternTable[v]				found = false		if not pt then return end -- check patternTable		-- 		timer = GetTime() -- timer		if self:OptimizerCheck(message, v) then-- 			timer = GetTime() -- timer			found, self.info = FindString[pt.tc](message, pt.pattern, self.info)-- 			self.timer.ParseMessage_FindPattern_Regexp_FindString = GetTime() - timer + self.timer.ParseMessage_FindPattern_Regexp_FindString -- timer		end-- 		self.timer.ParseMessage_FindPattern_Regexp = GetTime() - timer + self.timer.ParseMessage_FindPattern_Regexp -- timer				if found then 			-- self:Print(message.." = " .. v .. ":" .. pt.pattern)  -- debug			return v			end	end		end-- Parses for trailors.function lib:ParseTrailers(message)	local found, amount, info		info = self.info			if not self.trailers then 		self.trailers = {			CRUSHING_TRAILER = self:ConvertPattern(CRUSHING_TRAILER),			GLANCING_TRAILER = self:ConvertPattern(GLANCING_TRAILER),			ABSORB_TRAILER = self:ConvertPattern(ABSORB_TRAILER),			BLOCK_TRAILER = self:ConvertPattern(BLOCK_TRAILER),			RESIST_TRAILER = self:ConvertPattern(RESIST_TRAILER),			VULNERABLE_TRAILER = self:ConvertPattern(VULNERABLE_TRAILER),		}	end		found = string.find(message, self.trailers.CRUSHING_TRAILER)	if found then 		info.isCrushing = true	end	found = string.find(message, self.trailers.GLANCING_TRAILER)	if found then 		info.isGlancing = true	end	found, _, amount = string.find(message, self.trailers.ABSORB_TRAILER)	if found then 		info.amountAbsorb = amount	end	found, _, amount = string.find(message, self.trailers.BLOCK_TRAILER)	if found then 		info.amountBlock = amount	end	found, _, amount = string.find(message, self.trailers.RESIST_TRAILER)	if found then 		info.amountResist = amount	end	found, _, amount = string.find(message, self.trailers.VULNERABLE_TRAILER)	if found then 		info.amountVulnerable = amount	endendfunction lib:ParseInformation(patternName)	local patternInfo = self.patternTable[patternName]	local info = self.info	-- Create an info table from pattern table, copies everything except the pattern string.		for i, v in ipairs(patternInfo) do		if i == 1 then			info.type = v		elseif type(i) == "number" then			if type(v) == "number" and v < 100 then				info[ self:GetInfoFieldName( self.patternTable[patternName][1], i) ] = info[v]			else				info[ self:GetInfoFieldName( self.patternTable[patternName][1], i) ] = v			end		end	end	if info.type == "honor" and not info.amount then		info.isDishonor = true		elseif info.type == "durability" and not info.item  then		info.isAllItems = true	end	for i in ipairs(info) do		info[i] = nil	end	endfunction lib:ConvertTypes(info)	for i in pairs(info) do		if string.find(i, "^amount") then info[i] = tonumber(info[i]) end	endendfunction lib:OptimizerCheck(message, patternName)	--if 1 then return true end	if not ParserLibOptimizer then return true end		if not ParserLibOptimizer[patternName] then return true end		if string.find(message, ParserLibOptimizer[patternName], 1, true) then return true end		return falseend-- Most of the parts were learnt from BabbleLib by chknight, so credits goes to him.function lib:Curry(pattern)	local cp, tt, n, f, o	local DoNothing = function(tok) return tok end			tt = {}	for tk in string.gmatch(pattern, "%%%d?%$?([sd])") do		table.insert(tt, tk)	end			cp = { self:ConvertPattern(pattern, true) }	cp.p = cp[1]		n = table.getn(cp)	for i=1,n-1 do		cp[i] = cp[i+1]	end	table.remove(cp, n)		f = {}	o = {}	n = table.getn(tt)	for i=1, n do		if tt[i] == "s" then			f[i] = DoNothing		else			f[i] = tonumber		end	end	if not cp[1] then		if n == 0 then			return function() end		elseif n == 1 then			return function(text)				_, _, o[1] = string.find(text, cp.p)				if o[1] then					return f[1](o[1])				end			end		elseif n == 2 then			return function(text)				_, _, o[1], o[2]= string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2])				end			end		elseif n == 3 then			return function(text)				_, _, o[1], o[2], o[3] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3])				end			end		elseif n == 4 then			return function(text)				_, _, o[1], o[2], o[3], o[4] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4])				end			end		elseif n == 5 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4]), f[5](o[5])				end			end		elseif n == 6 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4]), f[5](o[5]), f[6](o[6])				end			end		elseif n == 7 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4]), f[5](o[5]), f[6](o[6]), f[7](o[7])				end			end		elseif n == 8 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4]), f[5](o[5]), f[6](o[6]), f[7](o[7]), f[8](o[8])				end			end		elseif n == 9 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8], o[9] = string.find(text, cp.p)				if o[1] then					return f[1](o[1]), f[2](o[2]), f[3](o[3]), f[4](o[4]), f[5](o[5]), f[6](o[6]), f[7](o[7]), f[8](o[8]), f[9](o[9])				end			end		end	else			if n == 0 then			return function() end		elseif n == 1 then			return function(text)				_, _, o[1] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]])				end			end				elseif n == 2 then			return function(text)				_, _, o[1], o[2] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]])				end			end				elseif n == 3 then			return function(text)				_, _, o[1], o[2], o[3] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]])				end			end				elseif n == 4 then			return function(text)				_, _, o[1], o[2], o[3], o[4] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]])				end			end				elseif n == 5 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]]), f[cp[5]](o[cp[5]])				end			end				elseif n == 6 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]]), f[cp[5]](o[cp[5]]), f[cp[6]](o[cp[6]])				end			end				elseif n == 7 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]]), f[cp[5]](o[cp[5]]), f[cp[6]](o[cp[6]]), f[cp[7]](o[cp[7]])				end			end				elseif n == 8 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]]), f[cp[5]](o[cp[5]]), f[cp[6]](o[cp[6]]), f[cp[7]](o[cp[7]]), f[cp[8]](o[cp[8]])				end			end				elseif n == 9 then			return function(text)				_, _, o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8], o[9] = string.find(text, cp.p)				if o[1] then					return f[cp[1]](o[cp[1]]), f[cp[2]](o[cp[2]]), f[cp[3]](o[cp[3]]), f[cp[4]](o[cp[4]]), f[cp[5]](o[cp[5]]), f[cp[6]](o[cp[6]]), f[cp[7]](o[cp[7]]), f[cp[8]](o[cp[8]]), f[cp[9]](o[cp[9]])				end			end				end			endendfunction lib:PrintTable(args)	for k, v in pairs(args) do		ChatFrame1:AddMessage(tostring(k) .. " = " .. tostring(v));	end	ChatFrame1:AddMessage("");end-- Used to test the correcteness of ParserLib on different languages.function lib:TestPatterns(sendToClients)			self:LoadEverything()		-- Creating the combat messages.		local testNumber = 123	local message	local messages = self:GetCompost():Acquire()	for patternName in pairs(self.patternTable) do		messages[patternName] = self:GetCompost():Acquire()		messages[patternName].message = getglobal(patternName)		for i, v in ipairs(self.patternTable[patternName]) do			if i ~= "tc" and type(v) == "number" and v < 100 and i~=1 then				messages[patternName][v] =  self:GetInfoFieldName(self.patternTable[patternName][1], i)			end		end		for i, v in ipairs(messages[patternName]) do			if string.find(v, "^amount") then				messages[patternName].message = string.gsub(messages[patternName].message, "%%%d?%$?d", testNumber, 1)			else				messages[patternName].message = string.gsub(messages[patternName].message, "%%%d?%$?s", string.upper(v), 1)			end		end	end		-- Begin the test.		local info, msg	local startTime = GetTime() 	local startMem = gcinfo()		for _, event in pairs(self.supportedEvents) do		for _, pattern in pairs(self:LoadPatternList(event)) do			msg = messages[pattern].message			if sendToClients then self:OnEvent(event, msg)	end			if self:ParseMessage(msg, event) then				info = self.info				for i, v in ipairs(messages[pattern]) do					if not info[v] 					or ( string.find(v, "^amount") and info[v] ~= testNumber ) 					or ( not string.find(v, "^amount") and info[v] ~= string.upper(v) ) then						self:Print("Event: " .. event)						self:Print("Pattern: " .. pattern)						self:Print("Message: " .. msg)						self:PrintTable(messages[pattern])						self:PrintTable(info)					end				end			end		end	end	self:Print( string.format("Test completed in %.4fs, memory cost %.2fKB.", GetTime() - startTime, gcinfo() - startMem) )	self:GetCompost():Reclaim(messages, 1)	endfunction lib:LoadEverything()	-- Load all patterns and events.	for _, v in pairs(self.supportedEvents) do		for _, w in pairs(self:LoadPatternList(v)) do			if not self.patternTable[w] then				self.patternTable[w] = self:LoadPatternInfo(w)			end		end	end	endfunction lib:PrintTimers()	if not self.timer then return end	local total = 0	for i in ipairs(self.timer) do		total = total + self.timer[i]	end	if not self.timerIndex then 		self.timerIndex = {}		for i in pairs(self.timer) do			table.insert(self.timerIndex, i)		end		table.sort(self.timerIndex)	end	DEFAULT_CHAT_FRAME:AddMessage("Time\t%\tDescription")	for i, idx in ipairs(self.timerIndex) do		DEFAULT_CHAT_FRAME:AddMessage(string.format("%.3f\t%.1f\t%s", self.timer[idx], 100*self.timer[idx]/total, idx) )	end			DEFAULT_CHAT_FRAME:AddMessage(total .. "\t100\tTotal")end-- Used to load eventTable elements on demand.function lib:LoadPatternList(eventName)	local list	--------------- Melee Hits ----------------		if eventName == "CHAT_MSG_COMBAT_SELF_HITS" then					if not self.eventTable["CHAT_MSG_COMBAT_SELF_HITS"] then						self.eventTable["CHAT_MSG_COMBAT_SELF_HITS"] = 				self:LoadPatternCategoryTree(				{					"HitSelf",					"EnvSelf",				}			)					end		list = self.eventTable["CHAT_MSG_COMBAT_SELF_HITS"] 			elseif eventName == "CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS" 	or eventName == "CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS" 	or eventName == "CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS" 	or eventName == "CHAT_MSG_COMBAT_PARTY_HITS" 	or eventName == "CHAT_MSG_COMBAT_PET_HITS" then		if not self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS"] then 			self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS"] = 				self:LoadPatternCategoryTree( {					"HitOtherOther",					"EnvOther",				} )		end		list = self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS"]			elseif eventName == "CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS" 	or eventName == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS"  then		if not self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS"] then 			self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS"] = 				self:LoadPatternCategoryTree( {					{						"HitOtherOther",						"HitOtherSelf",					},					"EnvOther",				} )		end		list = self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS"]	--------------- Melee Misses ----------------				elseif eventName == "CHAT_MSG_COMBAT_SELF_MISSES" then		if not self.eventTable["CHAT_MSG_COMBAT_SELF_MISSES"] then			self.eventTable["CHAT_MSG_COMBAT_SELF_MISSES"] = 				self:LoadPatternCategoryTree( {					"MissSelf",				} )		end		list = self.eventTable["CHAT_MSG_COMBAT_SELF_MISSES"]			elseif eventName == "CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES"	or eventName == "CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES"	or eventName == "CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES"	or eventName == "CHAT_MSG_COMBAT_PARTY_MISSES"	or eventName == "CHAT_MSG_COMBAT_PET_MISSES" then		if not self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES"] then			self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES"] = 			self:LoadPatternCategoryTree( {					"MissOtherOther",			} )		end		list = self.eventTable["CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES"]				elseif eventName == "CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES"	or eventName == "CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES" then		if not self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES"] then			self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES"] = 			self:LoadPatternCategoryTree( {				{					"MissOtherOther",					"MissOtherSelf",				}			} )		end		list = self.eventTable["CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES"]			--------------- Spell Buffs ----------------		elseif eventName == "CHAT_MSG_SPELL_SELF_BUFF" then		if not self.eventTable["CHAT_MSG_SPELL_SELF_BUFF"] then					if GetLocale() ~= "deDE"  then			self.eventTable["CHAT_MSG_SPELL_SELF_BUFF"] =  self:LoadPatternCategoryTree(				{					"HealSelf",					"EnchantSelf",					"CastSelf",					"PerformSelf",					"DispelFailSelf",					"SPELLCASTSELFSTART",					"SPELLPERFORMSELFSTART",					{						"DrainSelf",						"PowerGainSelf",						"ExtraAttackSelf",					},					"SPELLSPLITDAMAGESELFOTHER",					{						"ProcResistSelf",						"SpellMissSelf",					}				}			)			else			self.eventTable["CHAT_MSG_SPELL_SELF_BUFF"] =  self:LoadPatternCategoryTree(				{					"HealSelf",					"CastSelf",					"PerformSelf",					"DispelFailSelf",					"SPELLCASTSELFSTART",					"SPELLPERFORMSELFSTART",					{						"DrainSelf",						"PowerGainSelf",						"ExtraAttackSelf",					},					"SPELLSPLITDAMAGESELFOTHER",					{						"ProcResistSelf",						"SpellMissSelf",					}				}			)			end		end				list = self.eventTable["CHAT_MSG_SPELL_SELF_BUFF"]			elseif eventName == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF"	or eventName == "CHAT_MSG_SPELL_CREATURE_VS_PARTY_BUFF"  	or eventName == "CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF"  	or eventName == "CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF"  	or eventName == "CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF" 	or eventName == "CHAT_MSG_SPELL_PARTY_BUFF" 	or eventName == "CHAT_MSG_SPELL_PET_BUFF" then			if not self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"] then					if GetLocale() ~= "deDE"  then				self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"] = self:LoadPatternCategoryTree(					{						{							"HealOther",							"PowerGainOther",							"ExtraAttackOther",							"DrainOther",						},						"SPELLCASTOTHERSTART",						{							"EnchantOther",							"CastOther",							"PerformOther",						},						"SPELLPERFORMOTHERSTART",						"SpellMissOther",						"ProcResistOther",						"SplitDamageOther",						"DispelFailOther",					}				)			else -- Remove "EnchantOther" from German, since it's 100% ambiguous with SIMPLECASTOTHEROTHER, which is unsolvable.				self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"] = self:LoadPatternCategoryTree(					{						{							"HealOther",							"PowerGainOther",							"ExtraAttackOther",							"DrainOther",						},						"SPELLCASTOTHERSTART",						{							"CastOther",							"PerformOther",						},						"SPELLPERFORMOTHERSTART",						"SpellMissOther",						"ProcResistOther",						"SplitDamageOther",						"DispelFailOther",					}				)			end		end				list = self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"]--------------- Spell Damages ----------------				elseif eventName == "CHAT_MSG_SPELL_SELF_DAMAGE" then			if not self.eventTable["CHAT_MSG_SPELL_SELF_DAMAGE"] then			self.eventTable["CHAT_MSG_SPELL_SELF_DAMAGE"] = 				self:LoadPatternCategoryTree( {					"SpellHitSelf",					{						"CastSelf",						"DurabilityDamageSelf",					},					"PerformSelf",					"SpellMissSelf",					"SPELLCASTSELFSTART",					"SPELLPERFORMSELFSTART",					"InterruptSelf",					"DispelFailSelf",					"ExtraAttackSelf",					"DrainSelf",									} )		end				list = self.eventTable["CHAT_MSG_SPELL_SELF_DAMAGE"]		elseif eventName == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE" 	or eventName == "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE"  	or eventName == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE"  	or eventName == "CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE"  	or eventName == "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE" 	or eventName == "CHAT_MSG_SPELL_PARTY_DAMAGE"  	or eventName == "CHAT_MSG_SPELL_PET_DAMAGE"  then		if not self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE"] then			self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE"] = 				self:LoadPatternCategoryTree( {					"SpellHitOther",					"SPELLCASTOTHERSTART",					"SPELLPERFORMOTHERSTART",					"DrainOther",					"SpellMissOther",					{						"INSTAKILLOTHER",						"INSTAKILLSELF",					},					{						"PROCRESISTOTHEROTHER",						"PROCRESISTOTHERSELF",					},					"SplitDamageOther",					{						"CastOther",						"InterruptOther",						"DurabilityDamageOther",					},					"PerformOther",					"ExtraAttackOther",					{						"DISPELFAILEDOTHEROTHER",						"DISPELFAILEDOTHERSELF",											},				})		end		list = self.eventTable["CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE"]			--------------- Periodic Buffs ----------------				elseif eventName == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" then			if not self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"] then					self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"] = 				self:LoadPatternCategoryTree( {					{						"HotOther",						"HotSelf",					},					{						"BuffSelf",						"BuffOther",						"PowerGainOther",						"PowerGainSelf",					},					"DrainSelf",					"DotSelf",	-- Don't think this will hapen but add it anyway.				} )		end				list = self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"]		elseif eventName == "CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS"	or eventName == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS"	or eventName == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS"	or eventName == "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS" then				if not self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS"] then			self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS"] = 				self:LoadPatternCategoryTree( {					{						"HotOther",--						"DrainOther",	-- Dont think this would happen but add it anyway.					},					{						"BuffOther",						"PowerGainOther",						"DrainOther",	-- When other players use Skull of Impending Doom.					},					"DotOther",	-- Dont think this will happen but add anyway.					"DebuffOther", -- Was fired on older WoW version.				} )		end				list = self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS"]		--------------- Periodic Damages ----------------				elseif eventName == "CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE" then		if not self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE"] then					self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE"] = 				self:LoadPatternCategoryTree( {					{						"DotSelf",						"DotOther",					},					{						"DebuffSelf",						"DebuffOther",					},					{						"SPELLLOGABSORBOTHEROTHER",						"SPELLLOGABSORBOTHERSELF",						"SPELLLOGABSORBSELFSELF",						"SPELLLOGABSORBSELFOTHER",					},					"DrainSelf",				}	)		end			list = self.eventTable["CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE"]						elseif eventName == "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE"	or eventName == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE"	or eventName == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"	or eventName == "CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE" then			if not self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"] then			self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"] = 				self:LoadPatternCategoryTree( {					"DebuffOther",					"DotOther",					{						"SPELLLOGABSORBOTHEROTHER",						"SPELLLOGABSORBSELFOTHER",					},										"DrainOther",					{						"PowerGainOther",						"BuffOther", -- Was fired on older WoW version.										}				} )		end					list = self.eventTable["CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE"]--------------- Damage Shields ----------------						elseif eventName == "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF" then		if not self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF"] then			self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF"] = {				"SPELLRESISTOTHEROTHER",				"SPELLRESISTSELFOTHER",				"DAMAGESHIELDOTHEROTHER",				"DAMAGESHIELDSELFOTHER",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF"] , PatternCompare)		end		list = self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF"]				elseif eventName == "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS" then		if not self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS"] then			self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS"] = {				"SPELLRESISTOTHEROTHER",				"SPELLRESISTOTHERSELF",				"DAMAGESHIELDOTHEROTHER",				"DAMAGESHIELDOTHERSELF",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS"]						--------------- Auras ----------------		elseif eventName == "CHAT_MSG_SPELL_AURA_GONE_PARTY"	or eventName == "CHAT_MSG_SPELL_AURA_GONE_OTHER" then			if not self.eventTable["CHAT_MSG_SPELL_AURA_GONE_OTHER"] then			self.eventTable["CHAT_MSG_SPELL_AURA_GONE_OTHER"] = {				"AURAREMOVEDOTHER",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_AURA_GONE_OTHER"] , PatternCompare)		end		list = self.eventTable["CHAT_MSG_SPELL_AURA_GONE_OTHER"]		elseif  eventName == "CHAT_MSG_SPELL_AURA_GONE_SELF" then			if not self.eventTable["CHAT_MSG_SPELL_AURA_GONE_SELF"] then			self.eventTable["CHAT_MSG_SPELL_AURA_GONE_SELF"] = {				"AURAREMOVEDOTHER",				"AURAREMOVEDSELF",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_AURA_GONE_SELF"] , PatternCompare)		end		list = self.eventTable["CHAT_MSG_SPELL_AURA_GONE_SELF"]			elseif eventName == "CHAT_MSG_SPELL_BREAK_AURA" then			if not self.eventTable["CHAT_MSG_SPELL_BREAK_AURA"] then			self.eventTable["CHAT_MSG_SPELL_BREAK_AURA"] = {				"AURADISPELSELF",				"AURADISPELOTHER",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_BREAK_AURA"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_SPELL_BREAK_AURA"]										elseif eventName == "CHAT_MSG_SPELL_ITEM_ENCHANTMENTS" then			if not self.eventTable["CHAT_MSG_SPELL_ITEM_ENCHANTMENTS"] then			self.eventTable["CHAT_MSG_SPELL_ITEM_ENCHANTMENTS"] = {				"ITEMENCHANTMENTADDSELFSELF",				"ITEMENCHANTMENTADDSELFOTHER",				"ITEMENCHANTMENTADDOTHEROTHER",				"ITEMENCHANTMENTADDOTHERSELF",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_ITEM_ENCHANTMENTS"] , PatternCompare)		end					list = self.eventTable["CHAT_MSG_SPELL_ITEM_ENCHANTMENTS"]	--------------- Trade Skills ----------------				elseif eventName == "CHAT_MSG_SPELL_TRADESKILLS" then		if not self.eventTable["CHAT_MSG_SPELL_TRADESKILLS"] then			self.eventTable["CHAT_MSG_SPELL_TRADESKILLS"] = {				"TRADESKILL_LOG_FIRSTPERSON",				"TRADESKILL_LOG_THIRDPERSON",				"FEEDPET_LOG_FIRSTPERSON",				"FEEDPET_LOG_THIRDPERSON",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_TRADESKILLS"], PatternCompare )		end				list = self.eventTable["CHAT_MSG_SPELL_TRADESKILLS"]				elseif eventName == "CHAT_MSG_SPELL_FAILED_LOCALPLAYER" then			if not self.eventTable["CHAT_MSG_SPELL_FAILED_LOCALPLAYER"] then			self.eventTable["CHAT_MSG_SPELL_FAILED_LOCALPLAYER"] = {				"SPELLFAILPERFORMSELF",				"SPELLFAILCASTSELF",			}			table.sort(self.eventTable["CHAT_MSG_SPELL_FAILED_LOCALPLAYER"], PatternCompare)		end				list = self.eventTable["CHAT_MSG_SPELL_FAILED_LOCALPLAYER"] 						elseif eventName == "CHAT_MSG_COMBAT_FACTION_CHANGE" then			if not self.eventTable["CHAT_MSG_COMBAT_FACTION_CHANGE"] then					self.eventTable["CHAT_MSG_COMBAT_FACTION_CHANGE"] = {				"FACTION_STANDING_CHANGED",				"FACTION_STANDING_DECREASED",				"FACTION_STANDING_INCREASED",			}			table.sort(self.eventTable["CHAT_MSG_COMBAT_FACTION_CHANGE"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_COMBAT_FACTION_CHANGE"]			elseif eventName == "CHAT_MSG_COMBAT_HONOR_GAIN" then			if not self.eventTable["CHAT_MSG_COMBAT_HONOR_GAIN"] then			self.eventTable["CHAT_MSG_COMBAT_HONOR_GAIN"] = {			"COMBATLOG_HONORAWARD",			"COMBATLOG_HONORGAIN",			"COMBATLOG_DISHONORGAIN",			}			table.sort(self.eventTable["CHAT_MSG_COMBAT_HONOR_GAIN"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_COMBAT_HONOR_GAIN"]	elseif eventName == "CHAT_MSG_COMBAT_XP_GAIN" then			if not self.eventTable["CHAT_MSG_COMBAT_XP_GAIN"] then			self.eventTable["CHAT_MSG_COMBAT_XP_GAIN"] = {				"COMBATLOG_XPGAIN",				"COMBATLOG_XPGAIN_EXHAUSTION1",				"COMBATLOG_XPGAIN_EXHAUSTION1_GROUP",				"COMBATLOG_XPGAIN_EXHAUSTION1_RAID",				"COMBATLOG_XPGAIN_EXHAUSTION2",				"COMBATLOG_XPGAIN_EXHAUSTION2_GROUP",				"COMBATLOG_XPGAIN_EXHAUSTION2_RAID",				"COMBATLOG_XPGAIN_EXHAUSTION4",				"COMBATLOG_XPGAIN_EXHAUSTION4_GROUP",				"COMBATLOG_XPGAIN_EXHAUSTION4_RAID",				"COMBATLOG_XPGAIN_EXHAUSTION5",				"COMBATLOG_XPGAIN_EXHAUSTION5_GROUP",				"COMBATLOG_XPGAIN_EXHAUSTION5_RAID",				"COMBATLOG_XPGAIN_FIRSTPERSON",				"COMBATLOG_XPGAIN_FIRSTPERSON_GROUP",				"COMBATLOG_XPGAIN_FIRSTPERSON_RAID",				"COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED",				"COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED_GROUP",				"COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED_RAID",				"COMBATLOG_XPLOSS_FIRSTPERSON_UNNAMED",			}			table.sort(self.eventTable["CHAT_MSG_COMBAT_XP_GAIN"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_COMBAT_XP_GAIN"]					elseif eventName == "CHAT_MSG_COMBAT_FRIENDLY_DEATH" 	or eventName == "CHAT_MSG_COMBAT_HOSTILE_DEATH" then			if not self.eventTable["CHAT_MSG_COMBAT_HOSTILE_DEATH"] then			self.eventTable["CHAT_MSG_COMBAT_HOSTILE_DEATH"] = {				"SELFKILLOTHER",				"PARTYKILLOTHER",				"UNITDESTROYEDOTHER",				"UNITDIESOTHER",				"UNITDIESSELF",			}						table.sort(self.eventTable["CHAT_MSG_COMBAT_HOSTILE_DEATH"] , PatternCompare)		end				list = self.eventTable["CHAT_MSG_COMBAT_HOSTILE_DEATH"]		end	if not list then		-- self:Print(string.format("Event '%s' not found.", eventName), 1, 0,0); -- debug	end	return listendfunction lib:LoadPatternCategory(category)	local list	if category == "AuraChange" then		list = {			"AURACHANGEDOTHER",			"AURACHANGEDSELF",		}	elseif category == "AuraDispel" then		list = {			"AURADISPELOTHER",			"AURADISPELSELF",		}	elseif category == "BuffOther" then		list = {			"AURAADDEDOTHERHELPFUL",			"AURAAPPLICATIONADDEDOTHERHELPFUL",		}	elseif category == "BuffSelf" then		list = {			"AURAADDEDSELFHELPFUL",			"AURAAPPLICATIONADDEDSELFHELPFUL",		}	elseif category == "CastOther" then	list = {			"SIMPLECASTOTHEROTHER",			"SIMPLECASTOTHERSELF",			"SPELLTERSE_OTHER",		}	elseif category == "CastSelf" then	list = {			"SIMPLECASTSELFOTHER",			"SIMPLECASTSELFSELF",			"SPELLTERSE_SELF",		}	elseif category == "DebuffOther" then		list = {			"AURAADDEDOTHERHARMFUL",			"AURAAPPLICATIONADDEDOTHERHARMFUL",		}	elseif category == "DebuffSelf" then		list = {			"AURAADDEDSELFHARMFUL",			"AURAAPPLICATIONADDEDSELFHARMFUL",		}	elseif category == "DispelFailOther" then	list = {			"DISPELFAILEDOTHEROTHER",			"DISPELFAILEDOTHERSELF",				}	elseif category == "DispelFailSelf" then		list = {			"DISPELFAILEDSELFOTHER",			"DISPELFAILEDSELFSELF",		}	elseif category == "DmgShieldOther" then list = {			"DAMAGESHIELDOTHEROTHER",			"DAMAGESHIELDOTHERSELF",		}	elseif category == "DmgShieldSelf" then		list = {			"DAMAGESHIELDSELFOTHER",		}	elseif category == "DurabilityDamageSelf" then list = {		"SPELLDURABILITYDAMAGEALLSELFOTHER",		"SPELLDURABILITYDAMAGESELFOTHER",		}	elseif category == "DurabilityDamageOther" then list = {			"SPELLDURABILITYDAMAGEALLOTHEROTHER",			"SPELLDURABILITYDAMAGEALLOTHERSELF", 			"SPELLDURABILITYDAMAGEOTHEROTHER", 			"SPELLDURABILITYDAMAGEOTHERSELF",	}	elseif category == "EnchantOther" then		list  =  {			"ITEMENCHANTMENTADDOTHEROTHER",			"ITEMENCHANTMENTADDOTHERSELF",		}	elseif category == "EnchantSelf" then		list = {			"ITEMENCHANTMENTADDSELFOTHER",			"ITEMENCHANTMENTADDSELFSELF",		}	elseif category == "ExtraAttackOther" then		list = {			"SPELLEXTRAATTACKSOTHER",			"SPELLEXTRAATTACKSOTHER_SINGULAR",		}			elseif category == "ExtraAttackSelf" then		list = {			"SPELLEXTRAATTACKSSELF",			"SPELLEXTRAATTACKSSELF_SINGULAR",		}			elseif category == "Fade" then		list = {			"AURAREMOVEDOTHER",			"AURAREMOVEDSELF",		}	elseif category == "HealOther" then		list = {			"HEALEDCRITOTHEROTHER",			"HEALEDCRITOTHERSELF",			"HEALEDOTHEROTHER",			"HEALEDOTHERSELF",		}	elseif category == "HealSelf" then		list = {			"HEALEDCRITSELFOTHER",			"HEALEDCRITSELFSELF",			"HEALEDSELFOTHER",			"HEALEDSELFSELF",		}	elseif category == "HitOtherOther" then		list = {			"COMBATHITCRITOTHEROTHER",			"COMBATHITCRITSCHOOLOTHEROTHER",			"COMBATHITOTHEROTHER",			"COMBATHITSCHOOLOTHEROTHER",		}	elseif category == "HitOtherSelf" then		list = {				"COMBATHITCRITOTHERSELF",			"COMBATHITCRITSCHOOLOTHERSELF",			"COMBATHITOTHERSELF",			"COMBATHITSCHOOLOTHERSELF",		}	elseif category == "HitSelf" then		list = {			"COMBATHITSCHOOLSELFOTHER",			"COMBATHITSELFOTHER",			"COMBATHITCRITSCHOOLSELFOTHER",			"COMBATHITCRITSELFOTHER",		}	elseif category == "MissOtherOther" then	list = {			"MISSEDOTHEROTHER",			"VSABSORBOTHEROTHER",			"VSBLOCKOTHEROTHER",			"VSDEFLECTOTHEROTHER",			"VSDODGEOTHEROTHER",			"VSEVADEOTHEROTHER",			"VSIMMUNEOTHEROTHER",			"VSPARRYOTHEROTHER",			"VSRESISTOTHEROTHER",			"IMMUNEDAMAGECLASSOTHEROTHER",			"IMMUNEOTHEROTHER",					}		elseif category == "MissOtherSelf" then	list = {			"MISSEDOTHERSELF",			"VSABSORBOTHERSELF",			"VSBLOCKOTHERSELF",			"VSDEFLECTOTHERSELF",			"VSDODGEOTHERSELF",			"VSEVADEOTHERSELF",			"VSIMMUNEOTHERSELF",			"VSPARRYOTHERSELF",			"VSRESISTOTHERSELF",				"IMMUNEDAMAGECLASSOTHERSELF",			"IMMUNEOTHERSELF",		}		elseif category == "MissSelf" then	list = {				"MISSEDSELFOTHER",				"VSABSORBSELFOTHER",				"VSBLOCKSELFOTHER",				"VSDEFLECTSELFOTHER",				"VSDODGESELFOTHER",				"VSEVADESELFOTHER",				"VSIMMUNESELFOTHER",				"VSPARRYSELFOTHER",				"VSRESISTSELFOTHER",				"IMMUNEDAMAGECLASSSELFOTHER",				"IMMUNESELFOTHER",				"IMMUNESELFSELF",		}	elseif category == "PowerGainOther" then		list = {			"POWERGAINOTHEROTHER",			"POWERGAINOTHERSELF",		}	elseif category == "PerformOther" then list = {			"OPEN_LOCK_OTHER",			"SIMPLEPERFORMOTHEROTHER",			"SIMPLEPERFORMOTHERSELF",			"SPELLTERSEPERFORM_OTHER",		}	elseif category == "PerformSelf" then	list = {			"OPEN_LOCK_SELF",			"SIMPLEPERFORMSELFOTHER",			"SIMPLEPERFORMSELFSELF",			"SPELLTERSEPERFORM_SELF",		}	elseif category == "ProcResistOther" then list = {			"PROCRESISTOTHEROTHER",			"PROCRESISTOTHERSELF",		}	elseif category == "ProcResistSelf" then	list = {			"PROCRESISTSELFOTHER",			"PROCRESISTSELFSELF",		}	elseif category == "EnvOther" then list = {			"VSENVIRONMENTALDAMAGE_DROWNING_OTHER",			"VSENVIRONMENTALDAMAGE_FALLING_OTHER",			"VSENVIRONMENTALDAMAGE_FATIGUE_OTHER",			"VSENVIRONMENTALDAMAGE_FIRE_OTHER",			"VSENVIRONMENTALDAMAGE_LAVA_OTHER",			"VSENVIRONMENTALDAMAGE_SLIME_OTHER",		}	elseif category == "EnvSelf" then	list = {			"VSENVIRONMENTALDAMAGE_DROWNING_SELF",			"VSENVIRONMENTALDAMAGE_FALLING_SELF",			"VSENVIRONMENTALDAMAGE_FATIGUE_SELF",			"VSENVIRONMENTALDAMAGE_FIRE_SELF",			"VSENVIRONMENTALDAMAGE_LAVA_SELF",			"VSENVIRONMENTALDAMAGE_SLIME_SELF",		}	-- HoT effects on others. (not casted by others)	elseif category == "HotOther" then	list = {			"PERIODICAURAHEALOTHEROTHER",			"PERIODICAURAHEALSELFOTHER",		}	-- HoT effects on you. (not casted by you)	elseif category == "HotSelf" then	list = {			"PERIODICAURAHEALSELFSELF",			"PERIODICAURAHEALOTHERSELF",		}	elseif category == "PowerGainSelf" then	list = {			"POWERGAINSELFSELF",			"POWERGAINSELFOTHER",		}	elseif category == "BuffOther" then	list = {		"AURAAPPLICATIONADDEDOTHERHELPFUL",		"AURAADDEDOTHERHELPFUL",		}	elseif category == "BuffSelf" then	list = {			"AURAADDEDSELFHELPFUL",			"AURAAPPLICATIONADDEDSELFHELPFUL",		}	elseif category == "DrainSelf" then	list = {				"SPELLPOWERLEECHSELFOTHER",			"SPELLPOWERDRAINSELFOTHER",			"SPELLPOWERDRAINSELFSELF",		}	elseif category == "DrainOther" then	list = {				"SPELLPOWERLEECHOTHEROTHER",			"SPELLPOWERLEECHOTHERSELF",			"SPELLPOWERDRAINOTHEROTHER",			"SPELLPOWERDRAINOTHERSELF",		}	-- DoT effects on others (not casted by others)	elseif category == "DotOther" then	list = {			"PERIODICAURADAMAGEOTHEROTHER",			"PERIODICAURADAMAGESELFOTHER",		}	-- DoT effects on you (not casted by you)	elseif category == "DotSelf" then	list = {			"PERIODICAURADAMAGEOTHERSELF",			"PERIODICAURADAMAGESELFSELF",		}	elseif category == "SpellHitOther" then	list = {			"SPELLLOGCRITOTHEROTHER",			"SPELLLOGCRITOTHERSELF",			"SPELLLOGCRITSCHOOLOTHEROTHER",			"SPELLLOGCRITSCHOOLOTHERSELF",			"SPELLLOGOTHEROTHER",			"SPELLLOGOTHERSELF",			"SPELLLOGSCHOOLOTHEROTHER",			"SPELLLOGSCHOOLOTHERSELF",		}	elseif category == "SpellHitSelf" then	list = {			"SPELLLOGCRITSELFOTHER",			"SPELLLOGCRITSELFSELF",			"SPELLLOGCRITSCHOOLSELFOTHER",			"SPELLLOGCRITSCHOOLSELFSELF",			"SPELLLOGSELFOTHER",			"SPELLLOGSELFSELF",			"SPELLLOGSCHOOLSELFOTHER",			"SPELLLOGSCHOOLSELFSELF",		}	elseif category == "SpellMissSelf" then		list = {			"IMMUNESPELLSELFOTHER",			"IMMUNESPELLSELFSELF",			"SPELLBLOCKEDSELFOTHER",			"SPELLDEFLECTEDSELFOTHER",			"SPELLDEFLECTEDSELFSELF",			"SPELLDODGEDSELFOTHER",			"SPELLDODGEDSELFSELF",			"SPELLEVADEDSELFOTHER",			"SPELLEVADEDSELFSELF",			"SPELLIMMUNESELFOTHER",			"SPELLIMMUNESELFSELF",			"SPELLLOGABSORBSELFOTHER",			"SPELLLOGABSORBSELFSELF",			"SPELLMISSSELFOTHER",			"SPELLMISSSELFSELF",			"SPELLPARRIEDSELFOTHER",			"SPELLPARRIEDSELFSELF",			"SPELLREFLECTSELFOTHER",			"SPELLREFLECTSELFSELF",			"SPELLRESISTSELFOTHER",			"SPELLRESISTSELFSELF",		}	elseif category == "SpellMissOther" then		list = {			"IMMUNESPELLOTHEROTHER",			"IMMUNESPELLOTHERSELF",			"SPELLBLOCKEDOTHEROTHER",			"SPELLBLOCKEDOTHERSELF",			"SPELLDODGEDOTHEROTHER",			"SPELLDODGEDOTHERSELF",			"SPELLDEFLECTEDOTHEROTHER",			"SPELLDEFLECTEDOTHERSELF",			"SPELLEVADEDOTHEROTHER",			"SPELLEVADEDOTHERSELF",			"SPELLIMMUNEOTHEROTHER",			"SPELLIMMUNEOTHERSELF",			"SPELLLOGABSORBOTHEROTHER",			"SPELLLOGABSORBOTHERSELF",			"SPELLMISSOTHEROTHER",			"SPELLMISSOTHERSELF",			"SPELLPARRIEDOTHEROTHER",			"SPELLPARRIEDOTHERSELF",			"SPELLREFLECTOTHEROTHER",			"SPELLREFLECTOTHERSELF",			"SPELLRESISTOTHEROTHER",			"SPELLRESISTOTHERSELF",		}		elseif category == "InterruptOther" then	list = {			"SPELLINTERRUPTOTHEROTHER",			"SPELLINTERRUPTOTHERSELF",		}	elseif category == "InterruptSelf" then	list = {			"SPELLINTERRUPTSELFOTHER",		}	elseif category == "SplitDamageOther" then list = {		"SPELLSPLITDAMAGEOTHEROTHER",		"SPELLSPLITDAMAGEOTHERSELF",	}			else return { category }	end		return list	end-- Load categories recursively. First layer will not be sorted.function lib:LoadPatternCategoryTree(catTree, reSort)	if type(catTree) ~= "table" then return end		local resultList = {}	local list		for i, v in ipairs(catTree) do			if type(v) == "table" then			list = self:LoadPatternCategoryTree(v, true)		else -- should be string.					list = self:LoadPatternCategory(v)			table.sort(list, PatternCompare)		end				for j, w in pairs(list) do			table.insert(resultList, w)		end			end		if reSort then		table.sort(resultList, PatternCompare)	end		return resultListend -- Used to load patternTable elements on demand.function lib:LoadPatternInfo(patternName)	local patternInfo		if patternName == "AURAADDEDOTHERHELPFUL" then		patternInfo = { "buff", 1, 2, nil, }	elseif patternName == "AURAADDEDSELFHELPFUL" then		patternInfo = { "buff", ParserLib_SELF, 1, nil, }	elseif patternName == "AURAAPPLICATIONADDEDOTHERHELPFUL" then		patternInfo = { "buff", 1, 2, 3, }	elseif patternName == "AURAAPPLICATIONADDEDSELFHELPFUL" then		patternInfo = { "buff", ParserLib_SELF, 1, 2, }		elseif patternName == "OPEN_LOCK_OTHER" then		patternInfo = { "cast", 1, 2, 3, nil, true, }	elseif patternName == "OPEN_LOCK_SELF" then 		patternInfo = { "cast", ParserLib_SELF, 1, 2, nil, true, }	elseif patternName == "SIMPLECASTOTHEROTHER" then		patternInfo = { "cast", 1, 2, 3, nil, nil, }	elseif patternName == "SIMPLECASTOTHERSELF" then		patternInfo = { "cast", 1, 2, ParserLib_SELF, nil, nil, }	elseif patternName == "SIMPLECASTSELFOTHER" then		patternInfo = { "cast", ParserLib_SELF, 1, 2, nil, nil, }	elseif patternName == "SIMPLECASTSELFSELF" then		patternInfo = { "cast", ParserLib_SELF, 1, ParserLib_SELF, nil, nil, }	elseif patternName == "SIMPLEPERFORMOTHEROTHER" then		patternInfo = { "cast", 1, 2, 3, nil, true, }	elseif patternName == "SIMPLEPERFORMOTHERSELF" then		patternInfo = { "cast", 1, 2, ParserLib_SELF, nil, true, }	elseif patternName == "SIMPLEPERFORMSELFOTHER" then		patternInfo = { "cast", ParserLib_SELF, 1, 2, nil, true, }	elseif patternName == "SIMPLEPERFORMSELFSELF" then		patternInfo = { "cast", ParserLib_SELF, 1, ParserLib_SELF, nil, true, }	elseif patternName == "SPELLCASTOTHERSTART" then		patternInfo = { "cast", 1, 2, nil, true, nil, }	elseif patternName == "SPELLCASTSELFSTART" then		patternInfo = { "cast", ParserLib_SELF, 1, nil, true, nil, }	elseif patternName == "SPELLPERFORMOTHERSTART" then		patternInfo = { "cast", 1, 2, nil, true, true, }	elseif patternName == "SPELLPERFORMSELFSTART" then		patternInfo = { "cast", ParserLib_SELF, 1, nil, true, true, }	elseif patternName == "SPELLTERSEPERFORM_OTHER" then		patternInfo = { "cast", 1, 2, nil, nil, true, }	elseif patternName == "SPELLTERSEPERFORM_SELF" then		patternInfo = { "cast", ParserLib_SELF, 1, nil, nil, true, }	elseif patternName == "SPELLTERSE_OTHER" then		patternInfo = { "cast", 1, 2, nil, nil, nil, }	elseif patternName == "SPELLTERSE_SELF" then		patternInfo = { "cast", ParserLib_SELF, 1, nil, nil, nil, }		elseif patternName == "TRADESKILL_LOG_FIRSTPERSON" then		patternInfo = { "create", ParserLib_SELF, 1, }	elseif patternName == "TRADESKILL_LOG_THIRDPERSON" then		patternInfo = { "create", 1, 2, }		elseif patternName == "PARTYKILLOTHER" then		patternInfo = { "death", 1, 2, nil, nil, }	elseif patternName == "SELFKILLOTHER" then		patternInfo = { "death", 1, ParserLib_SELF, nil, nil, }	elseif patternName == "UNITDESTROYEDOTHER" then		patternInfo = { "death", 1, nil, nil, true, }	elseif patternName == "UNITDIESOTHER" then		patternInfo = { "death", 1, nil, nil, nil, }	elseif patternName == "UNITDIESSELF" then		patternInfo = { "death", ParserLib_SELF, nil, nil, nil, }	elseif patternName == "INSTAKILLOTHER" then		patternInfo = { "death", 1, nil, 2, nil, }	elseif patternName == "INSTAKILLSELF" then		patternInfo = { "death", ParserLib_SELF, nil, true, nil }			elseif patternName == "AURAADDEDOTHERHARMFUL" then		patternInfo = { "debuff", 1, 2, nil, }	elseif patternName == "AURAADDEDSELFHARMFUL" then		patternInfo = { "debuff", ParserLib_SELF, 1, nil, }	elseif patternName == "AURAAPPLICATIONADDEDOTHERHARMFUL" then		patternInfo = { "debuff", 1, 2, 3, }	elseif patternName == "AURAAPPLICATIONADDEDSELFHARMFUL" then		patternInfo = { "debuff", ParserLib_SELF, 1, 2, }		elseif patternName == "AURADISPELOTHER" then		patternInfo = { "dispel", 1, 2, nil, nil, }	elseif patternName == "AURADISPELSELF" then		patternInfo = { "dispel", ParserLib_SELF, 1, nil, nil, }	elseif patternName == "DISPELFAILEDOTHEROTHER" then		patternInfo = { "dispel", 2, 3, 1, true, }	elseif patternName == "DISPELFAILEDOTHERSELF" then		patternInfo = { "dispel", ParserLib_SELF, 2, 1, true, }	elseif patternName == "DISPELFAILEDSELFOTHER" then		patternInfo = { "dispel", 1, 2, ParserLib_SELF, true, }	elseif patternName == "DISPELFAILEDSELFSELF" then		patternInfo = { "dispel", ParserLib_SELF, 1, ParserLib_SELF, true, }		elseif patternName == "SPELLPOWERDRAINOTHEROTHER" then		patternInfo = { "drain", 1, 5, 2, 3, 4, }	elseif patternName == "SPELLPOWERDRAINOTHERSELF" then		patternInfo = { "drain", 1, ParserLib_SELF, 2, 3, 4, }	elseif patternName == "SPELLPOWERDRAINSELFOTHER" then		patternInfo = { "drain", ParserLib_SELF, 4, 1, 2, 3, }	elseif patternName == "SPELLPOWERDRAINSELFSELF" then		patternInfo = { "drain", ParserLib_SELF, ParserLib_SELF, 1, 2, 3, }		elseif patternName == "SPELLDURABILITYDAMAGEALLOTHEROTHER" then		patternInfo = { "durability", 1, 2, 3, nil, }	elseif patternName == "SPELLDURABILITYDAMAGEALLOTHERSELF" then		patternInfo = { "durability", 1, 2, ParserLib_SELF, nil, }	elseif patternName == "SPELLDURABILITYDAMAGEALLSELFOTHER" then		patternInfo = { "durability", ParserLib_SELF, 1, 2, nil, }	elseif patternName == "SPELLDURABILITYDAMAGEOTHEROTHER" then		patternInfo = { "durability", 1, 2, 3, 4, }	elseif patternName == "SPELLDURABILITYDAMAGEOTHERSELF" then		patternInfo = { "durability", 1, 2, ParserLib_SELF, 3, }	elseif patternName == "SPELLDURABILITYDAMAGESELFOTHER" then		patternInfo = { "durability", ParserLib_SELF, 1, 2, 3, }		elseif patternName == "ITEMENCHANTMENTADDOTHEROTHER" then		patternInfo = { "enchant", 1, 3, 2, 4, }	elseif patternName == "ITEMENCHANTMENTADDOTHERSELF" then		patternInfo = { "enchant", 1, ParserLib_SELF, 2, 3, }	elseif patternName == "ITEMENCHANTMENTADDSELFOTHER" then		patternInfo = { "enchant", ParserLib_SELF, 2, 1, 3, }	elseif patternName == "ITEMENCHANTMENTADDSELFSELF" then		patternInfo = { "enchant", ParserLib_SELF, ParserLib_SELF, 1, 2, }		elseif patternName == "VSENVIRONMENTALDAMAGE_DROWNING_OTHER" then		patternInfo = { "environment", 1, 2, "drown", }	elseif patternName == "VSENVIRONMENTALDAMAGE_DROWNING_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "drown", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FALLING_OTHER" then		patternInfo = { "environment", 1, 2, "fall", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FALLING_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "fall", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FATIGUE_OTHER" then		patternInfo = { "environment", 1, 2, "exhaust", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FATIGUE_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "exhaust", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FIRE_OTHER" then		patternInfo = { "environment", 1, 2, "fire", }	elseif patternName == "VSENVIRONMENTALDAMAGE_FIRE_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "fire", }	elseif patternName == "VSENVIRONMENTALDAMAGE_LAVA_OTHER" then		patternInfo = { "environment", 1, 2, "lava", }	elseif patternName == "VSENVIRONMENTALDAMAGE_LAVA_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "lava", }	elseif patternName == "VSENVIRONMENTALDAMAGE_SLIME_OTHER" then		patternInfo = { "environment", 1, 2, "slime", }	elseif patternName == "VSENVIRONMENTALDAMAGE_SLIME_SELF" then		patternInfo = { "environment", ParserLib_SELF, 1, "slime", }		elseif patternName == "COMBATLOG_XPGAIN" then		patternInfo = { "experience", 2, nil, nil, nil, nil, nil, nil, nil, 1, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION1" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION1_GROUP" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, nil, 5, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION1_RAID" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, 5, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION2" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION2_GROUP" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, nil, 5, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION2_RAID" then		patternInfo = { "experience", 2, 1, 3, 4, nil, nil, 5, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION4" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION4_GROUP" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, nil, 5, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION4_RAID" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, 5, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION5" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION5_GROUP" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, nil, 5, nil, }	elseif patternName == "COMBATLOG_XPGAIN_EXHAUSTION5_RAID" then		patternInfo = { "experience", 2, 1, nil, nil, 3, 4, 5, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON" then		patternInfo = { "experience", 2, 1, nil, nil, nil, nil, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON_GROUP" then		patternInfo = { "experience", 2, 1, nil, nil, nil, nil, nil, 3, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON_RAID" then		patternInfo = { "experience", 2, 1, nil, nil, nil, nil, 3, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED" then		patternInfo = { "experience", 1, nil, nil, nil, nil, nil, nil, nil, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED_GROUP" then		patternInfo = { "experience", 1, nil, nil, nil, nil, nil, nil, 2, nil, }	elseif patternName == "COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED_RAID" then		patternInfo = { "experience", 1, nil, nil, nil, nil, nil, 2, nil, nil, }	elseif patternName == "COMBATLOG_XPLOSS_FIRSTPERSON_UNNAMED" then		patternInfo = { "experience", 1, nil, nil, nil, nil, nil, nil, nil, nil, }		elseif patternName == "SPELLEXTRAATTACKSOTHER" then		patternInfo = { "extraattack", 1, 3, 2, }	elseif patternName == "SPELLEXTRAATTACKSOTHER_SINGULAR" then		patternInfo = { "extraattack", 1, 3, 2, }	elseif patternName == "SPELLEXTRAATTACKSSELF" then		patternInfo = { "extraattack", ParserLib_SELF, 2, 1, }	elseif patternName == "SPELLEXTRAATTACKSSELF_SINGULAR" then		patternInfo = { "extraattack", ParserLib_SELF, 2, 1, }		elseif patternName == "AURAREMOVEDOTHER" then		patternInfo = { "fade", 2, 1, }	elseif patternName == "AURAREMOVEDSELF" then		patternInfo = { "fade", ParserLib_SELF, 1, }		elseif patternName == "SPELLFAILCASTSELF" then		patternInfo = { "fail", ParserLib_SELF, 1, 2, }	elseif patternName == "SPELLFAILPERFORMSELF" then		patternInfo = { "fail", ParserLib_SELF, 1, 2, }		elseif patternName == "FEEDPET_LOG_FIRSTPERSON" then		patternInfo = { "feedpet", ParserLib_SELF, 1, }	elseif patternName == "FEEDPET_LOG_THIRDPERSON" then		patternInfo = { "feedpet", 1, 2, }		elseif patternName == "POWERGAINOTHEROTHER" then		patternInfo = { "gain", 4, 1, 5, 2, 3, }	elseif patternName == "POWERGAINOTHERSELF" then		patternInfo = { "gain", 3, ParserLib_SELF, 4, 1, 2, }	elseif patternName == "POWERGAINSELFOTHER" then		patternInfo = { "gain", ParserLib_SELF, 1, 4, 2, 3, }	elseif patternName == "POWERGAINSELFSELF" then		patternInfo = { "gain", ParserLib_SELF, ParserLib_SELF, 3, 1, 2, }		elseif patternName == "HEALEDCRITOTHEROTHER" then		patternInfo = { "heal", 1, 3, 2, 4, true, nil, }	elseif patternName == "HEALEDCRITOTHERSELF" then		patternInfo = { "heal", 1, ParserLib_SELF, 2, 3, true, nil, }	elseif patternName == "HEALEDCRITSELFOTHER" then		patternInfo = { "heal", ParserLib_SELF, 2, 1, 3, true, nil, }	elseif patternName == "HEALEDCRITSELFSELF" then		patternInfo = { "heal", ParserLib_SELF, ParserLib_SELF, 1, 2, true, nil, }	elseif patternName == "HEALEDOTHEROTHER" then		patternInfo = { "heal", 1, 3, 2, 4, nil, nil, }	elseif patternName == "HEALEDOTHERSELF" then		patternInfo = { "heal", 1, ParserLib_SELF, 2, 3, nil, nil, }	elseif patternName == "HEALEDSELFOTHER" then		patternInfo = { "heal", ParserLib_SELF, 2, 1, 3, nil, nil, }	elseif patternName == "HEALEDSELFSELF" then		patternInfo = { "heal", ParserLib_SELF, ParserLib_SELF, 1, 2, nil, nil, }	elseif patternName == "PERIODICAURAHEALOTHEROTHER" then		patternInfo = { "heal", 3, 1, 4, 2, nil, true, }	elseif patternName == "PERIODICAURAHEALOTHERSELF" then		patternInfo = { "heal", 2, ParserLib_SELF, 3, 1, nil, true, }	elseif patternName == "PERIODICAURAHEALSELFOTHER" then		patternInfo = { "heal", ParserLib_SELF, 1, 3, 2, nil, true, }	elseif patternName == "PERIODICAURAHEALSELFSELF" then		patternInfo = { "heal", ParserLib_SELF, ParserLib_SELF, 2, 1, nil, true, }		elseif patternName == "COMBATHITCRITOTHEROTHER" then		patternInfo = { "hit", 1, 2, ParserLib_MELEE, 3, nil, true, nil, nil, }	elseif patternName == "COMBATHITCRITOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, ParserLib_MELEE, 2, nil, true, nil, nil, }	elseif patternName == "COMBATHITCRITSCHOOLOTHEROTHER" then		patternInfo = { "hit", 1, 2, ParserLib_MELEE, 3, 4, true, nil, nil, }	elseif patternName == "COMBATHITCRITSCHOOLOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, ParserLib_MELEE, 2, 3, true, nil, nil, }	elseif patternName == "COMBATHITCRITSCHOOLSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 1, ParserLib_MELEE, 2, 3, true, nil, nil, }	elseif patternName == "COMBATHITCRITSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 1, ParserLib_MELEE, 2, nil, true, nil, nil, }	elseif patternName == "COMBATHITOTHEROTHER" then		patternInfo = { "hit", 1, 2, ParserLib_MELEE, 3, nil, nil, nil, nil, }	elseif patternName == "COMBATHITOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, ParserLib_MELEE, 2, nil, nil, nil, nil, }	elseif patternName == "COMBATHITSCHOOLOTHEROTHER" then		patternInfo = { "hit", 1, 2, ParserLib_MELEE, 3, 4, nil, nil, nil, }	elseif patternName == "COMBATHITSCHOOLOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, ParserLib_MELEE, 2, 3, nil, nil, nil, }	elseif patternName == "COMBATHITSCHOOLSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 1, ParserLib_MELEE, 2, 3, nil, nil, nil, }	elseif patternName == "COMBATHITSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 1, ParserLib_MELEE, 2, nil, nil, nil, nil, }	elseif patternName == "DAMAGESHIELDOTHEROTHER" then		patternInfo = { "hit", 1, 4, ParserLib_DAMAGESHIELD, 2, 3, nil, nil, nil, }	elseif patternName == "DAMAGESHIELDOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, ParserLib_DAMAGESHIELD, 2, 3, nil, nil, nil, }	elseif patternName == "DAMAGESHIELDSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 3, ParserLib_DAMAGESHIELD, 1, 2, nil, nil, nil, }	elseif patternName == "PERIODICAURADAMAGEOTHEROTHER" then		patternInfo = { "hit", 4, 1, 5, 2, 3, nil, true, nil, }	elseif patternName == "PERIODICAURADAMAGEOTHERSELF" then		patternInfo = { "hit", 3, ParserLib_SELF, 4, 1, 2, nil, true, nil, }	elseif patternName == "PERIODICAURADAMAGESELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 1, 4, 2, 3, nil, true, nil, }	elseif patternName == "PERIODICAURADAMAGESELFSELF" then		patternInfo = { "hit", ParserLib_SELF, ParserLib_SELF, 3, 1, 2, nil, true, nil, }	elseif patternName == "SPELLLOGCRITOTHEROTHER" then		patternInfo = { "hit", 1, 3, 2, 4, nil, true, nil, nil, }	elseif patternName == "SPELLLOGCRITOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, 2, 3, nil, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSCHOOLOTHEROTHER" then		patternInfo = { "hit", 1, 3, 2, 4, 5, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSCHOOLOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, 2, 3, 4, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSCHOOLSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 2, 1, 3, 4, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSCHOOLSELFSELF" then		patternInfo = { "hit", ParserLib_SELF, ParserLib_SELF, 1, 2, 3, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 2, 1, 3, nil, true, nil, nil, }	elseif patternName == "SPELLLOGCRITSELFSELF" then		patternInfo = { "hit", ParserLib_SELF, ParserLib_SELF, 1, 2, nil, true, nil, nil, }	elseif patternName == "SPELLLOGOTHEROTHER" then		patternInfo = { "hit", 1, 3, 2, 4, nil, nil, nil, nil, }	elseif patternName == "SPELLLOGOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, 2, 3, nil, nil, nil, nil, }	elseif patternName == "SPELLLOGSCHOOLOTHEROTHER" then		patternInfo = { "hit", 1, 3, 2, 4, 5, nil, nil, nil, }	elseif patternName == "SPELLLOGSCHOOLOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, 2, 3, 4, nil, nil, nil, }	elseif patternName == "SPELLLOGSCHOOLSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 2, 1, 3, 4, nil, nil, nil, }	elseif patternName == "SPELLLOGSCHOOLSELFSELF" then		patternInfo = { "hit", ParserLib_SELF, ParserLib_SELF, 1, 2, 3, nil, nil, nil, }	elseif patternName == "SPELLLOGSELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 2, 1, 3, nil, nil, nil, nil, }	elseif patternName == "SPELLLOGSELFSELF" then		patternInfo = { "hit", ParserLib_SELF, ParserLib_SELF, 1, 2, nil, nil, nil, nil, }	elseif patternName == "SPELLSPLITDAMAGEOTHEROTHER" then		patternInfo = { "hit", 1, 3, 2, 4, nil, nil, nil, true, }	elseif patternName == "SPELLSPLITDAMAGEOTHERSELF" then		patternInfo = { "hit", 1, ParserLib_SELF, 2, 3, nil, nil, nil, true, }	elseif patternName == "SPELLSPLITDAMAGESELFOTHER" then		patternInfo = { "hit", ParserLib_SELF, 2, 1, 3, nil, nil, nil, true, }		elseif patternName == "COMBATLOG_DISHONORGAIN" then		patternInfo = { "honor", nil, 1, nil, }	elseif patternName == "COMBATLOG_HONORAWARD" then		patternInfo = { "honor", 1, nil, nil, }	elseif patternName == "COMBATLOG_HONORGAIN" then		patternInfo = { "honor", 3, 1, 2, }		elseif patternName == "SPELLINTERRUPTOTHEROTHER" then		patternInfo = { "interrupt", 1, 2, 3, }	elseif patternName == "SPELLINTERRUPTOTHERSELF" then		patternInfo = { "interrupt", 1, ParserLib_SELF, 2, }	elseif patternName == "SPELLINTERRUPTSELFOTHER" then		patternInfo = { "interrupt", ParserLib_SELF, 1, 2, }		elseif patternName == "SPELLPOWERLEECHOTHEROTHER" then		patternInfo = { "leech", 1, 5, 2, 3, 4, 6, 7, 8, }	elseif patternName == "SPELLPOWERLEECHOTHERSELF" then		patternInfo = { "leech", 1, ParserLib_SELF, 2, 3, 4, 5, 6, 7, }	elseif patternName == "SPELLPOWERLEECHSELFOTHER" then		patternInfo = { "leech", ParserLib_SELF, 4, 1, 2, 3, ParserLib_SELF, 5, 6, }		elseif patternName == "IMMUNEDAMAGECLASSOTHEROTHER" then		patternInfo = { "miss", 2, 1, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNEDAMAGECLASSOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNEDAMAGECLASSSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNEOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNEOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNESELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNESELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, ParserLib_MELEE, "immune", }	elseif patternName == "IMMUNESPELLOTHEROTHER" then		patternInfo = { "miss", 2, 1, 3, "immune", }	elseif patternName == "IMMUNESPELLOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "immune", }	elseif patternName == "IMMUNESPELLSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, 2, "immune", }	elseif patternName == "IMMUNESPELLSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "immune", }	elseif patternName == "MISSEDOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "miss", }	elseif patternName == "MISSEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "miss", }	elseif patternName == "MISSEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "miss", }	elseif patternName == "PROCRESISTOTHEROTHER" then		patternInfo = { "miss", 2, 1, 3, "resist", }	elseif patternName == "PROCRESISTOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "resist", }	elseif patternName == "PROCRESISTSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, 2, "resist", }	elseif patternName == "PROCRESISTSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "resist", }	elseif patternName == "SPELLBLOCKEDOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "block", }	elseif patternName == "SPELLBLOCKEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "block", }	elseif patternName == "SPELLBLOCKEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "block", }	elseif patternName == "SPELLDEFLECTEDOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "deflect", }	elseif patternName == "SPELLDEFLECTEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "deflect", }	elseif patternName == "SPELLDEFLECTEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "deflect", }	elseif patternName == "SPELLDEFLECTEDSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "deflect", }	elseif patternName == "SPELLDODGEDOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "dodge", }	elseif patternName == "SPELLDODGEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "dodge", }	elseif patternName == "SPELLDODGEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "dodge", }	elseif patternName == "SPELLDODGEDSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "dodge", }	elseif patternName == "SPELLEVADEDOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "evade", }	elseif patternName == "SPELLEVADEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "evade", }	elseif patternName == "SPELLEVADEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "evade", }	elseif patternName == "SPELLEVADEDSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "evade", }	elseif patternName == "SPELLIMMUNEOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "immune", }	elseif patternName == "SPELLIMMUNEOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "immune", }	elseif patternName == "SPELLIMMUNESELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "immune", }	elseif patternName == "SPELLIMMUNESELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "immune", }	elseif patternName == "SPELLLOGABSORBOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "absorb", }	elseif patternName == "SPELLLOGABSORBOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "absorb", }	elseif patternName == "SPELLLOGABSORBSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "absorb", }	elseif patternName == "SPELLLOGABSORBSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "absorb", }	elseif patternName == "SPELLMISSOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "miss", }	elseif patternName == "SPELLMISSOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "miss", }	elseif patternName == "SPELLMISSSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "miss", }	elseif patternName == "SPELLMISSSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "miss", }	elseif patternName == "SPELLPARRIEDOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "parry", }	elseif patternName == "SPELLPARRIEDOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "parry", }	elseif patternName == "SPELLPARRIEDSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "parry", }	elseif patternName == "SPELLPARRIEDSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "parry", }	elseif patternName == "SPELLREFLECTOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "reflect", }	elseif patternName == "SPELLREFLECTOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "reflect", }	elseif patternName == "SPELLREFLECTSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "reflect", }	elseif patternName == "SPELLREFLECTSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "reflect", }	elseif patternName == "SPELLRESISTOTHEROTHER" then		patternInfo = { "miss", 1, 3, 2, "resist", }	elseif patternName == "SPELLRESISTOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, 2, "resist", }	elseif patternName == "SPELLRESISTSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 2, 1, "resist", }	elseif patternName == "SPELLRESISTSELFSELF" then		patternInfo = { "miss", ParserLib_SELF, ParserLib_SELF, 1, "resist", }	elseif patternName == "VSABSORBOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "absorb", }	elseif patternName == "VSABSORBOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "absorb", }	elseif patternName == "VSABSORBSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "absorb", }	elseif patternName == "VSBLOCKOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "block", }	elseif patternName == "VSBLOCKOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "block", }	elseif patternName == "VSBLOCKSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "block", }	elseif patternName == "VSDEFLECTOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "deflect", }	elseif patternName == "VSDEFLECTOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "deflect", }	elseif patternName == "VSDEFLECTSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "deflect", }	elseif patternName == "VSDODGEOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "dodge", }	elseif patternName == "VSDODGEOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "dodge", }	elseif patternName == "VSDODGESELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "dodge", }	elseif patternName == "VSEVADEOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "evade", }	elseif patternName == "VSEVADEOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "evade", }	elseif patternName == "VSEVADESELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "evade", }	elseif patternName == "VSIMMUNEOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "immune", }	elseif patternName == "VSIMMUNEOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "immune", }	elseif patternName == "VSIMMUNESELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "immune", }	elseif patternName == "VSPARRYOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "parry", }	elseif patternName == "VSPARRYOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "parry", }	elseif patternName == "VSPARRYSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "parry", }	elseif patternName == "VSRESISTOTHEROTHER" then		patternInfo = { "miss", 1, 2, ParserLib_MELEE, "resist", }	elseif patternName == "VSRESISTOTHERSELF" then		patternInfo = { "miss", 1, ParserLib_SELF, ParserLib_MELEE, "resist", }	elseif patternName == "VSRESISTSELFOTHER" then		patternInfo = { "miss", ParserLib_SELF, 1, ParserLib_MELEE, "resist", }		elseif patternName == "FACTION_STANDING_CHANGED" then		patternInfo = { "reputation", 2, nil, 1, nil, }	elseif patternName == "FACTION_STANDING_DECREASED" then		patternInfo = { "reputation", 1, 2, nil, true, }	elseif patternName == "FACTION_STANDING_INCREASED" then		patternInfo = { "reputation", 1, 2, nil, nil, }	end		if not patternInfo then		-- self:Print("LoadPatternInfo(): Cannot find " .. patternName ); -- debug		return	end		local pattern = getglobal(patternName);	-- Get the pattern from GlobalStrings.lua		-- Add a function to fix some global strings.	if FixGlobalString then		local fixPattern = FixGlobalString(patternName, pattern);		if pattern ~= fixPattern then			--self:Print("PP : "..pattern)  -- debug			--self:Print("FP : "..fixPattern)  -- debug			setglobal(patternName, fixPattern);			pattern = fixPattern		end	end		-- How many regexp tokens in this pattern?	local tc = 0	for _ in string.gmatch(pattern, "%%%d?%$?([sd])") do tc = tc + 1 end		-- Convert string.format tokens into LUA regexp tokens.	pattern = { self:ConvertPattern(pattern, true) }			local n = table.getn(pattern)		if n > 1 then	-- Extra return values are the remapped token sequences.			for j in pairs(patternInfo) do			if type(patternInfo[j]) == "number" and patternInfo[j] < 100 then				patternInfo[j] = pattern[patternInfo[j]+1]	-- Remap to correct token sequence.			end		end			end		patternInfo.tc = tc	patternInfo.pattern = pattern[1]		return patternInfoend-- Fields of the patternTable.lib.infoMap = {	hit = { "source", "victim", "skill", "amount", "element", "isCrit", "isDOT", "isSplit" },	heal = { "source", "victim", "skill", "amount", "isCrit", "isDOT" },	miss = { "source", "victim", "skill", "missType" },	death = { "victim", "source", "skill", "isItem" },	debuff = { "victim", "skill", "amountRank" },	buff = { "victim", "skill", "amountRank" },	fade = { "victim", "skill" },	cast = { "source", "skill", "victim", "isBegin", "isPerform" },		gain = { "source", "victim", "skill", "amount", "attribute" },	drain = { "source", "victim", "skill", "amount", "attribute" },	leech = { "source", "victim", "skill", "amount", "attribute", "sourceGained", "amountGained", "attributeGained" },	dispel = { "victim", "skill", "source", "isFailed" },	extraattack = { "victim", "skill", "amount" },	environment = { "victim", "amount", "damageType" },	experience = { "amount", "source", "bonusAmount", "bonusType", "penaltyAmount", "penaltyType", "amountRaidPenalty", "amountGroupBonus", "victim" },	reputation = { "faction", "amount", "rank", "isNegative" },	feedpet = { "victim", "item" },	enchant = { "source", "victim", "skill", "item" },	fail = { "source", "skill", "reason" },	interrupt = { "source", "victim", "skill" },	create = { "source", "item" },	honor = { "amount", "source", "sourceRank" }, -- if amount == nil then isDishonor = true.	durability = { "source", "skill", "victim", "item" }, -- is not item then isAllItems = true 	unknown = { "message" },	}function lib:GetInfoFieldName(infoType, fieldIndex)	if self.infoMap[infoType] then		return self.infoMap[infoType][fieldIndex-1]	-- Skip the first field in patternTable which is 'type'.	endend----------------------------------      Load this bitch!      ----------------------------------libobj:Register(lib)