Quantcast

core.lua -> Core.lua. This has been annoying me for ages. :)

John Pasula [03-24-11 - 13:35]
core.lua -> Core.lua.  This has been annoying me for ages. :)
Filename
AckisRecipeList.toc
Core.lua
core.lua
diff --git a/AckisRecipeList.toc b/AckisRecipeList.toc
index cdbb959..0690634 100644
--- a/AckisRecipeList.toc
+++ b/AckisRecipeList.toc
@@ -65,7 +65,7 @@ locale.xml
 # Constants should be loaded first - many files use them in their main chunk.
 Constants.lua

-core.lua
+Core.lua
 Recipe.lua
 Config.lua
 Waypoint.lua
diff --git a/Core.lua b/Core.lua
new file mode 100644
index 0000000..0774586
--- /dev/null
+++ b/Core.lua
@@ -0,0 +1,1466 @@
+--[[
+************************************************************************
+core.lua
+Core functions for Ackis Recipe List
+************************************************************************
+File date: @file-date-iso@
+File hash: @file-abbreviated-hash@
+Project hash: @project-abbreviated-hash@
+Project version: @project-version@
+************************************************************************
+Please see http://www.wowace.com/addons/arl/ for more information.
+************************************************************************
+This source code is released under All Rights Reserved.
+************************************************************************
+--- Ackis Recipe List provides functionality to scan your professions.
+-- It will determine which recipes you are missing.
+-- @class file
+-- @name core.lua
+-- @release 2.0
+************************************************************************
+]]
+
+-------------------------------------------------------------------------------
+-- Localized Lua globals.
+-------------------------------------------------------------------------------
+local _G = getfenv(0)
+
+-- Functions
+local pairs, ipairs = _G.pairs, _G.ipairs
+local select = _G.select
+local tonumber, tostring = _G.tonumber, _G.tostring
+local type = _G.type
+
+-- Libraries
+local bit = _G.bit
+local string = _G.string
+local table = _G.table
+
+-------------------------------------------------------------------------------
+-- AddOn namespace.
+-------------------------------------------------------------------------------
+local FOLDER_NAME, private = ...
+private.addon_name = "Ackis Recipe List"
+
+local LibStub	= _G.LibStub
+local addon	= LibStub("AceAddon-3.0"):NewAddon(private.addon_name, "AceConsole-3.0", "AceEvent-3.0")
+_G.AckisRecipeList = addon
+
+--@alpha@
+_G.ARL = addon
+--@end-alpha@
+
+local L		= LibStub("AceLocale-3.0"):GetLocale(private.addon_name)
+local BFAC 	= LibStub("LibBabble-Faction-3.0"):GetLookupTable()
+
+local debugger	= _G.tekDebug and _G.tekDebug:GetFrame(private.addon_name)
+
+private.build_num = select(2, _G.GetBuildInfo())
+
+private.custom_list	= {}
+private.mob_list	= {}
+private.quest_list	= {}
+private.recipe_list	= {}
+private.reputation_list	= {}
+private.trainer_list	= {}
+private.seasonal_list	= {}
+private.vendor_list	= {}
+private.location_list	= {}
+private.acquire_list	= {}
+
+------------------------------------------------------------------------------
+-- Constants.
+------------------------------------------------------------------------------
+local PROFESSION_INIT_FUNCS = {}
+
+------------------------------------------------------------------------------
+-- Database tables
+------------------------------------------------------------------------------
+local AllSpecialtiesTable = {}
+local SpecialtyTable
+
+-- Filter flags and acquire types - defined in Constants.lua
+local F 	= private.filter_flags
+local A		= private.acquire_types
+
+-- Global Frame Variables
+addon.optionsFrame = {}
+
+-------------------------------------------------------------------------------
+-- Check to see if we have mandatory libraries loaded. If not, notify the user
+-- which are missing and return.
+-------------------------------------------------------------------------------
+local MissingLibraries
+do
+	local REQUIRED_LIBS = {
+		"AceLocale-3.0",
+		"LibBabble-Boss-3.0",
+		"LibBabble-Faction-3.0",
+		"LibBabble-Zone-3.0",
+	}
+	function MissingLibraries()
+		local missing = false
+
+		for idx, lib in ipairs(REQUIRED_LIBS) do
+			if not LibStub:GetLibrary(lib, true) then
+				missing = true
+				addon:Print(L["MISSING_LIBRARY"]:format(lib))
+			end
+		end
+		return missing
+	end
+end -- do
+
+if MissingLibraries() then
+	--@debug@
+	addon:Print("You are using a development version of ARL.  As per WowAce standards, externals are not set up.  You will have to install all necessary libraries in order for the addon to function correctly.")
+	--@end-debug@
+	_G.AckisRecipeList = nil
+	return
+end
+
+-------------------------------------------------------------------------------
+-- Define the static popups we're going to call when people haven't scanned or
+-- when current filters are blocking all recipes from being displayed.
+-------------------------------------------------------------------------------
+_G.StaticPopupDialogs["ARL_NOTSCANNED"] = {
+	text = L["NOTSCANNED"],
+	button1 = _G.OKAY,
+	timeout = 0,
+	exclusive = 1,
+	whileDead = 1,
+	hideOnEscape = 1
+}
+
+_G.StaticPopupDialogs["ARL_ALLFILTERED"] = {
+	text = L["ALL_FILTERED"],
+	button1 = _G.OKAY,
+	timeout = 0,
+	exclusive = 1,
+	whileDead = 1,
+	hideOnEscape = 1
+}
+
+_G.StaticPopupDialogs["ARL_ALLKNOWN"] = {
+	text = L["ARL_ALLKNOWN"],
+	button1 = _G.OKAY,
+	timeout = 0,
+	exclusive = 1,
+	whileDead = 1,
+	hideOnEscape = 1
+}
+
+_G.StaticPopupDialogs["ARL_ALLEXCLUDED"] = {
+	text = L["ARL_ALLEXCLUDED"],
+	button1 = _G.OKAY,
+	timeout = 0,
+	exclusive = 1,
+	whileDead = 1,
+	hideOnEscape = 1
+}
+
+_G.StaticPopupDialogs["ARL_SEARCHFILTERED"] = {
+	text = L["ARL_SEARCHFILTERED"],
+	button1 = _G.OKAY,
+	timeout = 0,
+	exclusive = 1,
+	whileDead = 1,
+	hideOnEscape = 1
+}
+
+-------------------------------------------------------------------------------
+-- Close all possible pop-up windows
+-------------------------------------------------------------------------------
+function addon:ClosePopups()
+	_G.StaticPopup_Hide("ARL_NOTSCANNED")
+	_G.StaticPopup_Hide("ARL_ALLFILTERED")
+	_G.StaticPopup_Hide("ARL_ALLKNOWN")
+	_G.StaticPopup_Hide("ARL_ALLEXCLUDED")
+	_G.StaticPopup_Hide("ARL_SEARCHFILTERED")
+end
+
+-------------------------------------------------------------------------------
+-- Functions common to most files in the AddOn.
+-------------------------------------------------------------------------------
+function private.SetTextColor(color_code, text)
+	return ("|cff%s%s|r"):format(color_code or "ffffff", text)
+end
+
+-------------------------------------------------------------------------------
+-- Debugger.
+-------------------------------------------------------------------------------
+function addon:Debug(...)
+	if debugger then
+		debugger:AddMessage(string.format(...))
+	else
+		--@debug@
+		self:Printf(...)
+		--@end-debug@
+	end
+end
+
+do
+	local output = {}
+
+	function addon:DumpMembers(match)
+		table.wipe(output)
+		table.insert(output, "Addon Object members.\n")
+
+		local count = 0
+
+		for key, value in pairs(self) do
+			local val_type = type(value)
+
+			if not match or val_type == match then
+				table.insert(output, ("%s (%s)"):format(key, val_type))
+				count = count + 1
+			end
+		end
+		table.insert(output, ("\n%d found\n"):format(count))
+		self:DisplayTextDump(nil, nil, table.concat(output, "\n"))
+	end
+end	-- do
+
+-------------------------------------------------------------------------------
+-- Initialization functions
+-------------------------------------------------------------------------------
+function addon:OnInitialize()
+	-- Set default options, which are to include everything in the scan
+	local defaults = {
+		global = {
+			-- Saving alts tradeskills (needs to be global so all profiles can access it)
+			tradeskill = {},
+		},
+		profile = {
+			-------------------------------------------------------------------------------
+			-- Frame options
+			-------------------------------------------------------------------------------
+			frameopts = {
+				offsetx = 0,
+				offsety = 0,
+				anchorTo = "",
+				anchorFrom = "",
+				uiscale = 1,
+				small_list_font = true,
+			},
+
+			-------------------------------------------------------------------------------
+			-- Tooltip Options
+			-------------------------------------------------------------------------------
+			tooltip = {
+				scale = 1,
+				acquire_fontsize = 11,
+			},
+			-------------------------------------------------------------------------------
+			-- Sorting Options
+			-------------------------------------------------------------------------------
+			sorting = "Ascending",
+			current_tab = 3,		-- Name tab
+			skill_view = false,		-- Sort the recipes by skill level instead of name?
+
+			-------------------------------------------------------------------------------
+			-- Display Options
+			-------------------------------------------------------------------------------
+			includefiltered = false,
+			includeexcluded = false,
+			closeguionskillclose = false,
+			ignoreexclusionlist = false,
+			scanbuttonlocation = "TR",
+			spelltooltiplocation = "Right",
+			acquiretooltiplocation = "Right",
+			recipes_in_tooltips = true,
+			max_recipes_in_tooltips = 10,
+			hide_tooltip_hint = false,
+			hidepopup = false,
+			minimap = true,
+			worldmap = true,
+			autoscanmap = false,
+			scantrainers = false,
+			scanvendors = false,
+			autoloaddb = false,
+			maptrainer = false,
+			mapvendor = true,
+			mapmob = true,
+			mapquest = true,
+
+			-------------------------------------------------------------------------------
+			-- Text Dump Options
+			-------------------------------------------------------------------------------
+			textdumpformat = "BBCode",
+
+			-------------------------------------------------------------------------------
+			-- Recipe Exclusion
+			-------------------------------------------------------------------------------
+			exclusionlist = {},
+
+			-------------------------------------------------------------------------------
+			-- Filter Options
+			-------------------------------------------------------------------------------
+			filters = {
+				-------------------------------------------------------------------------------
+				-- General Filters
+				-------------------------------------------------------------------------------
+				general = {
+					faction = true,
+					specialty = false,
+					skill = true,
+					known = false,
+					unknown = true,
+					retired = false,
+				},
+				-------------------------------------------------------------------------------
+				-- Obtain Filters
+				-------------------------------------------------------------------------------
+				obtain = {
+					trainer = true,
+					vendor = true,
+					instance = true,
+					raid = true,
+					seasonal = true,
+					quest = true,
+					pvp = true,
+					discovery = true,
+					worlddrop = true,
+					mobdrop = true,
+					achievement = true,
+					expansion0 = true,
+					expansion1 = true,
+					expansion2 = true,
+					expansion3 = true,
+				},
+				-------------------------------------------------------------------------------
+				-- Item Filters (Armor/Weapon)
+				-------------------------------------------------------------------------------
+				item = {
+					armor = {
+						cloth = true,
+						leather = true,
+						mail = true,
+						plate = true,
+						trinket = true,
+						cloak = true,
+						ring = true,
+						necklace = true,
+						shield = true,
+					},
+					weapon = {
+						onehand = true,
+						twohand = true,
+						axe = true,
+						sword = true,
+						mace = true,
+						polearm = true,
+						dagger = true,
+						fist = true,
+						staff = true,
+						wand = true,
+						thrown = true,
+						bow = true,
+						crossbow = true,
+						ammo = true,
+						gun = true,
+					},
+				},
+				-------------------------------------------------------------------------------
+				-- Quality Filters
+				-------------------------------------------------------------------------------
+				quality = {
+					common = true,
+					uncommon = true,
+					rare = true,
+					epic = true,
+				},
+				-------------------------------------------------------------------------------
+				-- Binding Filters
+				-------------------------------------------------------------------------------
+				binding = {
+					itemboe = true,
+					itembop = true,
+					recipebop = true,
+					recipeboe = true,
+				},
+				-------------------------------------------------------------------------------
+				-- Player Role Filters
+				-------------------------------------------------------------------------------
+				player = {
+					melee = true,
+					tank = true,
+					healer = true,
+					caster = true,
+				},
+				-------------------------------------------------------------------------------
+				-- Reputation Filters
+				-------------------------------------------------------------------------------
+				rep = {
+					aldor = true,
+					scryer = true,
+					argentdawn = true,
+					ashtonguedeathsworn = true,
+					cenarioncircle = true,
+					cenarionexpedition = true,
+					consortium = true,
+					hellfire = true,
+					keepersoftime = true,
+					nagrand = true,
+					lowercity = true,
+					scaleofthesands = true,
+					shatar = true,
+					shatteredsun = true,
+					sporeggar = true,
+					thoriumbrotherhood = true,
+					timbermaw = true,
+					violeteye = true,
+					zandalar = true,
+					argentcrusade = true,
+					frenzyheart = true,
+					ebonblade = true,
+					kirintor = true,
+					sonsofhodir = true,
+					kaluak = true,
+					oracles = true,
+					wyrmrest = true,
+					wrathcommon1 = true,
+					wrathcommon2 = true,
+					wrathcommon3 = true,
+					wrathcommon4 = true,
+					wrathcommon5 = true,
+					ashenverdict = true,
+					catacommon1 = true,
+					catacommon2 = true,
+					guardiansofhyjal = true,
+					ramkahen = true,
+					earthenring = true,
+					therazane = true,
+				},
+				-------------------------------------------------------------------------------
+				-- Class Filters
+				-------------------------------------------------------------------------------
+				classes = {
+					deathknight = true,
+					druid = true,
+					hunter = true,
+					mage = true,
+					paladin = true,
+					priest = true,
+					rogue = true,
+					shaman = true,
+					warlock = true,
+					warrior = true,
+				},
+			}
+		}
+	}
+	self.db = LibStub("AceDB-3.0"):New("ARLDB2", defaults)
+
+	if not self.db then
+		self:Print("Error: Database not loaded correctly.  Please exit out of WoW and delete the ARL database file (AckisRecipeList.lua) found in: \\World of Warcraft\\WTF\\Account\\<Account Name>>\\SavedVariables\\")
+		return
+	end
+	local version = _G.GetAddOnMetadata("AckisRecipeList", "Version")
+	local debug_version = false
+	local alpha_version = false
+
+	-- @debug@
+	debug_version = true
+	-- @end-debug
+
+	-- @alpha@
+	alpha_version = true
+	-- @end-alpha@
+
+	version = debug_version and "Devel" or (alpha_version and version .. "-Alpha") or version
+
+	self.version = version
+
+	self:SetupOptions()
+
+	-- Register slash commands
+	self:RegisterChatCommand("arl", "ChatCommand")
+	self:RegisterChatCommand("ackisrecipelist", "ChatCommand")
+
+	-------------------------------------------------------------------------------
+	-- Create the scan button
+	-------------------------------------------------------------------------------
+	local scan_button = _G.CreateFrame("Button", nil, _G.UIParent, "UIPanelButtonTemplate")
+	scan_button:SetHeight(20)
+
+	scan_button:RegisterForClicks("LeftButtonUp")
+	scan_button:SetScript("OnClick",
+			      function(self, button, down)
+				      local cur_profession = _G.GetTradeSkillLine()
+				      local MainPanel = addon.Frame
+				      local prev_profession
+
+				      if MainPanel then
+					      prev_profession = MainPanel.prof_name or private.ordered_professions[MainPanel.profession]
+				      end
+
+				      local shift_key = _G.IsShiftKeyDown()
+				      local alt_key = _G.IsAltKeyDown()
+				      local ctrl_key = _G.IsControlKeyDown()
+
+				      if shift_key and not alt_key and not ctrl_key then
+					      addon:Scan(true)
+				      elseif alt_key and not shift_key and not ctrl_key then
+					      addon:ClearWaypoints()
+				      elseif ctrl_key and not shift_key and not alt_key then
+					      local current_prof = _G.GetTradeSkillLine()
+					      addon:DumpProfession(current_prof)
+				      elseif not shift_key and not alt_key and not ctrl_key then
+					      if MainPanel and MainPanel:IsVisible() and prev_profession == cur_profession then
+						      MainPanel:Hide()
+					      else
+						      addon:Scan(false)
+						      addon:AddWaypoint()
+					      end
+				      end
+			      end)
+
+	scan_button:SetScript("OnEnter",
+			      function(self)
+				      local tooltip = _G.GameTooltip
+
+				      _G.GameTooltip_SetDefaultAnchor(tooltip, self)
+				      tooltip:SetText(L["SCAN_RECIPES_DESC"])
+				      tooltip:Show()
+			      end)
+	scan_button:SetScript("OnLeave", function() _G.GameTooltip:Hide() end)
+	scan_button:SetText(L["Scan"])
+
+	self.scan_button = scan_button
+
+	-------------------------------------------------------------------------------
+	-- Populate the profession initialization functions.
+	-------------------------------------------------------------------------------
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51304)] = addon.InitAlchemy
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51300)] = addon.InitBlacksmithing
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51296)] = addon.InitCooking
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51313)] = addon.InitEnchanting
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51306)] = addon.InitEngineering
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(45542)] = addon.InitFirstAid
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51302)] = addon.InitLeatherworking
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(32606)] = addon.InitSmelting
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51309)] = addon.InitTailoring
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51311)] = addon.InitJewelcrafting
+	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(45363)] = addon.InitInscription
+	PROFESSION_INIT_FUNCS[private.runeforging_name] = addon.InitRuneforging
+
+	-------------------------------------------------------------------------------
+	-- Hook GameTooltip so we can show information on mobs that drop/sell/train
+	-------------------------------------------------------------------------------
+        _G.GameTooltip:HookScript("OnTooltipSetUnit",
+		       function(self)
+			       if not addon.db.profile.recipes_in_tooltips then
+				       return
+			       end
+			       local name, unit = self:GetUnit()
+
+			       if not unit then
+				       return
+			       end
+			       local guid = _G.UnitGUID(unit)
+
+			       if not guid then
+				       return
+			       end
+			       local GUID = tonumber(string.sub(guid, -12, -9), 16)
+			       local unit = private.mob_list[GUID] or private.vendor_list[GUID] or private.trainer_list[GUID]
+
+			       if not unit or not unit.item_list then
+				       return
+			       end
+			       local player = private.Player
+			       local recipe_list = private.recipe_list
+			       local shifted = _G.IsShiftKeyDown()
+			       local count = 0
+
+			       for spell_id in pairs(unit.item_list) do
+				       local recipe = recipe_list[spell_id]
+				       local recipe_prof = _G.GetSpellInfo(recipe.profession)
+				       local scanned = player.has_scanned[recipe_prof]
+
+				       if scanned then
+					       local skill_level = player.professions[recipe_prof]
+					       local has_level = skill_level and (type(skill_level) == "boolean" and true or skill_level >= recipe.skill_level)
+
+					       if ((not recipe:HasState("KNOWN") and has_level) or shifted) and player:HasRecipeFaction(recipe) then
+						       local _, _, _, hex = _G.GetItemQualityColor(recipe.quality)
+
+						       self:AddLine(("%s: %s%s|r (%d)"):format(recipe.profession, hex, recipe.name, recipe.skill_level))
+						       count = count + 1
+					       end
+				       end
+
+				       if count >= addon.db.profile.max_recipes_in_tooltips then
+					       break
+				       end
+			       end
+		       end)
+end
+
+---Function run when the addon is enabled.  Registers events and pre-loads certain variables.
+function addon:OnEnable()
+	self:RegisterEvent("TRADE_SKILL_SHOW")	-- Make addon respond to the tradeskill windows being shown
+	self:RegisterEvent("TRADE_SKILL_CLOSE")	-- Addon responds to tradeskill windows being closed.
+	self:RegisterEvent("TRADE_SKILL_UPDATE")
+
+	if addon.db.profile.scantrainers then
+		self:RegisterEvent("TRAINER_SHOW")
+	end
+
+	if addon.db.profile.scanvendors then
+		self:RegisterEvent("MERCHANT_SHOW")
+	end
+
+	-------------------------------------------------------------------------------
+	-- Set the parent and scripts for addon.scan_button.
+	-------------------------------------------------------------------------------
+	local scan_button = self.scan_button
+
+	if _G.Skillet and _G.Skillet:IsActive() then
+		scan_button:SetParent(_G.SkilletFrame)
+		_G.Skillet:AddButtonToTradeskillWindow(scan_button)
+		scan_button:SetWidth(80)
+	elseif _G.MRTAPI then
+		_G.MRTAPI:RegisterHandler("TradeSkillWindowOnShow",
+						function()
+							scan_button:SetParent(_G.MRTSkillFrame)
+							scan_button:ClearAllPoints()
+							scan_button:SetPoint("RIGHT", _G.MRTSkillFrameCloseButton, "LEFT", 4, 0)
+							scan_button:SetWidth(scan_button:GetTextWidth() + 10)
+							scan_button:Show()
+						end)
+  	elseif _G.ATSWFrame then
+		scan_button:SetParent(_G.ATSWFrame)
+		scan_button:ClearAllPoints()
+
+		if _G.TradeJunkieMain and _G.TJ_OpenButtonATSW then
+			scan_button:SetPoint("RIGHT", _G.TJ_OpenButtonATSW, "LEFT", 0, 0)
+		else
+			scan_button:SetPoint("RIGHT", _G.ATSWOptionsButton, "LEFT", 0, 0)
+		end
+		scan_button:SetHeight(_G.ATSWOptionsButton:GetHeight())
+		scan_button:SetWidth(_G.ATSWOptionsButton:GetWidth())
+	elseif _G.CauldronFrame then
+		scan_button:SetParent(_G.CauldronFrame)
+		scan_button:ClearAllPoints()
+		scan_button:SetPoint("TOP", _G.CauldronFrame, "TOPRIGHT", -58, -52)
+		scan_button:SetWidth(90)
+	elseif _G.BPM_ShowTrainerFrame then
+		scan_button:SetParent(_G.BPM_ShowTrainerFrame)
+		scan_button:ClearAllPoints()
+		scan_button:SetPoint("RIGHT", _G.BPM_ShowTrainerFrame, "LEFT", 4, 0)
+		scan_button:SetWidth(scan_button:GetTextWidth() + 10)
+		scan_button:Show()
+	end
+
+	local buttonparent = scan_button:GetParent()
+	local framelevel = buttonparent:GetFrameLevel()
+	local framestrata = buttonparent:GetFrameStrata()
+
+	-- Set the frame level of the button to be 1 deeper than its parent
+	scan_button:SetFrameLevel(framelevel + 1)
+	scan_button:SetFrameStrata(framestrata)
+	scan_button:Enable()
+
+	-- Add an option so that ARL will work with Manufac
+	if _G.Manufac then
+		_G.Manufac.options.args.ARLScan = {
+			type = 'execute',
+			name = L["Scan"],
+			desc = L["SCAN_RECIPES_DESC"],
+			func = function() addon:Scan(false) end,
+			order = 550,
+		}
+	end
+	private.Player:Initialize()
+
+	-------------------------------------------------------------------------------
+	-- Initialize the SpecialtyTable and AllSpecialtiesTable.
+	-------------------------------------------------------------------------------
+	do
+		local AlchemySpec = {
+			[_G.GetSpellInfo(28674)] = 28674,
+			[_G.GetSpellInfo(28678)] = 28678,
+			[_G.GetSpellInfo(28676)] = 28676,
+		}
+
+		local BlacksmithSpec = {
+			[_G.GetSpellInfo(9788)] = 9788,		-- Armorsmith
+			[_G.GetSpellInfo(17041)] = 17041,	-- Master Axesmith
+			[_G.GetSpellInfo(17040)] = 17040,	-- Master Hammersmith
+			[_G.GetSpellInfo(17039)] = 17039,	-- Master Swordsmith
+			[_G.GetSpellInfo(9787)] = 9787,		-- Weaponsmith
+		}
+
+		local EngineeringSpec = {
+			[_G.GetSpellInfo(20219)] = 20219, -- Gnomish
+			[_G.GetSpellInfo(20222)] = 20222, -- Goblin
+		}
+
+		local LeatherworkSpec = {
+			[_G.GetSpellInfo(10657)] = 10657, -- Dragonscale
+			[_G.GetSpellInfo(10659)] = 10659, -- Elemental
+			[_G.GetSpellInfo(10661)] = 10661, -- Tribal
+		}
+
+		local TailorSpec = {
+			[_G.GetSpellInfo(26797)] = 26797, -- Spellfire
+			[_G.GetSpellInfo(26801)] = 26801, -- Shadoweave
+			[_G.GetSpellInfo(26798)] = 26798, -- Primal Mooncloth
+		}
+
+		SpecialtyTable = {
+			[_G.GetSpellInfo(51304)] = AlchemySpec,
+			[_G.GetSpellInfo(51300)] = BlacksmithSpec,
+			[_G.GetSpellInfo(51306)] = EngineeringSpec,
+			[_G.GetSpellInfo(51302)] = LeatherworkSpec,
+			[_G.GetSpellInfo(51309)] = TailorSpec,
+		}
+
+		-- Populate the Specialty table with all Specialties, adding alchemy even though no recipes have alchemy filters
+		for i in pairs(AlchemySpec) do AllSpecialtiesTable[i] = true end
+		for i in pairs(BlacksmithSpec) do AllSpecialtiesTable[i] = true end
+		for i in pairs(EngineeringSpec) do AllSpecialtiesTable[i] = true end
+		for i in pairs(LeatherworkSpec) do AllSpecialtiesTable[i] = true end
+		for i in pairs(TailorSpec) do AllSpecialtiesTable[i] = true end
+	end	-- do
+end
+
+---Run when the addon is disabled. Ace3 takes care of unregistering events, etc.
+function addon:OnDisable()
+	if addon.Frame then
+		addon.Frame:Hide()
+	end
+
+	-- Remove the option from Manufac
+	if _G.Manufac then
+		_G.Manufac.options.args.ARLScan = nil
+	end
+end
+
+-------------------------------------------------------------------------------
+-- Event handling functions
+-------------------------------------------------------------------------------
+
+---Event used for datamining when a trainer is shown.
+function addon:TRAINER_SHOW()
+	self:ScanTrainerData(true)
+end
+
+---Event used for datamining when a vendor is shown.
+function addon:MERCHANT_SHOW()
+	self:ScanVendor()
+end
+
+do
+	local GetTradeSkillListLink = _G.GetTradeSkillListLink
+	local UnitName = _G.UnitName
+	local GetRealmName = _G.GetRealmName
+
+	function addon:TRADE_SKILL_SHOW()
+		local is_linked = _G.IsTradeSkillLinked() or _G.IsTradeSkillGuild()
+		local tradelink = GetTradeSkillListLink()
+
+		local pname = UnitName("player")
+		local prealm = GetRealmName()
+		local tradename = _G.GetTradeSkillLine()
+
+		-- Actual alt information saved here. -Torhal
+		addon.db.global.tradeskill = addon.db.global.tradeskill or {}
+		addon.db.global.tradeskill[prealm] = addon.db.global.tradeskill[prealm] or {}
+		addon.db.global.tradeskill[prealm][pname] = addon.db.global.tradeskill[prealm][pname] or {}
+
+		-- If this is our own skill, save it. Otherwise, make sure it's gone.
+		addon.db.global.tradeskill[prealm][pname][tradename] = (not is_linked) and tradelink or nil
+
+		local scan_button = self.scan_button
+		local scan_parent = scan_button:GetParent()
+
+		if not scan_parent or scan_parent == _G.UIParent then
+			scan_button:SetParent(_G.TradeSkillFrame)
+			scan_parent = scan_button:GetParent()
+		end
+
+		if scan_parent == _G.TradeSkillFrame then
+			scan_button:ClearAllPoints()
+
+			local loc = addon.db.profile.scanbuttonlocation
+
+			if loc == "TR" then
+				scan_button:SetPoint("RIGHT", _G.TradeSkillFrameCloseButton, "LEFT",4,0)
+			elseif loc == "TL" then
+				scan_button:SetPoint("LEFT", _G.TradeSkillFramePortrait, "RIGHT",2,12)
+			elseif loc == "BR" then
+				scan_button:SetPoint("TOP", _G.TradeSkillCancelButton, "BOTTOM",0,-5)
+			elseif loc == "BL" then
+				scan_button:SetPoint("TOP", _G.TradeSkillCreateAllButton, "BOTTOM",0,-5)
+			end
+			scan_button:SetWidth(scan_button:GetTextWidth() + 10)
+		end
+		scan_button:Show()
+	end
+end
+
+function addon:TRADE_SKILL_CLOSE()
+	if self.Frame and addon.db.profile.closeguionskillclose then
+		self.Frame:Hide()
+	end
+
+	if not _G.Skillet then
+		addon.scan_button:Hide()
+	end
+end
+
+do
+	local last_update = 0
+	local updater = _G.CreateFrame("Frame", nil, _G.UIParent)
+
+	updater:Hide()
+	updater:SetScript("OnUpdate",
+			  function(self, elapsed)
+				  last_update = last_update + elapsed
+
+				  if last_update >= 0.5 then
+					  local profession = _G.GetTradeSkillLine()
+
+					  if profession ~= "UNKNOWN" then
+						  addon:Scan(false, true)
+					  end
+					  self:Hide()
+				  end
+			  end)
+
+	function addon:TRADE_SKILL_UPDATE(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
+		if not self.Frame or not self.Frame:IsVisible() then
+			return
+		end
+
+		if not updater:IsVisible() then
+			last_update = 0
+			updater:Show()
+		end
+	end
+end
+
+-------------------------------------------------------------------------------
+-- ARL Logic Functions
+-------------------------------------------------------------------------------
+function addon:InitializeProfession(profession)
+	if not profession then
+		--@alpha@
+		addon:Print("nil profession passed to InitializeProfession()")
+		--@end-alpha@
+		return
+	end
+
+	if profession == private.professions["Smelting"] then
+		profession = private.mining_name
+	end
+	local func = PROFESSION_INIT_FUNCS[profession]
+
+	if func then
+		func(addon)
+		PROFESSION_INIT_FUNCS[profession] = nil
+	end
+end
+
+do
+	local fa = _G.GetSpellInfo(45542)
+
+	-- Code snippet stolen from GearGuage by Torhal and butchered by Ackis
+	local function StrSplit(input)
+		if not input then return nil, nil end
+		local arg1, arg2, var1
+
+		arg1, var1 = input:match("^([^%s]+)%s*(.*)$")
+		arg1 = (arg1 and arg1:lower() or input:lower())
+
+		if var1 then
+			-- Small hack to get code to work with first aid.
+			if var1:lower() == fa:lower() then
+				arg2 = var1
+			else
+				local var2
+				arg2, var2 = var1:match("^([^%s]+)%s*(.*)$")
+				arg2 = (arg2 and arg2:lower() or var1:lower())
+			end
+		end
+		return arg1, arg2
+	end
+
+	-- Determines what to do when the slash command is called.
+	function addon:ChatCommand(input)
+
+		local arg1, arg2 = StrSplit(input)
+
+		-- Open About panel if there's no parameters or if we do /arl about
+		if not arg1 or (arg1 and arg1:trim() == "") or arg1 == L["Sorting"]:lower() or arg1 == L["Sort"]:lower() or arg1 == _G.DISPLAY:lower() then
+			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
+		elseif arg1 == L["About"]:lower() then
+			if self.optionsFrame["About"] then
+				_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["About"])
+			else
+				_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
+			end
+		elseif arg1 == L["Profile"]:lower() then
+			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Profiles"])
+		elseif arg1 == L["Documentation"]:lower() then
+			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Documentation"])
+		elseif arg1 == L["Scan"]:lower() then
+			if not arg2 then
+				self:Print(L["COMMAND_LINE_SCAN"])
+			else
+				_G.CastSpellByName(arg2)
+
+				if self.Frame and self.Frame:IsVisible() then
+					self.Frame:Hide()
+				else
+					self:Scan(false, false)
+				end
+			end
+		elseif arg1 == "scanprof" then
+			self:ScanProfession("all")
+		elseif arg1 == "tradelinks" then
+			self:GenerateLinks()
+		else
+			-- What happens when we get here?
+			LibStub("AceConfigCmd-3.0"):HandleCommand("arl", "Ackis Recipe List", arg1)
+		end
+	end
+end
+
+--- Public API function to initialize all of the lookup lists - self-nils once run.
+-- @name AckisRecipeList:InitializeLookups()
+-- @usage if AckisRecipeList.InitializeLookups then AckisRecipeList:InitializeLookups() end
+function addon:InitializeLookups()
+	self:InitCustom(private.custom_list)
+	self:InitMob(private.mob_list)
+	self:InitQuest(private.quest_list)
+	self:InitReputation(private.reputation_list)
+	self:InitTrainer(private.trainer_list)
+	self:InitSeasons(private.seasonal_list)
+	self:InitVendor(private.vendor_list)
+
+	self.InitializeLookups = nil
+end
+
+-------------------------------------------------------------------------------
+-- Recipe Scanning Functions
+-------------------------------------------------------------------------------
+do
+	-- List of tradeskill headers, used in addon:Scan()
+	local header_list = {}
+
+	-- Toggles a recipe ot known state if it's your own
+	local function togglerecipe(recipe, is_linked)
+		if not is_linked then
+			recipe:AddState("KNOWN")
+			recipe:RemoveState("LINKED")
+		else
+			recipe:AddState("LINKED")
+		end
+	end
+
+	--- Causes a scan of the tradeskill to be conducted. Function called when the scan button is clicked.   Parses recipes and displays output
+	-- @name AckisRecipeList:Scan
+	-- @usage AckisRecipeList:Scan(true)
+	-- @param textdump Boolean indicating if we want the output to be a text dump, or if we want to use the ARL GUI
+	-- @return A frame with either the text dump, or the ARL frame
+	function addon:Scan(textdump, is_refresh)
+		local current_prof, prof_level = _G.GetTradeSkillLine()
+
+		-- Bail if we haven't opened a tradeskill frame.
+		if current_prof == "UNKNOWN" then
+			self:Print(L["OpenTradeSkillWindow"])
+			return
+		end
+		local player = private.Player
+		player:SetProfessions()
+
+		-- Set the current profession level, and update the cached data.
+		private.current_profession_scanlevel = prof_level
+
+		-- Make sure we're only updating a profession the character actually knows - this could be a scan from a tradeskill link.
+		local is_linked = _G.IsTradeSkillLinked() or _G.IsTradeSkillGuild()
+
+		if not is_linked then
+			player.has_scanned[current_prof] = true
+		end
+
+		-- Get the current profession Specialty
+		local specialty = SpecialtyTable[current_prof]
+
+		for index = 1, 25, 1 do
+			local spell_name = _G.GetSpellBookItemName(index, _G.BOOKTYPE_SPELL)
+
+			if not spell_name or index == 25 then
+				player["Specialty"] = nil
+				break
+			elseif specialty and specialty[spell_name] then
+				player["Specialty"] = specialty[spell_name]
+				break
+			end
+		end
+
+		if self.InitializeLookups then
+			self:InitializeLookups()
+		end
+		addon:InitializeProfession(current_prof)
+
+		-------------------------------------------------------------------------------
+		-- Scan all recipes and mark the ones we know
+		-------------------------------------------------------------------------------
+		table.wipe(header_list)
+
+		-- Save the current state of the TradeSkillFrame so it can be restored after we muck with it.
+		local have_materials = _G.TradeSkillFrame.filterTbl.hasMaterials
+		local have_skillup = _G.TradeSkillFrame.filterTbl.hasSkillUp
+		local subclass = _G.TradeSkillFrame.filterTbl.subClassValue
+		local slot = _G.TradeSkillFrame.filterTbl.slotValue
+
+		if _G.MRTAPI and _G.MRTAPI:PushFilterSelection() then
+			-- MrTrader saved the state for us
+		else
+			if not _G.Skillet and have_materials then
+				_G.TradeSkillFrame.filterTbl.hasMaterials = false
+				_G.TradeSkillOnlyShowMakeable(false)
+			end
+			if not _G.Skillet and have_skillup then
+				_G.TradeSkillFrame.filterTbl.hasSkillUp = false
+				_G.TradeSkillOnlyShowSkillUps(false)
+			end
+			--UIDropDownMenu_Initialize(TradeSkillFilterDropDown, TradeSkillInvSlotDropDown_Initialize)
+			--UIDropDownMenu_SetSelectedID(TradeSkillFilterDropDown, 1)
+			_G.SetTradeSkillInvSlotFilter(0, 1, 1)
+			_G.TradeSkillUpdateFilterBar()
+			_G.TradeSkillFrame_Update()
+
+			-- Expand all headers so we can see all the recipes there are
+			for i = _G.GetNumTradeSkills(), 1, -1 do
+				local name, tradeType, _, isExpanded = _G.GetTradeSkillInfo(i)
+
+				if tradeType == "header" and not isExpanded then
+					header_list[name] = true
+					_G.ExpandTradeSkillSubClass(i)
+				end
+			end
+		end
+		local recipe_list = private.recipe_list
+		local recipes_found = 0
+		local SF = private.recipe_state_flags
+		local overwritemap = private.spell_overwrite_map
+
+		for i = 1, _G.GetNumTradeSkills() do
+			local tradeName, tradeType = _G.GetTradeSkillInfo(i)
+
+			if tradeType ~= "header" then
+				-- Get the trade skill link for the specified recipe
+				local spell_link = _G.GetTradeSkillRecipeLink(i)
+				-- Spell ID of the recipe being scanned.
+				local spell_string = spell_link:match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)")
+				local spell_id = tonumber(spell_string)
+				local recipe = recipe_list[spell_id]
+
+				if recipe then
+					-- Mark the first rank of the spell as known if we know rank 2 for certain recipes.
+					-- This is only done for recipes which when you learn the higher rank, you lose the
+					-- ability to learn the lower rank.
+
+					-- If we have it in the mapping, set the lower rank spell to known
+					if overwritemap[spell_id] then
+						local overwriterecipe = recipe_list[overwritemap[spell_id]]
+						if overwriterecipe then
+							togglerecipe(overwriterecipe, is_linked)
+						else
+							self:Debug(tradeName .. " " .. overwritemap[spell_id] .. L["MissingFromDB"])
+						end
+					end
+					-- Toggle spell to known
+					togglerecipe(recipe, is_linked)
+					recipes_found = recipes_found + 1
+				else
+					self:Debug(tradeName .. " " .. spell_string .. L["MissingFromDB"])
+				end
+			end
+		end
+
+		-- Close all the headers we've opened
+		-- If Mr Trader is installed use that API
+		if _G.MRTAPI and _G.MRTAPI:PopFilterSelection() then
+			-- MrTrader restored the state for us
+		else
+			-- Collapse all headers that were collapsed before
+			for i = _G.GetNumTradeSkills(), 1, -1 do
+				local name, tradeType, _, isExpanded = _G.GetTradeSkillInfo(i)
+
+				if header_list[name] then
+					_G.CollapseTradeSkillSubClass(i)
+				end
+			end
+
+			-- Restore the state of the things we changed.
+			_G.TradeSkillFrame.filterTbl.hasMaterials = have_materials
+			_G.TradeSkillOnlyShowMakeable(have_materials)
+			_G.TradeSkillFrame.filterTbl.hasSkillUp = have_skillup
+			_G.TradeSkillOnlyShowSkillUps(have_skillup)
+
+			_G.TradeSkillUpdateFilterBar()
+			_G.TradeSkillFrame_Update()
+
+		end
+		player.prev_count = player.foundRecipes
+		player.foundRecipes = recipes_found
+
+		if is_refresh and player.prev_count == recipes_found then
+			return
+		end
+
+		-------------------------------------------------------------------------------
+		-- Update the player's reputation levels.
+		-------------------------------------------------------------------------------
+		player:UpdateReputations()
+
+		-------------------------------------------------------------------------------
+		-- Everything is ready - display the GUI or dump the list to text.
+		-------------------------------------------------------------------------------
+		if textdump then
+			self:DisplayTextDump(recipe_list, current_prof)
+		else
+			if private.InitializeFrame then
+				private.InitializeFrame()
+			end
+			self.Frame:Display(current_prof, is_linked)
+		end
+	end
+end
+
+-------------------------------------------------------------------------------
+-- Text dumping functions
+-------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+--- Creates a new frame with the contents of a text dump so you can copy and paste
+-- Code borrowed from Antiarc (Chatter) with permission
+-- @name AckisRecipeList:DisplayTextDump
+-- @param RecipeDB The database (array) which you wish read data from.
+-- @param profession Which profession are you displaying data for
+-- @param text The text to be dumped
+--------------------------------------------------------------------------------
+do
+	local copy_frame = _G.CreateFrame("Frame", "ARLCopyFrame", _G.UIParent)
+	copy_frame:SetBackdrop({
+				       bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
+				       edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]],
+				       tile = true,
+				       tileSize = 16,
+				       edgeSize = 16,
+				       insets = {
+					       left = 3,
+					       right = 3,
+					       top = 5,
+					       bottom = 3
+				       }
+			       })
+	copy_frame:SetBackdropColor(0, 0, 0, 1)
+	copy_frame:SetWidth(750)
+	copy_frame:SetHeight(400)
+	copy_frame:SetPoint("CENTER", _G.UIParent, "CENTER")
+	copy_frame:SetFrameStrata("DIALOG")
+
+	table.insert(_G.UISpecialFrames, "ARLCopyFrame")
+
+	local scrollArea = _G.CreateFrame("ScrollFrame", "ARLCopyScroll", copy_frame, "UIPanelScrollFrameTemplate")
+	scrollArea:SetPoint("TOPLEFT", copy_frame, "TOPLEFT", 8, -30)
+	scrollArea:SetPoint("BOTTOMRIGHT", copy_frame, "BOTTOMRIGHT", -30, 8)
+
+	local edit_box = _G.CreateFrame("EditBox", nil, copy_frame)
+	edit_box:SetMultiLine(true)
+	edit_box:SetMaxLetters(0)
+	edit_box:EnableMouse(true)
+	edit_box:SetAutoFocus(true)
+	edit_box:SetFontObject("ChatFontNormal")
+	edit_box:SetWidth(650)
+	edit_box:SetHeight(270)
+	edit_box:SetScript("OnEscapePressed",
+			   function()
+				   copy_frame:Hide()
+			   end)
+	edit_box:HighlightText(0)
+
+	scrollArea:SetScrollChild(edit_box)
+
+	local close = _G.CreateFrame("Button", nil, copy_frame, "UIPanelCloseButton")
+	close:SetPoint("TOPRIGHT", copy_frame, "TOPRIGHT")
+
+	copy_frame:Hide()
+
+	function addon:DisplayTextDump(RecipeDB, profession, text)
+		local text = (not RecipeDB and not profession) and text or self:GetTextDump(profession)
+
+		if text ~= "" then
+			edit_box:SetText(text)
+			edit_box:HighlightText(0)
+			edit_box:SetCursorPosition(1)
+			copy_frame:Show()
+		end
+	end
+end	-- do
+
+do
+	-------------------------------------------------------------------------------
+	-- Dumps recipe output in the format requested by the user
+	-------------------------------------------------------------------------------
+	local text_table = {}
+	local acquire_list = {}
+	local ACQUIRE_NAMES = private.acquire_names
+
+	local GetFilterNames
+	do
+		local LC = _G.LOCALIZED_CLASS_NAMES_MALE
+		local FILTER_NAMES
+
+		function GetFilterNames()
+			if not FILTER_NAMES then
+				local is_alliance = (private.Player.faction == "Alliance")
+
+				FILTER_NAMES = {
+					[1]	= BFAC["Alliance"],
+					[2]	= BFAC["Horde"],
+					[3]	= L["Trainer"],
+					[4]	= L["Vendor"],
+					[5]	= _G.INSTANCE,
+					[6]	= _G.RAID,
+					[7]	= _G.EVENTS_LABEL,
+					[8]	= L["Quest"],
+					[9]	= _G.PVP,
+					[10]	= L["World Drop"],
+					[11]	= L["Mob Drop"],
+					[12]	= L["Discovery"],
+					[13]	= L["Retired"],
+					[21]	= LC["DEATHKNIGHT"],
+					[22]	= LC["DRUID"],
+					[23]	= LC["HUNTER"],
+					[24]	= LC["MAGE"],
+					[25]	= LC["PALADIN"],
+					[26]	= LC["PRIEST"],
+					[27]	= LC["SHAMAN"],
+					[28]	= LC["ROGUE"],
+					[29]	= LC["WARLOCK"],
+					[30]	= LC["WARRIOR"],
+					[36]	= L["BOEFilter"],
+					[37]	= L["BOPFilter"],
+					[38]	= L["BOAFilter"],
+					[40]	= L["RecipeBOEFilter"],
+					[41]	= L["RecipeBOPFilter"],
+					[42]	= L["RecipeBOAFilter"],
+					[51]	= _G.MELEE,
+					[52]	= _G.TANK,
+					[53]	= _G.HEALER,
+					[54]	= _G.DAMAGER,
+					[56]	= L["Cloth"],
+					[57]	= L["Leather"],
+					[58]	= L["Mail"],
+					[59]	= L["Plate"],
+					[60]	= L["Cloak"],
+					[61]	= L["Trinket"],
+					[62]	= L["Ring"],
+					[63]	= L["Necklace"],
+					[64]	= L["Shield"],
+					[66]	= L["One Hand"],
+					[67]	= L["Two Hand"],
+					[68]	= L["Axe"],
+					[69]	= L["Sword"],
+					[70]	= L["Mace"],
+					[71]	= L["Polearm"],
+					[72]	= L["Dagger"],
+					[73]	= L["Staff"],
+					[74]	= L["Wand"],
+					[75]	= L["Thrown"],
+					[76]	= L["Bow"],
+					[77]	= L["Crossbow"],
+					[78]	= L["Ammo"],
+					[79]	= L["Fist"],
+					[80]	= L["Gun"],
+					[96]	= BFAC["Argent Dawn"],
+					[97]	= BFAC["Cenarion Circle"],
+					[98]	= BFAC["Thorium Brotherhood"],
+					[99]	= BFAC["Timbermaw Hold"],
+					[100]	= BFAC["Zandalar Tribe"],
+					[101]	= BFAC["The Aldor"],
+					[102]	= BFAC["Ashtongue Deathsworn"],
+					[103]	= BFAC["Cenarion Expedition"],
+					[104]	= (is_alliance and BFAC["Honor Hold"] or BFAC["Thrallmar"]),
+					[105]	= BFAC["The Consortium"],
+					[106]	= BFAC["Keepers of Time"],
+					[107]	= BFAC["Lower City"],
+					[108]	= (is_alliance and BFAC["Kurenai"] or BFAC["The Mag'har"]),
+					[109]	= BFAC["The Scale of the Sands"],
+					[110]	= BFAC["The Scryers"],
+					[111]	= BFAC["The Sha'tar"],
+					[112]	= BFAC["Shattered Sun Offensive"],
+					[113]	= BFAC["Sporeggar"],
+					[114]	= BFAC["The Violet Eye"],
+					[115]	= BFAC["Argent Crusade"],
+					[116]	= BFAC["Frenzyheart Tribe"],
+					[117]	= BFAC["Knights of the Ebon Blade"],
+					[118]	= BFAC["Kirin Tor"],
+					[119]	= BFAC["The Sons of Hodir"],
+					[120]	= BFAC["The Kalu'ak"],
+					[121]	= BFAC["The Oracles"],
+					[122]	= BFAC["The Wyrmrest Accord"],
+					[123]	= (is_alliance and BFAC["The Silver Covenant"] or BFAC["The Sunreavers"]),
+					[124]	= (is_alliance and BFAC["Explorers' League"] or BFAC["The Hand of Vengeance"]),
+					[125]	= (is_alliance and BFAC["Valiance Expedition"] or BFAC["Warsong Offensive"]),
+					[126]	= (is_alliance and BFAC["The Frostborn"] or BFAC["The Taunka"]),
+					[127]	= (is_alliance and BFAC["Alliance Vanguard"] or BFAC["Horde Expedition"]),
+					[128]	= BFAC["The Ashen Verdict"],
+					[129]	= (is_alliance and BFAC["Wildhammer Clan"] or BFAC["Dragonmaw Clan"]),
+					[130]	= (is_alliance and BFAC["Baradin's Wardens"] or BFAC["Hellscream's Reach"]),
+					[131]	= BFAC["Guardians of Hyjal"],
+					[132]	= BFAC["Ramkahen"],
+					[133]	= BFAC["The Earthen Ring"],
+					[134]	= BFAC["Therazane"],
+				}
+			end
+			return FILTER_NAMES
+		end
+	end	-- do
+
+	---Dumps the recipe database in a format that is readable to humans (or machines)
+	function addon:GetTextDump(profession)
+		local output = addon.db.profile.textdumpformat
+		table.wipe(text_table)
+
+		if not output or output == "Comma" then
+			table.insert(text_table, ("Ackis Recipe List Text Dump for %s's %s, in the form of Comma Separated Values.\n  "):format(private.player_name, profession))
+			table.insert(text_table, "Spell ID,Recipe Name,Skill Level,ARL Filter Flags,Acquire Methods,Known\n")
+		elseif output == "BBCode" then
+			table.insert(text_table, ("Ackis Recipe List Text Dump for %s's %s, in the form of BBCode.\n"):format(private.player_name, profession))
+		elseif output == "XML" then
+			table.insert(text_table, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>")
+		end
+
+		local recipe_list = private.recipe_list
+		local SF = private.recipe_state_flags
+
+		for recipe_id in pairs(recipe_list) do
+			local recipe = recipe_list[recipe_id]
+			local recipe_prof = _G.GetSpellInfo(recipe.profession)
+			local is_known = recipe:HasState("KNOWN")
+
+			if recipe_prof == profession then
+				-- CSV
+				if not output or output == "Comma" then
+					-- Add Spell ID, Name and Skill Level to the list
+					table.insert(text_table, recipe_id)
+					table.insert(text_table, ",")
+					table.insert(text_table, recipe.name)
+					table.insert(text_table, ",")
+					table.insert(text_table, recipe.skill_level)
+					table.insert(text_table, ",\"")
+				-- BBCode
+				elseif output == "BBCode" then
+					-- Make the entry red
+					if not is_known then
+						table.insert(text_table, "[color=red]")
+					end
+					table.insert(text_table, "\n[b]" .. recipe_id .. "[/b] - " .. recipe.name .. " (" .. recipe.skill_level .. ")\n")
+
+					-- Close Color tag
+					if not is_known then
+						table.insert(text_table, "[/color]\nRecipe Flags:\n[list]")
+					elseif is_known then
+						table.insert(text_table, "\nRecipe Flags:\n[list]")
+					end
+				--XML
+				elseif output == "XML" then
+					table.insert(text_table, "<recipe>")
+					table.insert(text_table, "  <id>..recipe_id..</id>")
+					table.insert(text_table, "  <name>"..recipe.name.."</name>")
+					table.insert(text_table, "  <skilllevel>..recipe.skill_level..</skilllevel>")
+					table.insert(text_table, "  <known>"..tostring(is_known).."</known>")
+					table.insert(text_table, "  <flags>")
+				--Name
+				elseif output == "Name" then
+					table.insert(text_table, recipe.name)
+				end
+
+				-- Add in all the filter flags
+				local filter_names = GetFilterNames()
+				local prev = false
+
+				-- Find out which flags are set
+				for table_index, bits in ipairs(private.bit_flags) do
+					for flag_name, flag in pairs(bits) do
+						local bitfield = recipe.flags[private.flag_members[table_index]]
+
+						if bitfield and bit.band(bitfield, flag) == flag then
+							if not output or output == "Comma" then
+								if prev then
+									table.insert(text_table, ",")
+								end
+								table.insert(text_table, filter_names[private.filter_flags[flag_name]])
+								prev = true
+								-- BBCode
+							elseif output == "BBCode" then
+								table.insert(text_table, "[*]"..filter_names[private.filter_flags[flag_name]])
+							elseif output == "XML" then
+								table.insert(text_table, "    <flag>"..filter_names[private.filter_flags[flag_name]].."</flag>")
+							end
+						end
+					end
+				end
+
+				if not output or output == "Comma" then
+					table.insert(text_table, "\",\"")
+				elseif output == "BBCode" then
+					table.insert(text_table, "[/list]\nAcquire Methods:\n[list]")
+				elseif output == "XML" then
+					table.insert(text_table, "  </flags>")
+					table.insert(text_table, "  <acquire>")
+				end
+
+				-- Find out which unique acquire methods we have
+				local acquire_data = recipe["acquire_data"]
+				table.wipe(acquire_list)
+
+				for acquire_type in pairs(acquire_data) do
+					acquire_list[ACQUIRE_NAMES[acquire_type]] = true
+				end
+
+				-- Add all the acquire methods in
+				prev = false
+
+				for i in pairs(acquire_list) do
+					if not output or output == "Comma" then
+						if prev then
+							table.insert(text_table, ",")
+						end
+						table.insert(text_table, i)
+						prev = true
+					elseif output == "BBCode" then
+						table.insert(text_table, "[*] " .. i)
+					elseif output == "XML" then
+						table.insert(text_table, "<acquiremethod>"..i.."</acquiremethod>")
+					end
+				end
+
+				if not output or output == "Comma" then
+					table.insert(text_table, "\","..tostring(is_known).."\n")
+					--if is_known then
+					--	table.insert(text_table, "\",true\n")
+					--else
+					--	table.insert(text_table, "\",false\n")
+					--end
+				elseif output == "BBCode" then
+					table.insert(text_table, "\n[/list]")
+				elseif output == "XML" then
+					table.insert(text_table, "  </acquire>")
+					table.insert(text_table, "</recipe>")
+				end
+			end
+		end	-- for
+		return table.concat(text_table, "")
+	end
+end
diff --git a/core.lua b/core.lua
deleted file mode 100644
index 0774586..0000000
--- a/core.lua
+++ /dev/null
@@ -1,1466 +0,0 @@
---[[
-************************************************************************
-core.lua
-Core functions for Ackis Recipe List
-************************************************************************
-File date: @file-date-iso@
-File hash: @file-abbreviated-hash@
-Project hash: @project-abbreviated-hash@
-Project version: @project-version@
-************************************************************************
-Please see http://www.wowace.com/addons/arl/ for more information.
-************************************************************************
-This source code is released under All Rights Reserved.
-************************************************************************
---- Ackis Recipe List provides functionality to scan your professions.
--- It will determine which recipes you are missing.
--- @class file
--- @name core.lua
--- @release 2.0
-************************************************************************
-]]
-
--------------------------------------------------------------------------------
--- Localized Lua globals.
--------------------------------------------------------------------------------
-local _G = getfenv(0)
-
--- Functions
-local pairs, ipairs = _G.pairs, _G.ipairs
-local select = _G.select
-local tonumber, tostring = _G.tonumber, _G.tostring
-local type = _G.type
-
--- Libraries
-local bit = _G.bit
-local string = _G.string
-local table = _G.table
-
--------------------------------------------------------------------------------
--- AddOn namespace.
--------------------------------------------------------------------------------
-local FOLDER_NAME, private = ...
-private.addon_name = "Ackis Recipe List"
-
-local LibStub	= _G.LibStub
-local addon	= LibStub("AceAddon-3.0"):NewAddon(private.addon_name, "AceConsole-3.0", "AceEvent-3.0")
-_G.AckisRecipeList = addon
-
---@alpha@
-_G.ARL = addon
---@end-alpha@
-
-local L		= LibStub("AceLocale-3.0"):GetLocale(private.addon_name)
-local BFAC 	= LibStub("LibBabble-Faction-3.0"):GetLookupTable()
-
-local debugger	= _G.tekDebug and _G.tekDebug:GetFrame(private.addon_name)
-
-private.build_num = select(2, _G.GetBuildInfo())
-
-private.custom_list	= {}
-private.mob_list	= {}
-private.quest_list	= {}
-private.recipe_list	= {}
-private.reputation_list	= {}
-private.trainer_list	= {}
-private.seasonal_list	= {}
-private.vendor_list	= {}
-private.location_list	= {}
-private.acquire_list	= {}
-
-------------------------------------------------------------------------------
--- Constants.
-------------------------------------------------------------------------------
-local PROFESSION_INIT_FUNCS = {}
-
-------------------------------------------------------------------------------
--- Database tables
-------------------------------------------------------------------------------
-local AllSpecialtiesTable = {}
-local SpecialtyTable
-
--- Filter flags and acquire types - defined in Constants.lua
-local F 	= private.filter_flags
-local A		= private.acquire_types
-
--- Global Frame Variables
-addon.optionsFrame = {}
-
--------------------------------------------------------------------------------
--- Check to see if we have mandatory libraries loaded. If not, notify the user
--- which are missing and return.
--------------------------------------------------------------------------------
-local MissingLibraries
-do
-	local REQUIRED_LIBS = {
-		"AceLocale-3.0",
-		"LibBabble-Boss-3.0",
-		"LibBabble-Faction-3.0",
-		"LibBabble-Zone-3.0",
-	}
-	function MissingLibraries()
-		local missing = false
-
-		for idx, lib in ipairs(REQUIRED_LIBS) do
-			if not LibStub:GetLibrary(lib, true) then
-				missing = true
-				addon:Print(L["MISSING_LIBRARY"]:format(lib))
-			end
-		end
-		return missing
-	end
-end -- do
-
-if MissingLibraries() then
-	--@debug@
-	addon:Print("You are using a development version of ARL.  As per WowAce standards, externals are not set up.  You will have to install all necessary libraries in order for the addon to function correctly.")
-	--@end-debug@
-	_G.AckisRecipeList = nil
-	return
-end
-
--------------------------------------------------------------------------------
--- Define the static popups we're going to call when people haven't scanned or
--- when current filters are blocking all recipes from being displayed.
--------------------------------------------------------------------------------
-_G.StaticPopupDialogs["ARL_NOTSCANNED"] = {
-	text = L["NOTSCANNED"],
-	button1 = _G.OKAY,
-	timeout = 0,
-	exclusive = 1,
-	whileDead = 1,
-	hideOnEscape = 1
-}
-
-_G.StaticPopupDialogs["ARL_ALLFILTERED"] = {
-	text = L["ALL_FILTERED"],
-	button1 = _G.OKAY,
-	timeout = 0,
-	exclusive = 1,
-	whileDead = 1,
-	hideOnEscape = 1
-}
-
-_G.StaticPopupDialogs["ARL_ALLKNOWN"] = {
-	text = L["ARL_ALLKNOWN"],
-	button1 = _G.OKAY,
-	timeout = 0,
-	exclusive = 1,
-	whileDead = 1,
-	hideOnEscape = 1
-}
-
-_G.StaticPopupDialogs["ARL_ALLEXCLUDED"] = {
-	text = L["ARL_ALLEXCLUDED"],
-	button1 = _G.OKAY,
-	timeout = 0,
-	exclusive = 1,
-	whileDead = 1,
-	hideOnEscape = 1
-}
-
-_G.StaticPopupDialogs["ARL_SEARCHFILTERED"] = {
-	text = L["ARL_SEARCHFILTERED"],
-	button1 = _G.OKAY,
-	timeout = 0,
-	exclusive = 1,
-	whileDead = 1,
-	hideOnEscape = 1
-}
-
--------------------------------------------------------------------------------
--- Close all possible pop-up windows
--------------------------------------------------------------------------------
-function addon:ClosePopups()
-	_G.StaticPopup_Hide("ARL_NOTSCANNED")
-	_G.StaticPopup_Hide("ARL_ALLFILTERED")
-	_G.StaticPopup_Hide("ARL_ALLKNOWN")
-	_G.StaticPopup_Hide("ARL_ALLEXCLUDED")
-	_G.StaticPopup_Hide("ARL_SEARCHFILTERED")
-end
-
--------------------------------------------------------------------------------
--- Functions common to most files in the AddOn.
--------------------------------------------------------------------------------
-function private.SetTextColor(color_code, text)
-	return ("|cff%s%s|r"):format(color_code or "ffffff", text)
-end
-
--------------------------------------------------------------------------------
--- Debugger.
--------------------------------------------------------------------------------
-function addon:Debug(...)
-	if debugger then
-		debugger:AddMessage(string.format(...))
-	else
-		--@debug@
-		self:Printf(...)
-		--@end-debug@
-	end
-end
-
-do
-	local output = {}
-
-	function addon:DumpMembers(match)
-		table.wipe(output)
-		table.insert(output, "Addon Object members.\n")
-
-		local count = 0
-
-		for key, value in pairs(self) do
-			local val_type = type(value)
-
-			if not match or val_type == match then
-				table.insert(output, ("%s (%s)"):format(key, val_type))
-				count = count + 1
-			end
-		end
-		table.insert(output, ("\n%d found\n"):format(count))
-		self:DisplayTextDump(nil, nil, table.concat(output, "\n"))
-	end
-end	-- do
-
--------------------------------------------------------------------------------
--- Initialization functions
--------------------------------------------------------------------------------
-function addon:OnInitialize()
-	-- Set default options, which are to include everything in the scan
-	local defaults = {
-		global = {
-			-- Saving alts tradeskills (needs to be global so all profiles can access it)
-			tradeskill = {},
-		},
-		profile = {
-			-------------------------------------------------------------------------------
-			-- Frame options
-			-------------------------------------------------------------------------------
-			frameopts = {
-				offsetx = 0,
-				offsety = 0,
-				anchorTo = "",
-				anchorFrom = "",
-				uiscale = 1,
-				small_list_font = true,
-			},
-
-			-------------------------------------------------------------------------------
-			-- Tooltip Options
-			-------------------------------------------------------------------------------
-			tooltip = {
-				scale = 1,
-				acquire_fontsize = 11,
-			},
-			-------------------------------------------------------------------------------
-			-- Sorting Options
-			-------------------------------------------------------------------------------
-			sorting = "Ascending",
-			current_tab = 3,		-- Name tab
-			skill_view = false,		-- Sort the recipes by skill level instead of name?
-
-			-------------------------------------------------------------------------------
-			-- Display Options
-			-------------------------------------------------------------------------------
-			includefiltered = false,
-			includeexcluded = false,
-			closeguionskillclose = false,
-			ignoreexclusionlist = false,
-			scanbuttonlocation = "TR",
-			spelltooltiplocation = "Right",
-			acquiretooltiplocation = "Right",
-			recipes_in_tooltips = true,
-			max_recipes_in_tooltips = 10,
-			hide_tooltip_hint = false,
-			hidepopup = false,
-			minimap = true,
-			worldmap = true,
-			autoscanmap = false,
-			scantrainers = false,
-			scanvendors = false,
-			autoloaddb = false,
-			maptrainer = false,
-			mapvendor = true,
-			mapmob = true,
-			mapquest = true,
-
-			-------------------------------------------------------------------------------
-			-- Text Dump Options
-			-------------------------------------------------------------------------------
-			textdumpformat = "BBCode",
-
-			-------------------------------------------------------------------------------
-			-- Recipe Exclusion
-			-------------------------------------------------------------------------------
-			exclusionlist = {},
-
-			-------------------------------------------------------------------------------
-			-- Filter Options
-			-------------------------------------------------------------------------------
-			filters = {
-				-------------------------------------------------------------------------------
-				-- General Filters
-				-------------------------------------------------------------------------------
-				general = {
-					faction = true,
-					specialty = false,
-					skill = true,
-					known = false,
-					unknown = true,
-					retired = false,
-				},
-				-------------------------------------------------------------------------------
-				-- Obtain Filters
-				-------------------------------------------------------------------------------
-				obtain = {
-					trainer = true,
-					vendor = true,
-					instance = true,
-					raid = true,
-					seasonal = true,
-					quest = true,
-					pvp = true,
-					discovery = true,
-					worlddrop = true,
-					mobdrop = true,
-					achievement = true,
-					expansion0 = true,
-					expansion1 = true,
-					expansion2 = true,
-					expansion3 = true,
-				},
-				-------------------------------------------------------------------------------
-				-- Item Filters (Armor/Weapon)
-				-------------------------------------------------------------------------------
-				item = {
-					armor = {
-						cloth = true,
-						leather = true,
-						mail = true,
-						plate = true,
-						trinket = true,
-						cloak = true,
-						ring = true,
-						necklace = true,
-						shield = true,
-					},
-					weapon = {
-						onehand = true,
-						twohand = true,
-						axe = true,
-						sword = true,
-						mace = true,
-						polearm = true,
-						dagger = true,
-						fist = true,
-						staff = true,
-						wand = true,
-						thrown = true,
-						bow = true,
-						crossbow = true,
-						ammo = true,
-						gun = true,
-					},
-				},
-				-------------------------------------------------------------------------------
-				-- Quality Filters
-				-------------------------------------------------------------------------------
-				quality = {
-					common = true,
-					uncommon = true,
-					rare = true,
-					epic = true,
-				},
-				-------------------------------------------------------------------------------
-				-- Binding Filters
-				-------------------------------------------------------------------------------
-				binding = {
-					itemboe = true,
-					itembop = true,
-					recipebop = true,
-					recipeboe = true,
-				},
-				-------------------------------------------------------------------------------
-				-- Player Role Filters
-				-------------------------------------------------------------------------------
-				player = {
-					melee = true,
-					tank = true,
-					healer = true,
-					caster = true,
-				},
-				-------------------------------------------------------------------------------
-				-- Reputation Filters
-				-------------------------------------------------------------------------------
-				rep = {
-					aldor = true,
-					scryer = true,
-					argentdawn = true,
-					ashtonguedeathsworn = true,
-					cenarioncircle = true,
-					cenarionexpedition = true,
-					consortium = true,
-					hellfire = true,
-					keepersoftime = true,
-					nagrand = true,
-					lowercity = true,
-					scaleofthesands = true,
-					shatar = true,
-					shatteredsun = true,
-					sporeggar = true,
-					thoriumbrotherhood = true,
-					timbermaw = true,
-					violeteye = true,
-					zandalar = true,
-					argentcrusade = true,
-					frenzyheart = true,
-					ebonblade = true,
-					kirintor = true,
-					sonsofhodir = true,
-					kaluak = true,
-					oracles = true,
-					wyrmrest = true,
-					wrathcommon1 = true,
-					wrathcommon2 = true,
-					wrathcommon3 = true,
-					wrathcommon4 = true,
-					wrathcommon5 = true,
-					ashenverdict = true,
-					catacommon1 = true,
-					catacommon2 = true,
-					guardiansofhyjal = true,
-					ramkahen = true,
-					earthenring = true,
-					therazane = true,
-				},
-				-------------------------------------------------------------------------------
-				-- Class Filters
-				-------------------------------------------------------------------------------
-				classes = {
-					deathknight = true,
-					druid = true,
-					hunter = true,
-					mage = true,
-					paladin = true,
-					priest = true,
-					rogue = true,
-					shaman = true,
-					warlock = true,
-					warrior = true,
-				},
-			}
-		}
-	}
-	self.db = LibStub("AceDB-3.0"):New("ARLDB2", defaults)
-
-	if not self.db then
-		self:Print("Error: Database not loaded correctly.  Please exit out of WoW and delete the ARL database file (AckisRecipeList.lua) found in: \\World of Warcraft\\WTF\\Account\\<Account Name>>\\SavedVariables\\")
-		return
-	end
-	local version = _G.GetAddOnMetadata("AckisRecipeList", "Version")
-	local debug_version = false
-	local alpha_version = false
-
-	-- @debug@
-	debug_version = true
-	-- @end-debug
-
-	-- @alpha@
-	alpha_version = true
-	-- @end-alpha@
-
-	version = debug_version and "Devel" or (alpha_version and version .. "-Alpha") or version
-
-	self.version = version
-
-	self:SetupOptions()
-
-	-- Register slash commands
-	self:RegisterChatCommand("arl", "ChatCommand")
-	self:RegisterChatCommand("ackisrecipelist", "ChatCommand")
-
-	-------------------------------------------------------------------------------
-	-- Create the scan button
-	-------------------------------------------------------------------------------
-	local scan_button = _G.CreateFrame("Button", nil, _G.UIParent, "UIPanelButtonTemplate")
-	scan_button:SetHeight(20)
-
-	scan_button:RegisterForClicks("LeftButtonUp")
-	scan_button:SetScript("OnClick",
-			      function(self, button, down)
-				      local cur_profession = _G.GetTradeSkillLine()
-				      local MainPanel = addon.Frame
-				      local prev_profession
-
-				      if MainPanel then
-					      prev_profession = MainPanel.prof_name or private.ordered_professions[MainPanel.profession]
-				      end
-
-				      local shift_key = _G.IsShiftKeyDown()
-				      local alt_key = _G.IsAltKeyDown()
-				      local ctrl_key = _G.IsControlKeyDown()
-
-				      if shift_key and not alt_key and not ctrl_key then
-					      addon:Scan(true)
-				      elseif alt_key and not shift_key and not ctrl_key then
-					      addon:ClearWaypoints()
-				      elseif ctrl_key and not shift_key and not alt_key then
-					      local current_prof = _G.GetTradeSkillLine()
-					      addon:DumpProfession(current_prof)
-				      elseif not shift_key and not alt_key and not ctrl_key then
-					      if MainPanel and MainPanel:IsVisible() and prev_profession == cur_profession then
-						      MainPanel:Hide()
-					      else
-						      addon:Scan(false)
-						      addon:AddWaypoint()
-					      end
-				      end
-			      end)
-
-	scan_button:SetScript("OnEnter",
-			      function(self)
-				      local tooltip = _G.GameTooltip
-
-				      _G.GameTooltip_SetDefaultAnchor(tooltip, self)
-				      tooltip:SetText(L["SCAN_RECIPES_DESC"])
-				      tooltip:Show()
-			      end)
-	scan_button:SetScript("OnLeave", function() _G.GameTooltip:Hide() end)
-	scan_button:SetText(L["Scan"])
-
-	self.scan_button = scan_button
-
-	-------------------------------------------------------------------------------
-	-- Populate the profession initialization functions.
-	-------------------------------------------------------------------------------
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51304)] = addon.InitAlchemy
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51300)] = addon.InitBlacksmithing
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51296)] = addon.InitCooking
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51313)] = addon.InitEnchanting
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51306)] = addon.InitEngineering
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(45542)] = addon.InitFirstAid
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51302)] = addon.InitLeatherworking
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(32606)] = addon.InitSmelting
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51309)] = addon.InitTailoring
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(51311)] = addon.InitJewelcrafting
-	PROFESSION_INIT_FUNCS[_G.GetSpellInfo(45363)] = addon.InitInscription
-	PROFESSION_INIT_FUNCS[private.runeforging_name] = addon.InitRuneforging
-
-	-------------------------------------------------------------------------------
-	-- Hook GameTooltip so we can show information on mobs that drop/sell/train
-	-------------------------------------------------------------------------------
-        _G.GameTooltip:HookScript("OnTooltipSetUnit",
-		       function(self)
-			       if not addon.db.profile.recipes_in_tooltips then
-				       return
-			       end
-			       local name, unit = self:GetUnit()
-
-			       if not unit then
-				       return
-			       end
-			       local guid = _G.UnitGUID(unit)
-
-			       if not guid then
-				       return
-			       end
-			       local GUID = tonumber(string.sub(guid, -12, -9), 16)
-			       local unit = private.mob_list[GUID] or private.vendor_list[GUID] or private.trainer_list[GUID]
-
-			       if not unit or not unit.item_list then
-				       return
-			       end
-			       local player = private.Player
-			       local recipe_list = private.recipe_list
-			       local shifted = _G.IsShiftKeyDown()
-			       local count = 0
-
-			       for spell_id in pairs(unit.item_list) do
-				       local recipe = recipe_list[spell_id]
-				       local recipe_prof = _G.GetSpellInfo(recipe.profession)
-				       local scanned = player.has_scanned[recipe_prof]
-
-				       if scanned then
-					       local skill_level = player.professions[recipe_prof]
-					       local has_level = skill_level and (type(skill_level) == "boolean" and true or skill_level >= recipe.skill_level)
-
-					       if ((not recipe:HasState("KNOWN") and has_level) or shifted) and player:HasRecipeFaction(recipe) then
-						       local _, _, _, hex = _G.GetItemQualityColor(recipe.quality)
-
-						       self:AddLine(("%s: %s%s|r (%d)"):format(recipe.profession, hex, recipe.name, recipe.skill_level))
-						       count = count + 1
-					       end
-				       end
-
-				       if count >= addon.db.profile.max_recipes_in_tooltips then
-					       break
-				       end
-			       end
-		       end)
-end
-
----Function run when the addon is enabled.  Registers events and pre-loads certain variables.
-function addon:OnEnable()
-	self:RegisterEvent("TRADE_SKILL_SHOW")	-- Make addon respond to the tradeskill windows being shown
-	self:RegisterEvent("TRADE_SKILL_CLOSE")	-- Addon responds to tradeskill windows being closed.
-	self:RegisterEvent("TRADE_SKILL_UPDATE")
-
-	if addon.db.profile.scantrainers then
-		self:RegisterEvent("TRAINER_SHOW")
-	end
-
-	if addon.db.profile.scanvendors then
-		self:RegisterEvent("MERCHANT_SHOW")
-	end
-
-	-------------------------------------------------------------------------------
-	-- Set the parent and scripts for addon.scan_button.
-	-------------------------------------------------------------------------------
-	local scan_button = self.scan_button
-
-	if _G.Skillet and _G.Skillet:IsActive() then
-		scan_button:SetParent(_G.SkilletFrame)
-		_G.Skillet:AddButtonToTradeskillWindow(scan_button)
-		scan_button:SetWidth(80)
-	elseif _G.MRTAPI then
-		_G.MRTAPI:RegisterHandler("TradeSkillWindowOnShow",
-						function()
-							scan_button:SetParent(_G.MRTSkillFrame)
-							scan_button:ClearAllPoints()
-							scan_button:SetPoint("RIGHT", _G.MRTSkillFrameCloseButton, "LEFT", 4, 0)
-							scan_button:SetWidth(scan_button:GetTextWidth() + 10)
-							scan_button:Show()
-						end)
-  	elseif _G.ATSWFrame then
-		scan_button:SetParent(_G.ATSWFrame)
-		scan_button:ClearAllPoints()
-
-		if _G.TradeJunkieMain and _G.TJ_OpenButtonATSW then
-			scan_button:SetPoint("RIGHT", _G.TJ_OpenButtonATSW, "LEFT", 0, 0)
-		else
-			scan_button:SetPoint("RIGHT", _G.ATSWOptionsButton, "LEFT", 0, 0)
-		end
-		scan_button:SetHeight(_G.ATSWOptionsButton:GetHeight())
-		scan_button:SetWidth(_G.ATSWOptionsButton:GetWidth())
-	elseif _G.CauldronFrame then
-		scan_button:SetParent(_G.CauldronFrame)
-		scan_button:ClearAllPoints()
-		scan_button:SetPoint("TOP", _G.CauldronFrame, "TOPRIGHT", -58, -52)
-		scan_button:SetWidth(90)
-	elseif _G.BPM_ShowTrainerFrame then
-		scan_button:SetParent(_G.BPM_ShowTrainerFrame)
-		scan_button:ClearAllPoints()
-		scan_button:SetPoint("RIGHT", _G.BPM_ShowTrainerFrame, "LEFT", 4, 0)
-		scan_button:SetWidth(scan_button:GetTextWidth() + 10)
-		scan_button:Show()
-	end
-
-	local buttonparent = scan_button:GetParent()
-	local framelevel = buttonparent:GetFrameLevel()
-	local framestrata = buttonparent:GetFrameStrata()
-
-	-- Set the frame level of the button to be 1 deeper than its parent
-	scan_button:SetFrameLevel(framelevel + 1)
-	scan_button:SetFrameStrata(framestrata)
-	scan_button:Enable()
-
-	-- Add an option so that ARL will work with Manufac
-	if _G.Manufac then
-		_G.Manufac.options.args.ARLScan = {
-			type = 'execute',
-			name = L["Scan"],
-			desc = L["SCAN_RECIPES_DESC"],
-			func = function() addon:Scan(false) end,
-			order = 550,
-		}
-	end
-	private.Player:Initialize()
-
-	-------------------------------------------------------------------------------
-	-- Initialize the SpecialtyTable and AllSpecialtiesTable.
-	-------------------------------------------------------------------------------
-	do
-		local AlchemySpec = {
-			[_G.GetSpellInfo(28674)] = 28674,
-			[_G.GetSpellInfo(28678)] = 28678,
-			[_G.GetSpellInfo(28676)] = 28676,
-		}
-
-		local BlacksmithSpec = {
-			[_G.GetSpellInfo(9788)] = 9788,		-- Armorsmith
-			[_G.GetSpellInfo(17041)] = 17041,	-- Master Axesmith
-			[_G.GetSpellInfo(17040)] = 17040,	-- Master Hammersmith
-			[_G.GetSpellInfo(17039)] = 17039,	-- Master Swordsmith
-			[_G.GetSpellInfo(9787)] = 9787,		-- Weaponsmith
-		}
-
-		local EngineeringSpec = {
-			[_G.GetSpellInfo(20219)] = 20219, -- Gnomish
-			[_G.GetSpellInfo(20222)] = 20222, -- Goblin
-		}
-
-		local LeatherworkSpec = {
-			[_G.GetSpellInfo(10657)] = 10657, -- Dragonscale
-			[_G.GetSpellInfo(10659)] = 10659, -- Elemental
-			[_G.GetSpellInfo(10661)] = 10661, -- Tribal
-		}
-
-		local TailorSpec = {
-			[_G.GetSpellInfo(26797)] = 26797, -- Spellfire
-			[_G.GetSpellInfo(26801)] = 26801, -- Shadoweave
-			[_G.GetSpellInfo(26798)] = 26798, -- Primal Mooncloth
-		}
-
-		SpecialtyTable = {
-			[_G.GetSpellInfo(51304)] = AlchemySpec,
-			[_G.GetSpellInfo(51300)] = BlacksmithSpec,
-			[_G.GetSpellInfo(51306)] = EngineeringSpec,
-			[_G.GetSpellInfo(51302)] = LeatherworkSpec,
-			[_G.GetSpellInfo(51309)] = TailorSpec,
-		}
-
-		-- Populate the Specialty table with all Specialties, adding alchemy even though no recipes have alchemy filters
-		for i in pairs(AlchemySpec) do AllSpecialtiesTable[i] = true end
-		for i in pairs(BlacksmithSpec) do AllSpecialtiesTable[i] = true end
-		for i in pairs(EngineeringSpec) do AllSpecialtiesTable[i] = true end
-		for i in pairs(LeatherworkSpec) do AllSpecialtiesTable[i] = true end
-		for i in pairs(TailorSpec) do AllSpecialtiesTable[i] = true end
-	end	-- do
-end
-
----Run when the addon is disabled. Ace3 takes care of unregistering events, etc.
-function addon:OnDisable()
-	if addon.Frame then
-		addon.Frame:Hide()
-	end
-
-	-- Remove the option from Manufac
-	if _G.Manufac then
-		_G.Manufac.options.args.ARLScan = nil
-	end
-end
-
--------------------------------------------------------------------------------
--- Event handling functions
--------------------------------------------------------------------------------
-
----Event used for datamining when a trainer is shown.
-function addon:TRAINER_SHOW()
-	self:ScanTrainerData(true)
-end
-
----Event used for datamining when a vendor is shown.
-function addon:MERCHANT_SHOW()
-	self:ScanVendor()
-end
-
-do
-	local GetTradeSkillListLink = _G.GetTradeSkillListLink
-	local UnitName = _G.UnitName
-	local GetRealmName = _G.GetRealmName
-
-	function addon:TRADE_SKILL_SHOW()
-		local is_linked = _G.IsTradeSkillLinked() or _G.IsTradeSkillGuild()
-		local tradelink = GetTradeSkillListLink()
-
-		local pname = UnitName("player")
-		local prealm = GetRealmName()
-		local tradename = _G.GetTradeSkillLine()
-
-		-- Actual alt information saved here. -Torhal
-		addon.db.global.tradeskill = addon.db.global.tradeskill or {}
-		addon.db.global.tradeskill[prealm] = addon.db.global.tradeskill[prealm] or {}
-		addon.db.global.tradeskill[prealm][pname] = addon.db.global.tradeskill[prealm][pname] or {}
-
-		-- If this is our own skill, save it. Otherwise, make sure it's gone.
-		addon.db.global.tradeskill[prealm][pname][tradename] = (not is_linked) and tradelink or nil
-
-		local scan_button = self.scan_button
-		local scan_parent = scan_button:GetParent()
-
-		if not scan_parent or scan_parent == _G.UIParent then
-			scan_button:SetParent(_G.TradeSkillFrame)
-			scan_parent = scan_button:GetParent()
-		end
-
-		if scan_parent == _G.TradeSkillFrame then
-			scan_button:ClearAllPoints()
-
-			local loc = addon.db.profile.scanbuttonlocation
-
-			if loc == "TR" then
-				scan_button:SetPoint("RIGHT", _G.TradeSkillFrameCloseButton, "LEFT",4,0)
-			elseif loc == "TL" then
-				scan_button:SetPoint("LEFT", _G.TradeSkillFramePortrait, "RIGHT",2,12)
-			elseif loc == "BR" then
-				scan_button:SetPoint("TOP", _G.TradeSkillCancelButton, "BOTTOM",0,-5)
-			elseif loc == "BL" then
-				scan_button:SetPoint("TOP", _G.TradeSkillCreateAllButton, "BOTTOM",0,-5)
-			end
-			scan_button:SetWidth(scan_button:GetTextWidth() + 10)
-		end
-		scan_button:Show()
-	end
-end
-
-function addon:TRADE_SKILL_CLOSE()
-	if self.Frame and addon.db.profile.closeguionskillclose then
-		self.Frame:Hide()
-	end
-
-	if not _G.Skillet then
-		addon.scan_button:Hide()
-	end
-end
-
-do
-	local last_update = 0
-	local updater = _G.CreateFrame("Frame", nil, _G.UIParent)
-
-	updater:Hide()
-	updater:SetScript("OnUpdate",
-			  function(self, elapsed)
-				  last_update = last_update + elapsed
-
-				  if last_update >= 0.5 then
-					  local profession = _G.GetTradeSkillLine()
-
-					  if profession ~= "UNKNOWN" then
-						  addon:Scan(false, true)
-					  end
-					  self:Hide()
-				  end
-			  end)
-
-	function addon:TRADE_SKILL_UPDATE(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
-		if not self.Frame or not self.Frame:IsVisible() then
-			return
-		end
-
-		if not updater:IsVisible() then
-			last_update = 0
-			updater:Show()
-		end
-	end
-end
-
--------------------------------------------------------------------------------
--- ARL Logic Functions
--------------------------------------------------------------------------------
-function addon:InitializeProfession(profession)
-	if not profession then
-		--@alpha@
-		addon:Print("nil profession passed to InitializeProfession()")
-		--@end-alpha@
-		return
-	end
-
-	if profession == private.professions["Smelting"] then
-		profession = private.mining_name
-	end
-	local func = PROFESSION_INIT_FUNCS[profession]
-
-	if func then
-		func(addon)
-		PROFESSION_INIT_FUNCS[profession] = nil
-	end
-end
-
-do
-	local fa = _G.GetSpellInfo(45542)
-
-	-- Code snippet stolen from GearGuage by Torhal and butchered by Ackis
-	local function StrSplit(input)
-		if not input then return nil, nil end
-		local arg1, arg2, var1
-
-		arg1, var1 = input:match("^([^%s]+)%s*(.*)$")
-		arg1 = (arg1 and arg1:lower() or input:lower())
-
-		if var1 then
-			-- Small hack to get code to work with first aid.
-			if var1:lower() == fa:lower() then
-				arg2 = var1
-			else
-				local var2
-				arg2, var2 = var1:match("^([^%s]+)%s*(.*)$")
-				arg2 = (arg2 and arg2:lower() or var1:lower())
-			end
-		end
-		return arg1, arg2
-	end
-
-	-- Determines what to do when the slash command is called.
-	function addon:ChatCommand(input)
-
-		local arg1, arg2 = StrSplit(input)
-
-		-- Open About panel if there's no parameters or if we do /arl about
-		if not arg1 or (arg1 and arg1:trim() == "") or arg1 == L["Sorting"]:lower() or arg1 == L["Sort"]:lower() or arg1 == _G.DISPLAY:lower() then
-			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
-		elseif arg1 == L["About"]:lower() then
-			if self.optionsFrame["About"] then
-				_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["About"])
-			else
-				_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
-			end
-		elseif arg1 == L["Profile"]:lower() then
-			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Profiles"])
-		elseif arg1 == L["Documentation"]:lower() then
-			_G.InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Documentation"])
-		elseif arg1 == L["Scan"]:lower() then
-			if not arg2 then
-				self:Print(L["COMMAND_LINE_SCAN"])
-			else
-				_G.CastSpellByName(arg2)
-
-				if self.Frame and self.Frame:IsVisible() then
-					self.Frame:Hide()
-				else
-					self:Scan(false, false)
-				end
-			end
-		elseif arg1 == "scanprof" then
-			self:ScanProfession("all")
-		elseif arg1 == "tradelinks" then
-			self:GenerateLinks()
-		else
-			-- What happens when we get here?
-			LibStub("AceConfigCmd-3.0"):HandleCommand("arl", "Ackis Recipe List", arg1)
-		end
-	end
-end
-
---- Public API function to initialize all of the lookup lists - self-nils once run.
--- @name AckisRecipeList:InitializeLookups()
--- @usage if AckisRecipeList.InitializeLookups then AckisRecipeList:InitializeLookups() end
-function addon:InitializeLookups()
-	self:InitCustom(private.custom_list)
-	self:InitMob(private.mob_list)
-	self:InitQuest(private.quest_list)
-	self:InitReputation(private.reputation_list)
-	self:InitTrainer(private.trainer_list)
-	self:InitSeasons(private.seasonal_list)
-	self:InitVendor(private.vendor_list)
-
-	self.InitializeLookups = nil
-end
-
--------------------------------------------------------------------------------
--- Recipe Scanning Functions
--------------------------------------------------------------------------------
-do
-	-- List of tradeskill headers, used in addon:Scan()
-	local header_list = {}
-
-	-- Toggles a recipe ot known state if it's your own
-	local function togglerecipe(recipe, is_linked)
-		if not is_linked then
-			recipe:AddState("KNOWN")
-			recipe:RemoveState("LINKED")
-		else
-			recipe:AddState("LINKED")
-		end
-	end
-
-	--- Causes a scan of the tradeskill to be conducted. Function called when the scan button is clicked.   Parses recipes and displays output
-	-- @name AckisRecipeList:Scan
-	-- @usage AckisRecipeList:Scan(true)
-	-- @param textdump Boolean indicating if we want the output to be a text dump, or if we want to use the ARL GUI
-	-- @return A frame with either the text dump, or the ARL frame
-	function addon:Scan(textdump, is_refresh)
-		local current_prof, prof_level = _G.GetTradeSkillLine()
-
-		-- Bail if we haven't opened a tradeskill frame.
-		if current_prof == "UNKNOWN" then
-			self:Print(L["OpenTradeSkillWindow"])
-			return
-		end
-		local player = private.Player
-		player:SetProfessions()
-
-		-- Set the current profession level, and update the cached data.
-		private.current_profession_scanlevel = prof_level
-
-		-- Make sure we're only updating a profession the character actually knows - this could be a scan from a tradeskill link.
-		local is_linked = _G.IsTradeSkillLinked() or _G.IsTradeSkillGuild()
-
-		if not is_linked then
-			player.has_scanned[current_prof] = true
-		end
-
-		-- Get the current profession Specialty
-		local specialty = SpecialtyTable[current_prof]
-
-		for index = 1, 25, 1 do
-			local spell_name = _G.GetSpellBookItemName(index, _G.BOOKTYPE_SPELL)
-
-			if not spell_name or index == 25 then
-				player["Specialty"] = nil
-				break
-			elseif specialty and specialty[spell_name] then
-				player["Specialty"] = specialty[spell_name]
-				break
-			end
-		end
-
-		if self.InitializeLookups then
-			self:InitializeLookups()
-		end
-		addon:InitializeProfession(current_prof)
-
-		-------------------------------------------------------------------------------
-		-- Scan all recipes and mark the ones we know
-		-------------------------------------------------------------------------------
-		table.wipe(header_list)
-
-		-- Save the current state of the TradeSkillFrame so it can be restored after we muck with it.
-		local have_materials = _G.TradeSkillFrame.filterTbl.hasMaterials
-		local have_skillup = _G.TradeSkillFrame.filterTbl.hasSkillUp
-		local subclass = _G.TradeSkillFrame.filterTbl.subClassValue
-		local slot = _G.TradeSkillFrame.filterTbl.slotValue
-
-		if _G.MRTAPI and _G.MRTAPI:PushFilterSelection() then
-			-- MrTrader saved the state for us
-		else
-			if not _G.Skillet and have_materials then
-				_G.TradeSkillFrame.filterTbl.hasMaterials = false
-				_G.TradeSkillOnlyShowMakeable(false)
-			end
-			if not _G.Skillet and have_skillup then
-				_G.TradeSkillFrame.filterTbl.hasSkillUp = false
-				_G.TradeSkillOnlyShowSkillUps(false)
-			end
-			--UIDropDownMenu_Initialize(TradeSkillFilterDropDown, TradeSkillInvSlotDropDown_Initialize)
-			--UIDropDownMenu_SetSelectedID(TradeSkillFilterDropDown, 1)
-			_G.SetTradeSkillInvSlotFilter(0, 1, 1)
-			_G.TradeSkillUpdateFilterBar()
-			_G.TradeSkillFrame_Update()
-
-			-- Expand all headers so we can see all the recipes there are
-			for i = _G.GetNumTradeSkills(), 1, -1 do
-				local name, tradeType, _, isExpanded = _G.GetTradeSkillInfo(i)
-
-				if tradeType == "header" and not isExpanded then
-					header_list[name] = true
-					_G.ExpandTradeSkillSubClass(i)
-				end
-			end
-		end
-		local recipe_list = private.recipe_list
-		local recipes_found = 0
-		local SF = private.recipe_state_flags
-		local overwritemap = private.spell_overwrite_map
-
-		for i = 1, _G.GetNumTradeSkills() do
-			local tradeName, tradeType = _G.GetTradeSkillInfo(i)
-
-			if tradeType ~= "header" then
-				-- Get the trade skill link for the specified recipe
-				local spell_link = _G.GetTradeSkillRecipeLink(i)
-				-- Spell ID of the recipe being scanned.
-				local spell_string = spell_link:match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)")
-				local spell_id = tonumber(spell_string)
-				local recipe = recipe_list[spell_id]
-
-				if recipe then
-					-- Mark the first rank of the spell as known if we know rank 2 for certain recipes.
-					-- This is only done for recipes which when you learn the higher rank, you lose the
-					-- ability to learn the lower rank.
-
-					-- If we have it in the mapping, set the lower rank spell to known
-					if overwritemap[spell_id] then
-						local overwriterecipe = recipe_list[overwritemap[spell_id]]
-						if overwriterecipe then
-							togglerecipe(overwriterecipe, is_linked)
-						else
-							self:Debug(tradeName .. " " .. overwritemap[spell_id] .. L["MissingFromDB"])
-						end
-					end
-					-- Toggle spell to known
-					togglerecipe(recipe, is_linked)
-					recipes_found = recipes_found + 1
-				else
-					self:Debug(tradeName .. " " .. spell_string .. L["MissingFromDB"])
-				end
-			end
-		end
-
-		-- Close all the headers we've opened
-		-- If Mr Trader is installed use that API
-		if _G.MRTAPI and _G.MRTAPI:PopFilterSelection() then
-			-- MrTrader restored the state for us
-		else
-			-- Collapse all headers that were collapsed before
-			for i = _G.GetNumTradeSkills(), 1, -1 do
-				local name, tradeType, _, isExpanded = _G.GetTradeSkillInfo(i)
-
-				if header_list[name] then
-					_G.CollapseTradeSkillSubClass(i)
-				end
-			end
-
-			-- Restore the state of the things we changed.
-			_G.TradeSkillFrame.filterTbl.hasMaterials = have_materials
-			_G.TradeSkillOnlyShowMakeable(have_materials)
-			_G.TradeSkillFrame.filterTbl.hasSkillUp = have_skillup
-			_G.TradeSkillOnlyShowSkillUps(have_skillup)
-
-			_G.TradeSkillUpdateFilterBar()
-			_G.TradeSkillFrame_Update()
-
-		end
-		player.prev_count = player.foundRecipes
-		player.foundRecipes = recipes_found
-
-		if is_refresh and player.prev_count == recipes_found then
-			return
-		end
-
-		-------------------------------------------------------------------------------
-		-- Update the player's reputation levels.
-		-------------------------------------------------------------------------------
-		player:UpdateReputations()
-
-		-------------------------------------------------------------------------------
-		-- Everything is ready - display the GUI or dump the list to text.
-		-------------------------------------------------------------------------------
-		if textdump then
-			self:DisplayTextDump(recipe_list, current_prof)
-		else
-			if private.InitializeFrame then
-				private.InitializeFrame()
-			end
-			self.Frame:Display(current_prof, is_linked)
-		end
-	end
-end
-
--------------------------------------------------------------------------------
--- Text dumping functions
--------------------------------------------------------------------------------
-
---------------------------------------------------------------------------------
---- Creates a new frame with the contents of a text dump so you can copy and paste
--- Code borrowed from Antiarc (Chatter) with permission
--- @name AckisRecipeList:DisplayTextDump
--- @param RecipeDB The database (array) which you wish read data from.
--- @param profession Which profession are you displaying data for
--- @param text The text to be dumped
---------------------------------------------------------------------------------
-do
-	local copy_frame = _G.CreateFrame("Frame", "ARLCopyFrame", _G.UIParent)
-	copy_frame:SetBackdrop({
-				       bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
-				       edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]],
-				       tile = true,
-				       tileSize = 16,
-				       edgeSize = 16,
-				       insets = {
-					       left = 3,
-					       right = 3,
-					       top = 5,
-					       bottom = 3
-				       }
-			       })
-	copy_frame:SetBackdropColor(0, 0, 0, 1)
-	copy_frame:SetWidth(750)
-	copy_frame:SetHeight(400)
-	copy_frame:SetPoint("CENTER", _G.UIParent, "CENTER")
-	copy_frame:SetFrameStrata("DIALOG")
-
-	table.insert(_G.UISpecialFrames, "ARLCopyFrame")
-
-	local scrollArea = _G.CreateFrame("ScrollFrame", "ARLCopyScroll", copy_frame, "UIPanelScrollFrameTemplate")
-	scrollArea:SetPoint("TOPLEFT", copy_frame, "TOPLEFT", 8, -30)
-	scrollArea:SetPoint("BOTTOMRIGHT", copy_frame, "BOTTOMRIGHT", -30, 8)
-
-	local edit_box = _G.CreateFrame("EditBox", nil, copy_frame)
-	edit_box:SetMultiLine(true)
-	edit_box:SetMaxLetters(0)
-	edit_box:EnableMouse(true)
-	edit_box:SetAutoFocus(true)
-	edit_box:SetFontObject("ChatFontNormal")
-	edit_box:SetWidth(650)
-	edit_box:SetHeight(270)
-	edit_box:SetScript("OnEscapePressed",
-			   function()
-				   copy_frame:Hide()
-			   end)
-	edit_box:HighlightText(0)
-
-	scrollArea:SetScrollChild(edit_box)
-
-	local close = _G.CreateFrame("Button", nil, copy_frame, "UIPanelCloseButton")
-	close:SetPoint("TOPRIGHT", copy_frame, "TOPRIGHT")
-
-	copy_frame:Hide()
-
-	function addon:DisplayTextDump(RecipeDB, profession, text)
-		local text = (not RecipeDB and not profession) and text or self:GetTextDump(profession)
-
-		if text ~= "" then
-			edit_box:SetText(text)
-			edit_box:HighlightText(0)
-			edit_box:SetCursorPosition(1)
-			copy_frame:Show()
-		end
-	end
-end	-- do
-
-do
-	-------------------------------------------------------------------------------
-	-- Dumps recipe output in the format requested by the user
-	-------------------------------------------------------------------------------
-	local text_table = {}
-	local acquire_list = {}
-	local ACQUIRE_NAMES = private.acquire_names
-
-	local GetFilterNames
-	do
-		local LC = _G.LOCALIZED_CLASS_NAMES_MALE
-		local FILTER_NAMES
-
-		function GetFilterNames()
-			if not FILTER_NAMES then
-				local is_alliance = (private.Player.faction == "Alliance")
-
-				FILTER_NAMES = {
-					[1]	= BFAC["Alliance"],
-					[2]	= BFAC["Horde"],
-					[3]	= L["Trainer"],
-					[4]	= L["Vendor"],
-					[5]	= _G.INSTANCE,
-					[6]	= _G.RAID,
-					[7]	= _G.EVENTS_LABEL,
-					[8]	= L["Quest"],
-					[9]	= _G.PVP,
-					[10]	= L["World Drop"],
-					[11]	= L["Mob Drop"],
-					[12]	= L["Discovery"],
-					[13]	= L["Retired"],
-					[21]	= LC["DEATHKNIGHT"],
-					[22]	= LC["DRUID"],
-					[23]	= LC["HUNTER"],
-					[24]	= LC["MAGE"],
-					[25]	= LC["PALADIN"],
-					[26]	= LC["PRIEST"],
-					[27]	= LC["SHAMAN"],
-					[28]	= LC["ROGUE"],
-					[29]	= LC["WARLOCK"],
-					[30]	= LC["WARRIOR"],
-					[36]	= L["BOEFilter"],
-					[37]	= L["BOPFilter"],
-					[38]	= L["BOAFilter"],
-					[40]	= L["RecipeBOEFilter"],
-					[41]	= L["RecipeBOPFilter"],
-					[42]	= L["RecipeBOAFilter"],
-					[51]	= _G.MELEE,
-					[52]	= _G.TANK,
-					[53]	= _G.HEALER,
-					[54]	= _G.DAMAGER,
-					[56]	= L["Cloth"],
-					[57]	= L["Leather"],
-					[58]	= L["Mail"],
-					[59]	= L["Plate"],
-					[60]	= L["Cloak"],
-					[61]	= L["Trinket"],
-					[62]	= L["Ring"],
-					[63]	= L["Necklace"],
-					[64]	= L["Shield"],
-					[66]	= L["One Hand"],
-					[67]	= L["Two Hand"],
-					[68]	= L["Axe"],
-					[69]	= L["Sword"],
-					[70]	= L["Mace"],
-					[71]	= L["Polearm"],
-					[72]	= L["Dagger"],
-					[73]	= L["Staff"],
-					[74]	= L["Wand"],
-					[75]	= L["Thrown"],
-					[76]	= L["Bow"],
-					[77]	= L["Crossbow"],
-					[78]	= L["Ammo"],
-					[79]	= L["Fist"],
-					[80]	= L["Gun"],
-					[96]	= BFAC["Argent Dawn"],
-					[97]	= BFAC["Cenarion Circle"],
-					[98]	= BFAC["Thorium Brotherhood"],
-					[99]	= BFAC["Timbermaw Hold"],
-					[100]	= BFAC["Zandalar Tribe"],
-					[101]	= BFAC["The Aldor"],
-					[102]	= BFAC["Ashtongue Deathsworn"],
-					[103]	= BFAC["Cenarion Expedition"],
-					[104]	= (is_alliance and BFAC["Honor Hold"] or BFAC["Thrallmar"]),
-					[105]	= BFAC["The Consortium"],
-					[106]	= BFAC["Keepers of Time"],
-					[107]	= BFAC["Lower City"],
-					[108]	= (is_alliance and BFAC["Kurenai"] or BFAC["The Mag'har"]),
-					[109]	= BFAC["The Scale of the Sands"],
-					[110]	= BFAC["The Scryers"],
-					[111]	= BFAC["The Sha'tar"],
-					[112]	= BFAC["Shattered Sun Offensive"],
-					[113]	= BFAC["Sporeggar"],
-					[114]	= BFAC["The Violet Eye"],
-					[115]	= BFAC["Argent Crusade"],
-					[116]	= BFAC["Frenzyheart Tribe"],
-					[117]	= BFAC["Knights of the Ebon Blade"],
-					[118]	= BFAC["Kirin Tor"],
-					[119]	= BFAC["The Sons of Hodir"],
-					[120]	= BFAC["The Kalu'ak"],
-					[121]	= BFAC["The Oracles"],
-					[122]	= BFAC["The Wyrmrest Accord"],
-					[123]	= (is_alliance and BFAC["The Silver Covenant"] or BFAC["The Sunreavers"]),
-					[124]	= (is_alliance and BFAC["Explorers' League"] or BFAC["The Hand of Vengeance"]),
-					[125]	= (is_alliance and BFAC["Valiance Expedition"] or BFAC["Warsong Offensive"]),
-					[126]	= (is_alliance and BFAC["The Frostborn"] or BFAC["The Taunka"]),
-					[127]	= (is_alliance and BFAC["Alliance Vanguard"] or BFAC["Horde Expedition"]),
-					[128]	= BFAC["The Ashen Verdict"],
-					[129]	= (is_alliance and BFAC["Wildhammer Clan"] or BFAC["Dragonmaw Clan"]),
-					[130]	= (is_alliance and BFAC["Baradin's Wardens"] or BFAC["Hellscream's Reach"]),
-					[131]	= BFAC["Guardians of Hyjal"],
-					[132]	= BFAC["Ramkahen"],
-					[133]	= BFAC["The Earthen Ring"],
-					[134]	= BFAC["Therazane"],
-				}
-			end
-			return FILTER_NAMES
-		end
-	end	-- do
-
-	---Dumps the recipe database in a format that is readable to humans (or machines)
-	function addon:GetTextDump(profession)
-		local output = addon.db.profile.textdumpformat
-		table.wipe(text_table)
-
-		if not output or output == "Comma" then
-			table.insert(text_table, ("Ackis Recipe List Text Dump for %s's %s, in the form of Comma Separated Values.\n  "):format(private.player_name, profession))
-			table.insert(text_table, "Spell ID,Recipe Name,Skill Level,ARL Filter Flags,Acquire Methods,Known\n")
-		elseif output == "BBCode" then
-			table.insert(text_table, ("Ackis Recipe List Text Dump for %s's %s, in the form of BBCode.\n"):format(private.player_name, profession))
-		elseif output == "XML" then
-			table.insert(text_table, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>")
-		end
-
-		local recipe_list = private.recipe_list
-		local SF = private.recipe_state_flags
-
-		for recipe_id in pairs(recipe_list) do
-			local recipe = recipe_list[recipe_id]
-			local recipe_prof = _G.GetSpellInfo(recipe.profession)
-			local is_known = recipe:HasState("KNOWN")
-
-			if recipe_prof == profession then
-				-- CSV
-				if not output or output == "Comma" then
-					-- Add Spell ID, Name and Skill Level to the list
-					table.insert(text_table, recipe_id)
-					table.insert(text_table, ",")
-					table.insert(text_table, recipe.name)
-					table.insert(text_table, ",")
-					table.insert(text_table, recipe.skill_level)
-					table.insert(text_table, ",\"")
-				-- BBCode
-				elseif output == "BBCode" then
-					-- Make the entry red
-					if not is_known then
-						table.insert(text_table, "[color=red]")
-					end
-					table.insert(text_table, "\n[b]" .. recipe_id .. "[/b] - " .. recipe.name .. " (" .. recipe.skill_level .. ")\n")
-
-					-- Close Color tag
-					if not is_known then
-						table.insert(text_table, "[/color]\nRecipe Flags:\n[list]")
-					elseif is_known then
-						table.insert(text_table, "\nRecipe Flags:\n[list]")
-					end
-				--XML
-				elseif output == "XML" then
-					table.insert(text_table, "<recipe>")
-					table.insert(text_table, "  <id>..recipe_id..</id>")
-					table.insert(text_table, "  <name>"..recipe.name.."</name>")
-					table.insert(text_table, "  <skilllevel>..recipe.skill_level..</skilllevel>")
-					table.insert(text_table, "  <known>"..tostring(is_known).."</known>")
-					table.insert(text_table, "  <flags>")
-				--Name
-				elseif output == "Name" then
-					table.insert(text_table, recipe.name)
-				end
-
-				-- Add in all the filter flags
-				local filter_names = GetFilterNames()
-				local prev = false
-
-				-- Find out which flags are set
-				for table_index, bits in ipairs(private.bit_flags) do
-					for flag_name, flag in pairs(bits) do
-						local bitfield = recipe.flags[private.flag_members[table_index]]
-
-						if bitfield and bit.band(bitfield, flag) == flag then
-							if not output or output == "Comma" then
-								if prev then
-									table.insert(text_table, ",")
-								end
-								table.insert(text_table, filter_names[private.filter_flags[flag_name]])
-								prev = true
-								-- BBCode
-							elseif output == "BBCode" then
-								table.insert(text_table, "[*]"..filter_names[private.filter_flags[flag_name]])
-							elseif output == "XML" then
-								table.insert(text_table, "    <flag>"..filter_names[private.filter_flags[flag_name]].."</flag>")
-							end
-						end
-					end
-				end
-
-				if not output or output == "Comma" then
-					table.insert(text_table, "\",\"")
-				elseif output == "BBCode" then
-					table.insert(text_table, "[/list]\nAcquire Methods:\n[list]")
-				elseif output == "XML" then
-					table.insert(text_table, "  </flags>")
-					table.insert(text_table, "  <acquire>")
-				end
-
-				-- Find out which unique acquire methods we have
-				local acquire_data = recipe["acquire_data"]
-				table.wipe(acquire_list)
-
-				for acquire_type in pairs(acquire_data) do
-					acquire_list[ACQUIRE_NAMES[acquire_type]] = true
-				end
-
-				-- Add all the acquire methods in
-				prev = false
-
-				for i in pairs(acquire_list) do
-					if not output or output == "Comma" then
-						if prev then
-							table.insert(text_table, ",")
-						end
-						table.insert(text_table, i)
-						prev = true
-					elseif output == "BBCode" then
-						table.insert(text_table, "[*] " .. i)
-					elseif output == "XML" then
-						table.insert(text_table, "<acquiremethod>"..i.."</acquiremethod>")
-					end
-				end
-
-				if not output or output == "Comma" then
-					table.insert(text_table, "\","..tostring(is_known).."\n")
-					--if is_known then
-					--	table.insert(text_table, "\",true\n")
-					--else
-					--	table.insert(text_table, "\",false\n")
-					--end
-				elseif output == "BBCode" then
-					table.insert(text_table, "\n[/list]")
-				elseif output == "XML" then
-					table.insert(text_table, "  </acquire>")
-					table.insert(text_table, "</recipe>")
-				end
-			end
-		end	-- for
-		return table.concat(text_table, "")
-	end
-end