Quantcast

Renamed ARL.lua to core.lua

James D. Callahan III [07-09-10 - 22:14]
Renamed ARL.lua to core.lua
Filename
ARL.lua
AckisRecipeList.toc
core.lua
diff --git a/ARL.lua b/ARL.lua
deleted file mode 100644
index 8522c39..0000000
--- a/ARL.lua
+++ /dev/null
@@ -1,2188 +0,0 @@
---[[
-************************************************************************
-ARL.lua
-************************************************************************
-File date: @file-date-iso@
-File hash: @file-abbreviated-hash@
-Project hash: @project-abbreviated-hash@
-Project version: @project-version@
-************************************************************************
-Authors: Ackis, Zhinjio, Jim-Bim, Torhal, Pompachomp
-************************************************************************
-Please see http://www.wowace.com/addons/arl/ for more information.
-************************************************************************
-This source code is released under All Rights Reserved.
-************************************************************************
-**AckisRecipeList** provides an interface for scanning professions for missing recipes.
-There are a set of functions which allow you make use of the ARL database outside of ARL.
-ARL supports all professions currently in World of Warcraft 3.3.2
-@class file
-@name ARL.lua
-@release 1.0
-************************************************************************
-]]
-
--------------------------------------------------------------------------------
--- Localized Lua globals.
--------------------------------------------------------------------------------
-local _G = getfenv(0)
-
-local tostring = _G.tostring
-local tonumber = _G.tonumber
-
-local pairs, ipairs = _G.pairs, _G.ipairs
-local select = _G.select
-
-local table = _G.table
-local twipe = table.wipe
-local tconcat = table.concat
-local tinsert = table.insert
-
-local bit = _G.bit
-
-local string = _G.string
-local strformat = string.format
-local strfind = string.find
-local strmatch = string.match
-local strlower = string.lower
-
--------------------------------------------------------------------------------
--- Localized Blizzard API.
--------------------------------------------------------------------------------
-local GetNumTradeSkills = _G.GetNumTradeSkills
-local GetSpellInfo = _G.GetSpellInfo
-
--------------------------------------------------------------------------------
--- AddOn namespace.
--------------------------------------------------------------------------------
-local LibStub	= _G.LibStub
-local MODNAME	= "Ackis Recipe List"
-local addon	= LibStub("AceAddon-3.0"):NewAddon(MODNAME, "AceConsole-3.0", "AceEvent-3.0")
-_G.AckisRecipeList = addon
-
---@alpha@
-_G.ARL = addon
---@end-alpha@
-
-local L		= LibStub("AceLocale-3.0"):GetLocale(MODNAME)
-local BFAC 	= LibStub("LibBabble-Faction-3.0"):GetLookupTable()
-local BZ	= LibStub("LibBabble-Zone-3.0"):GetLookupTable()
-
-local debugger	= _G.tekDebug and _G.tekDebug:GetFrame(MODNAME)
-
-------------------------------------------------------------------------------
--- Constants.
-------------------------------------------------------------------------------
-local PROFESSION_INITS = {}	-- Professions initialization functions.
-
-------------------------------------------------------------------------------
--- Database tables
-------------------------------------------------------------------------------
-local AllSpecialtiesTable = {}
-local SpecialtyTable
-
--- Set up the private intra-file namespace.
-local private	= select(2, ...)
-
-private.build_num = select(2, 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	= {}
-
--- Filter flags and acquire types - defined in Constants.lua
-local F 	= private.filter_flags
-local A		= private.acquire_types
-
-------------------------------------------------------------------------------
--- Data which is stored regarding a players statistics (luadoc copied from Collectinator, needs updating)
-------------------------------------------------------------------------------
--- @class table
--- @name Player
--- @field known_filtered Total number of items known filtered during the scan.
--- @field Faction Player's faction
--- @field Class Player's class
--- @field ["Reputation"] Listing of players reputation levels
-local Player = {}
-private.Player = Player
-
--- 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(strformat(L["MISSING_LIBRARY"], 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
-
-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)
-		twipe(output)
-		tinsert(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
-				tinsert(output, key.. " ("..val_type..")")
-				count = count + 1
-			end
-		end
-		tinsert(output, string.format("\n%d found\n", count))
-		self:DisplayTextDump(nil, nil, tconcat(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,
-					expansion0 = true,
-					expansion1 = true,
-					expansion2 = 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,
-				},
-				-------------------------------------------------------------------------------
-				-- 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 = GetAddOnMetadata("AckisRecipeList", "Version")
-	self.version = (version == "@project-version@") and "Devel" or version
-
-	self:SetupOptions()
-
-	-- Register slash commands
-	self:RegisterChatCommand("arl", "ChatCommand")
-	self:RegisterChatCommand("ackisrecipelist", "ChatCommand")
-
-	-------------------------------------------------------------------------------
-	-- Create the scan button
-	-------------------------------------------------------------------------------
-	local scan_button = CreateFrame("Button", nil, UIParent, "UIPanelButtonTemplate")
-	scan_button:SetHeight(20)
-
-	scan_button:RegisterForClicks("LeftButtonUp")
-	scan_button:SetScript("OnClick",
-			      function(self, button, down)
-				      local cur_profession = GetTradeSkillLine()
-				      local prev_profession = addon.Frame.prof_name or private.ordered_professions[addon.Frame.profession]
-
-				      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 not shift_key and alt_key and not ctrl_key then
-					      addon:ClearWaypoints()
-				      elseif not shift_key and not alt_key and not ctrl_key then
-					      if addon.Frame:IsVisible() and prev_profession == cur_profession then
-						      addon.Frame:Hide()
-					      else
-						      addon:Scan(false)
-						      addon:AddWaypoint()
-					      end
-				      end
-			      end)
-
-	scan_button:SetScript("OnEnter",
-			      function(this)
-				      GameTooltip_SetDefaultAnchor(GameTooltip, this)
-				      GameTooltip:SetText(L["SCAN_RECIPES_DESC"])
-				      GameTooltip:Show()
-			      end)
-	scan_button:SetScript("OnLeave", function() GameTooltip:Hide() end)
-	scan_button:SetText(L["Scan"])
-
-	self.scan_button = scan_button
-
-	-------------------------------------------------------------------------------
-	-- Populate the profession initialization functions.
-	-------------------------------------------------------------------------------
-	PROFESSION_INITS[GetSpellInfo(51304)] = addon.InitAlchemy
-	PROFESSION_INITS[GetSpellInfo(51300)] = addon.InitBlacksmithing
-	PROFESSION_INITS[GetSpellInfo(51296)] = addon.InitCooking
-	PROFESSION_INITS[GetSpellInfo(51313)] = addon.InitEnchanting
-	PROFESSION_INITS[GetSpellInfo(51306)] = addon.InitEngineering
-	PROFESSION_INITS[GetSpellInfo(45542)] = addon.InitFirstAid
-	PROFESSION_INITS[GetSpellInfo(51302)] = addon.InitLeatherworking
-	PROFESSION_INITS[GetSpellInfo(32606)] = addon.InitSmelting
-	PROFESSION_INITS[GetSpellInfo(51309)] = addon.InitTailoring
-	PROFESSION_INITS[GetSpellInfo(51311)] = addon.InitJewelcrafting
-	PROFESSION_INITS[GetSpellInfo(45363)] = addon.InitInscription
-	PROFESSION_INITS[private.runeforging_name] = addon.InitRuneforging
-
-	-------------------------------------------------------------------------------
-	-- Hook GameTooltip so we can show information on mobs that drop/sell/train
-	-------------------------------------------------------------------------------
-        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 = UnitGUID(unit)
-
-			       if not guid then
-				       return
-			       end
-			       local GUID = tonumber(string.sub(guid, 8, 12), 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 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 = 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 = GetItemQualityColor(recipe.quality)
-
-						       self:AddLine(string.format("%s: %s%s|r (%d)", 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 Skillet and Skillet:IsActive() then
-		scan_button:SetParent(SkilletFrame)
-		Skillet:AddButtonToTradeskillWindow(scan_button)
-		scan_button:SetWidth(80)
-	elseif MRTUIUtils_RegisterWindowOnShow then
-		MRTUIUtils_RegisterWindowOnShow(function()
-							scan_button:SetParent(MRTSkillFrame)
-							scan_button:ClearAllPoints()
-							scan_button:SetPoint("RIGHT", MRTSkillFrameCloseButton, "LEFT", 4, 0)
-							scan_button:SetWidth(scan_button:GetTextWidth() + 10)
-							scan_button:Show()
-						end)
-  	elseif ATSWFrame then
-		scan_button:SetParent(ATSWFrame)
-		scan_button:ClearAllPoints()
-
-		if TradeJunkieMain and TJ_OpenButtonATSW then
-			scan_button:SetPoint("RIGHT", TJ_OpenButtonATSW, "LEFT", 0, 0)
-		else
-			scan_button:SetPoint("RIGHT", ATSWOptionsButton, "LEFT", 0, 0)
-		end
-		scan_button:SetHeight(ATSWOptionsButton:GetHeight())
-		scan_button:SetWidth(ATSWOptionsButton:GetWidth())
-	elseif CauldronFrame then
-		scan_button:SetParent(CauldronFrame)
-		scan_button:ClearAllPoints()
-		scan_button:SetPoint("TOP", CauldronFrame, "TOPRIGHT", -58, -52)
-		scan_button:SetWidth(90)
-	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 Manufac then
-		Manufac.options.args.ARLScan = {
-			type = 'execute',
-			name = L["Scan"],
-			desc = L["SCAN_RECIPES_DESC"],
-			func = function() addon:Scan(false) end,
-			order = 550,
-		}
-	end
-
---[[
-	-- If we're using Skillet, use Skillet's API to work with getting tradeskills
-	if (Skillet) and (Skillet.GetNumTradeSkills) and
-	(Skillet.GetTradeSkillLine) and (Skillet.GetTradeSkillInfo) and
-	(Skillet.GetTradeSkillRecipeLink) and (Skillet.ExpandTradeSkillSubClass) then
-		self:Print("Enabling Skillet advanced features.")
-		GetNumTradeSkills = function(...) return Skillet:GetNumTradeSkills(...) end
-		GetTradeSkillLine = function(...) return Skillet:GetTradeSkillLine(...) end
-		GetTradeSkillInfo = function(...) return Skillet:GetTradeSkillInfo(...) end
-		GetTradeSkillRecipeLink = function(...) return Skillet:GetTradeSkillRecipeLink(...) end
-		ExpandTradeSkillSubClass = function(...) return Skillet:ExpandTradeSkillSubClass(...) end
-	end
-]]--
-	-------------------------------------------------------------------------------
-	-- Initialize the player's data.
-	-------------------------------------------------------------------------------
-	do
-		Player.faction = UnitFactionGroup("player")
-		Player["Class"] = select(2, UnitClass("player"))
-
-		-------------------------------------------------------------------------------
-		-- Get the player's professions.
-		-------------------------------------------------------------------------------
-		Player.professions = {
-			[GetSpellInfo(51304)]	= false, -- Alchemy
-			[GetSpellInfo(51300)]	= false, -- Blacksmithing
-			[GetSpellInfo(51296)]	= false, -- Cooking
-			[GetSpellInfo(51313)]	= false, -- Enchanting
-			[GetSpellInfo(51306)]	= false, -- Engineering
-			[GetSpellInfo(45542)]	= false, -- First Aid
-			[GetSpellInfo(51302)]	= false, -- Leatherworking
-			[GetSpellInfo(2656)]	= false, -- Smelting
-			[GetSpellInfo(51309)]	= false, -- Tailoring
-			[GetSpellInfo(51311)]	= false, -- Jewelcrafting
-			[GetSpellInfo(45363)]	= false, -- Inscription
-			[private.runeforging_name]	= false, -- Runeforging
-		}
-		Player:SetProfessions()
-
-		-------------------------------------------------------------------------------
-		-- Set the scanned state for all professions to false.
-		-------------------------------------------------------------------------------
-		Player.has_scanned = {}
-
-		for profession in pairs(Player.professions) do
-			Player.has_scanned[profession] = false
-		end
-
-	end	-- do
-
-	-------------------------------------------------------------------------------
-	-- Initialize the SpecialtyTable and AllSpecialtiesTable.
-	-------------------------------------------------------------------------------
-	do
-		local AlchemySpec = {
-			[GetSpellInfo(28674)] = 28674,
-			[GetSpellInfo(28678)] = 28678,
-			[GetSpellInfo(28676)] = 28676,
-		}
-
-		local BlacksmithSpec = {
-			[GetSpellInfo(9788)] = 9788,	-- Armorsmith
-			[GetSpellInfo(17041)] = 17041,	-- Master Axesmith
-			[GetSpellInfo(17040)] = 17040,	-- Master Hammersmith
-			[GetSpellInfo(17039)] = 17039,	-- Master Swordsmith
-			[GetSpellInfo(9787)] = 9787,	-- Weaponsmith
-		}
-
-		local EngineeringSpec = {
-			[GetSpellInfo(20219)] = 20219, -- Gnomish
-			[GetSpellInfo(20222)] = 20222, -- Goblin
-		}
-
-		local LeatherworkSpec = {
-			[GetSpellInfo(10657)] = 10657, -- Dragonscale
-			[GetSpellInfo(10659)] = 10659, -- Elemental
-			[GetSpellInfo(10661)] = 10661, -- Tribal
-		}
-
-		local TailorSpec = {
-			[GetSpellInfo(26797)] = 26797, -- Spellfire
-			[GetSpellInfo(26801)] = 26801, -- Shadoweave
-			[GetSpellInfo(26798)] = 26798, -- Primal Mooncloth
-		}
-
-		SpecialtyTable = {
-			[GetSpellInfo(51304)] = AlchemySpec,
-			[GetSpellInfo(51300)] = BlacksmithSpec,
-			[GetSpellInfo(51306)] = EngineeringSpec,
-			[GetSpellInfo(51302)] = LeatherworkSpec,
-			[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()
-	addon.Frame:Hide()
-
-	-- Remove the option from Manufac
-	if Manufac then
-		Manufac.options.args.ARLScan = nil
-	end
-end
-
--------------------------------------------------------------------------------
--- Event handling functions
--------------------------------------------------------------------------------
-
----Event used for datamining when a trainer is shown.
-function addon:TRAINER_SHOW()
-	self:ScanSkillLevelData(true)
-	self:ScanTrainerData(true)
-end
-
----Event used for datamining when a vendor is shown.
-function addon:MERCHANT_SHOW()
-	addon:ScanVendor()
-end
-
-do
-	local GetTradeSkillListLink = _G.GetTradeSkillListLink
-	local UnitName = _G.UnitName
-	local GetRealmName = _G.GetRealmName
-	local IsTradeSkillLinked = _G.IsTradeSkillLinked
-
-	function addon:TRADE_SKILL_SHOW()
-		-- If this is our own skill, save it, if not don't save it
-		if not IsTradeSkillLinked() then
-			local tradelink = GetTradeSkillListLink()
-
-			if tradelink then
-				local pname = UnitName("player")
-				local prealm = GetRealmName()
-				local tradename = 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 {}
-
-				addon.db.global.tradeskill[prealm][pname][tradename] = tradelink
-			end
-		end
-		local scan_button = self.scan_button
-		local scan_parent = scan_button:GetParent()
-
-		if not scan_parent or scan_parent == UIParent then
-			scan_button:SetParent(TradeSkillFrame)
-			scan_parent = scan_button:GetParent()
-		end
-
-		if scan_parent == TradeSkillFrame then
-			scan_button:ClearAllPoints()
-
-			local loc = addon.db.profile.scanbuttonlocation
-
-			if loc == "TR" then
-				scan_button:SetPoint("RIGHT", TradeSkillFrameCloseButton, "LEFT",4,0)
-			elseif loc == "TL" then
-				scan_button:SetPoint("LEFT", TradeSkillFramePortrait, "RIGHT",2,12)
-			elseif loc == "BR" then
-				scan_button:SetPoint("TOP", TradeSkillCancelButton, "BOTTOM",0,-5)
-			elseif loc == "BL" then
-				scan_button:SetPoint("TOP", TradeSkillCreateAllButton, "BOTTOM",0,-5)
-			end
-			scan_button:SetWidth(scan_button:GetTextWidth() + 10)
-		end
-		scan_button:Show()
-	end
-end
-
-function addon:TRADE_SKILL_CLOSE()
-	if addon.db.profile.closeguionskillclose then
-		self.Frame:Hide()
-	end
-
-	if not Skillet then
-		addon.scan_button:Hide()
-	end
-end
-
-do
-	local last_update = 0
-	local updater = CreateFrame("Frame", nil, UIParent)
-
-	updater:Hide()
-	updater:SetScript("OnUpdate",
-			  function(self, elapsed)
-				  last_update = last_update + elapsed
-
-				  if last_update >= 0.5 then
-					  local profession = 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:IsVisible() then
-			return
-		end
-
-		if not updater:IsVisible() then
-			last_update = 0
-			updater:Show()
-		end
-	end
-end
-
--------------------------------------------------------------------------------
--- Tradeskill functions
--- Recipe DB Structures are defined in Documentation.lua
--------------------------------------------------------------------------------
-
-do
-	local SF = private.recipe_state_flags
-
-	-------------------------------------------------------------------------------
-	-- Recipe member functions for bit flags.
-	-------------------------------------------------------------------------------
-	local function Recipe_HasState(self, state_name)
-		return self.state and (bit.band(self.state, SF[state_name]) == SF[state_name]) or false
-	end
-
-	local function Recipe_AddState(self, state_name)
-		if not self.state then
-			self.state = 0
-		end
-
-		if bit.band(self.state, SF[state_name]) == SF[state_name] then
-			return
-		end
-		self.state = bit.bxor(self.state, SF[state_name])
-	end
-
-	local function Recipe_RemoveState(self, state_name)
-		if not self.state then
-			return
-		end
-
-		if bit.band(self.state, SF[state_name]) ~= SF[state_name] then
-			return
-		end
-		self.state = bit.bxor(self.state, SF[state_name])
-
-		if self.state == 0 then
-			self.state = nil
-		end
-	end
-
-	local BITFIELD_MAP = {
-		["common1"]	= private.common_flags_word1,
-		["class1"]	= private.class_flags_word1,
-		["reputation1"]	= private.rep_flags_word1,
-		["reputation2"]	= private.rep_flags_word2,
-		["item1"]	= private.item_flags_word1,
-	}
-
-	local function Recipe_IsFlagged(self, field_name, flag_name)
-		local bitfield = self.flags[field_name]
-		local bitset = BITFIELD_MAP[field_name]
-		local value = bitset[flag_name]
-
-		return bitfield and (bit.band(bitfield, value) == value) or false
-	end
-
-	--- Adds a tradeskill recipe into the specified recipe database
-	-- @name AckisRecipeList:AddRecipe
-	-- @usage AckisRecipeList:AddRecipe(28927, 305, 23109, Q.UNCOMMON, V.TBC, 305, 305, 325, 345)
-	-- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe being added to the database
-	-- @param skill_level The skill level at which the recipe can be initially learned
-	-- @param item_id The [[http://www.wowwiki.com/ItemLink|Item ID]] that is created by the recipe, or nil
-	-- @param quality The quality/rarity of the recipe
-	-- @param profession The profession ID that uses the recipe.  See [[API/database-documentation]] for a listing of profession IDs
-	-- @param specialty The specialty that uses the recipe (ie: goblin engineering) or nil or blank
-	-- @param genesis Game version that the recipe was first introduced in, for example, Original, BC, or WoTLK
-	-- @param optimal_level Level at which recipe is considered orange
-	-- @param medium_level Level at which recipe is considered yellow
-	-- @param easy_level Level at which recipe is considered green
-	-- @param trivial_level Level at which recipe is considered grey
-	-- @return None, array is passed as a reference
-	function addon:AddRecipe(spell_id, skill_level, item_id, quality, profession, specialty, genesis, optimal_level, medium_level, easy_level, trivial_level)
-		local recipe_list = private.recipe_list
-
-		if recipe_list[spell_id] then
-			--@alpha@
-			self:Print("Duplicate recipe: "..recipe_list[spell_id].profession.." "..tostring(spell_id).." "..recipe_list[spell_id].name)
-			--@end-alpha@
-			return
-		end
-
-		local recipe = {
-			["spell_id"]		= spell_id,
-			["skill_level"]		= skill_level,
-			["item_id"]		= item_id,
-			["quality"]		= quality,
-			["profession"]		= GetSpellInfo(profession),
-			["name"]		= GetSpellInfo(spell_id),
-			["flags"]		= {},
-			["acquire_data"]	= {},
-			["specialty"]		= specialty,			-- Assumption: there will only be 1 speciality for a trade skill
-			["genesis"]		= private.game_version_names[genesis],
-			["optimal_level"]	= optimal_level or skill_level,
-			["medium_level"]	= medium_level or skill_level + 10,
-			["easy_level"]		= easy_level or skill_level + 15,
-			["trivial_level"]	= trivial_level or skill_level + 20,
-
-			-- Function members
-			["HasState"]		= Recipe_HasState,
-			["AddState"]		= Recipe_AddState,
-			["RemoveState"]		= Recipe_RemoveState,
-			["IsFlagged"]		= Recipe_IsFlagged,
-		}
-
-		if not recipe.name then
-			self:Print(strformat(L["SpellIDCache"], spell_id))
-		end
-		recipe_list[spell_id] = recipe
-	end
-end	-- do
-
--- Public API function for retrieving specific information about a recipe.
--- @name AckisRecipeList:GetRecipeData
--- @usage AckisRecipeList:GetRecipeData(28972, "profession")
--- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe being queried.
--- @param data Which member of the recipe table is being queried.
--- @return Variable, depending upon which member of the recipe table is queried.
-function addon:GetRecipeData(spell_id, data)
-	local recipe = private.recipe_list[spell_id]
-	return recipe and recipe[data] or nil
-end
-
---- Adds filtering flags to a specific tradeskill.
--- @name AckisRecipeList:AddRecipeFlags
--- @usage AckisRecipeList:AddRecipeFlags(28927, F.ALLIANCE, F.VENDOR, F.IBOE, F.RBOP, F.HEALER, F.CASTER, F.ALDOR)
--- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe which the filter flags are being added to
--- @param ... A listing of filtering flags.  See [[API/database-documentation]] for a listing of filter flags
--- @return None, array is passed as a reference.
-function addon:AddRecipeFlags(spell_id, ...)
-	local num_flags = select('#',...)
-	local recipe = private.recipe_list[spell_id]
-
-	for index = 1, num_flags, 1 do
-		local flag = select(index, ...)
-		local flag_name = private.filter_strings[flag]
-
-		local bitfield
-		local member_name
-
-		for table_index, bits in ipairs(private.bit_flags) do
-			if bits[flag_name] then
-				bitfield = bits
-				member_name = private.flag_members[table_index]
-			end
-		end
-
-		if not bitfield or not member_name then
-			return
-		end
-
-		if not recipe.flags[member_name] then
-			recipe.flags[member_name] = 0
-		end
-		recipe.flags[member_name] = bit.bxor(recipe.flags[member_name], bitfield[flag_name])
-	end
-end
-
---- Adds acquire methods to a specific tradeskill.
--- @name AckisRecipeList:AddRecipeAcquire
--- @usage AckisRecipeList:AddRecipeAcquire(28927, A.REPUTATION, FAC.ALDOR, REP.HONORED, 19321)
--- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe which acquire methods are being added to
--- @param ... A listing of acquire methods.  See [[API/database-documentation]] for a listing of acquire methods and how they work
--- @return None, array is passed as a reference.
-do
-	local location_list = private.location_list
-	local acquire_list = private.acquire_list
-
-	function addon:AddRecipeAcquire(spell_id, ...)
-		local numvars = select('#', ...)	-- Find out how many flags we're adding
-		local i = 1				-- Index for which variables we're parsing through
-		local recipe_list = private.recipe_list
-		local acquire_data = recipe_list[spell_id].acquire_data
-
-		while i <= numvars do
-			local location, affiliation
-
-			local acquire_type, acquire_id = select(i, ...)
-			i = i + 2
-
-			if not acquire_type then
-				self:Debug("Spell ID: %d has no acquire type.", spell_id)
-			else
-				acquire_data[acquire_type] = acquire_data[acquire_type] or {}
-
-				local acquire = acquire_data[acquire_type]
-
-				if not acquire_id then
-					self:Debug("Spell ID %d: %s ID is nil.", spell_id, private.acquire_strings[acquire_type])
-				else
-					if acquire_type == A.TRAINER then
-						local trainer_list = private.trainer_list
-						local trainer = trainer_list[acquire_id]
-
-						if not trainer then
-							self:Debug("Spell ID "..spell_id..": TrainerID "..acquire_id.." does not exist in the database.")
-						else
-							acquire[acquire_id] = true
-
-							affiliation = trainer.faction
-							location = trainer.location
-
-							trainer.item_list = trainer.item_list or {}
-							trainer.item_list[spell_id] = true
-						end
-					elseif acquire_type == A.VENDOR then
-						local vendor_list = private.vendor_list
-						local vendor = vendor_list[acquire_id]
-
-						if not vendor then
-							self:Debug("Spell ID "..spell_id..": VendorID "..acquire_id.." does not exist in the database.")
-						else
-							acquire[acquire_id] = true
-
-							affiliation = vendor.faction
-							location = vendor.location
-
-							vendor.item_list = vendor.item_list or {}
-							vendor.item_list[spell_id] = true
-						end
-					elseif acquire_type == A.MOB_DROP then
-						local mob_list = private.mob_list
-						local mob = mob_list[acquire_id]
-
-						if not mob then
-							self:Debug("Spell ID "..spell_id..": Mob ID "..acquire_id.." does not exist in the database.")
-						else
-							acquire[acquire_id] = true
-
-							affiliation = mob.faction
-							location = mob.location
-
-							mob_list[acquire_id].item_list = mob_list[acquire_id].item_list or {}
-							mob_list[acquire_id].item_list[spell_id] = true
-						end
-					elseif acquire_type == A.QUEST then
-						local quest_list = private.quest_list
-						local quest = quest_list[acquire_id]
-
-						if not quest then
-							self:Debug("Spell ID "..spell_id..": Quest ID "..acquire_id.." does not exist in the database.")
-						else
-							acquire[acquire_id] = true
-
-							affiliation = quest.faction
-							location = quest.location
-						end
-					elseif acquire_type == A.REPUTATION then
-						local vendor_list = private.vendor_list
-						local rep_level, vendor_id = select(i, ...)
-						i = i + 2
-
-						if not private.reputation_list[acquire_id] then
-							self:Debug("Spell ID "..spell_id..": ReputationID "..acquire_id.." does not exist in the database.")
-						else
-							if not vendor_id then
-								self:Debug("Spell ID "..spell_id..": Reputation Vendor ID is nil.")
-							elseif not vendor_list[vendor_id] then
-								self:Debug("Spell ID "..spell_id..": Reputation Vendor ID "..vendor_id.." does not exist in the database.")
-							else
-								acquire[acquire_id] = acquire[acquire_id] or {}
-
-								local faction = acquire[acquire_id]
-								faction[rep_level] = faction[rep_level] or {}
-								faction[rep_level][vendor_id] = true
-
-								local rep_vendor = vendor_list[vendor_id]
-
-								affiliation = rep_vendor.faction
-								location = rep_vendor.location
-
-								rep_vendor.item_list = rep_vendor.item_list or {}
-								rep_vendor.item_list[spell_id] = true
-							end
-						end
-					elseif acquire_type == A.WORLD_DROP then
-						acquire[acquire_id] = true
-						location = type(acquire_id) == "string" and BZ[acquire_id] or nil
-
-						if location then
-							affiliation = "world_drop"
-						else
-							addon:Debug("WORLD_DROP with no location: %d %s", spell_id, recipe_list[spell_id].name)
-						end
-					elseif acquire_type == A.SEASONAL then
-						acquire[acquire_id] = true
-					elseif acquire_type == A.CUSTOM then
-						acquire[acquire_id] = true
-						location = private.custom_list[acquire_id].location
-					else
-						-- Unhandled acquire_type
-						acquire[acquire_id] = true
-						location = private.acquire_strings[acquire_type] or _G.UNKNOWN
-					end
-				end	-- acquire_id
-				acquire_list[acquire_type] = acquire_list[acquire_type] or {}
-				acquire_list[acquire_type].recipes = acquire_list[acquire_type].recipes or {}
-
-				acquire_list[acquire_type].name = private.acquire_names[acquire_type]
-				acquire_list[acquire_type].recipes[spell_id] = affiliation or true
-			end	-- acquire_type
-
-			if location then
-				location_list[location] = location_list[location] or {}
-				location_list[location].recipes = location_list[location].recipes or {}
-
-				location_list[location].name = location
-				location_list[location].recipes[spell_id] = affiliation or true
-			end
-		end	-- while
-	end
-
-	local function GenericAddRecipeAcquire(spell_id, acquire_type, type_string, unit_list, ...)
-		local num_vars = select('#', ...)
-		local cur_var = 1
-		local recipe = private.recipe_list[spell_id]
-
-		local acquire_data = recipe.acquire_data
-		acquire_data[acquire_type] = acquire_data[acquire_type] or {}
-
-		local acquire = acquire_data[acquire_type]
-
-		while cur_var <= num_vars do
-			local location, affiliation
-			local id_num = select(cur_var, ...)
-			cur_var = cur_var + 1
-
-			-- A quantity of true means unlimited - normal vendor item.
-			local quantity = true
-
-			if type_string == "Limited Vendor" then
-				quantity = select(cur_var, ...)
-				cur_var = cur_var + 1
-			end
-			acquire[id_num] = true
-
-			if unit_list and not unit_list[id_num] then
-				addon:Debug("Spell ID %d: %s ID %d does not exist in the database.", spell_id, type_string, id_num)
-			else
-				if not unit_list then
-					location = type(id_num) == "string" and BZ[id_num] or nil
-
-					if location then
-						affiliation = "world_drop"
-					else
-						addon:Debug("WORLD_DROP with no location: %d %s", spell_id, private.recipe_list[spell_id].name)
-					end
-				else
-					local unit = unit_list[id_num]
-
-					affiliation = unit.faction
-					location = unit.location
-
-					unit.item_list = unit.item_list or {}
-					unit.item_list[spell_id] = quantity
-				end
-			end
-			acquire_list[acquire_type] = acquire_list[acquire_type] or {}
-			acquire_list[acquire_type].recipes = acquire_list[acquire_type].recipes or {}
-
-			acquire_list[acquire_type].name = private.acquire_names[acquire_type]
-			acquire_list[acquire_type].recipes[spell_id] = affiliation or true
-
-			if location then
-				location_list[location] = location_list[location] or {}
-				location_list[location].recipes = location_list[location].recipes or {}
-
-				location_list[location].name = location
-				location_list[location].recipes[spell_id] = affiliation or true
-			end
-		end
-	end
-
-	function addon:AddRecipeMobDrop(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.MOB_DROP, "Mob", private.mob_list, ...)
-	end
-
-	function addon:AddRecipeTrainer(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.TRAINER, "Trainer", private.trainer_list, ...)
-	end
-
-	function addon:AddRecipeVendor(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.VENDOR, "Vendor", private.vendor_list, ...)
-	end
-
-	function addon:AddRecipeLimitedVendor(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.VENDOR, "Limited Vendor", private.vendor_list, ...)
-	end
-
-	function addon:AddRecipeWorldDrop(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.WORLD_DROP, nil, nil, ...)
-	end
-
-	function addon:AddRecipeQuest(spell_id, ...)
-		GenericAddRecipeAcquire(spell_id, A.QUEST, "Quest", private.quest_list, ...)
-	end
-
-	-- This function can NOT use GenericAddRecipeAcquire() - reputation vendors are more complicated than the other acquire types.
-	function addon:AddRecipeRepVendor(spell_id, faction_id, rep_level, ...)
-		local num_vars = select('#', ...)
-		local cur_var = 1
-
-		local recipe = private.recipe_list[spell_id]
-		local vendor_list = private.vendor_list
-
-		local acquire_data = recipe.acquire_data
-		acquire_data[A.REPUTATION] = acquire_data[A.REPUTATION] or {}
-
-		local acquire = acquire_data[A.REPUTATION]
-		acquire[faction_id] = acquire[faction_id] or {}
-
-		local faction = acquire[faction_id]
-		faction[rep_level] = faction[rep_level] or {}
-
-		while cur_var <= num_vars do
-			local location, affiliation
-			local vendor_id = select(cur_var, ...)
-			cur_var = cur_var + 1
-
-			if not private.reputation_list[faction_id] then
-				--@alpha@
-				self:Printf("Spell ID %d: Faction ID %d does not exist in the database.", spell_id, faction_id)
-				--@end-alpha@
-			else
-				if not vendor_id then
-					--@alpha@
-					self:Print("Spell ID "..spell_id..": Reputation Vendor ID is nil.")
-					--@end-alpha@
-				elseif not vendor_list[vendor_id] then
-					--@alpha@
-					self:Print("Spell ID "..spell_id..": Reputation Vendor ID "..vendor_id.." does not exist in the database.")
-					--@end-alpha@
-				else
-					faction[rep_level][vendor_id] = true
-
-					local rep_vendor = vendor_list[vendor_id]
-
-					affiliation = rep_vendor.faction
-					location = rep_vendor.location
-
-					rep_vendor.item_list = rep_vendor.item_list or {}
-					rep_vendor.item_list[spell_id] = true
-				end
-			end
-			acquire_list[A.REPUTATION] = acquire_list[A.REPUTATION] or {}
-			acquire_list[A.REPUTATION].recipes = acquire_list[A.REPUTATION].recipes or {}
-
-			acquire_list[A.REPUTATION].name = private.acquire_names[A.REPUTATION]
-			acquire_list[A.REPUTATION].recipes[spell_id] = affiliation or true
-
-			if location then
-				location_list[location] = location_list[location] or {}
-				location_list[location].recipes = location_list[location].recipes or {}
-
-				location_list[location].name = location
-				location_list[location].recipes[spell_id] = affiliation or true
-			end
-		end
-	end
-end	-- do block
-
---- Adds an item to a specific database listing (ie: vendor, mob, etc)
--- @name AckisRecipeList:addLookupList
--- @usage AckisRecipeList:addLookupList(DB,NPC ID, NPC Name, NPC Location, X Coord, Y Coord, Faction)
--- @param DB Database which the entry will be stored
--- @param ID Unique identified for the entry
--- @param name Name of the entry
--- @param location Location of the entry in the world
--- @param coord_x X coordinate of where the entry is found
--- @param coord_y Y coordinate of where the entry is found
--- @param faction Faction identifier for the entry
--- @return None, array is passed as a reference
---For individual database structures, see Documentation.lua
-do
-	local FACTION_NAMES = {
-		[1]	= BFAC["Neutral"],
-		[2]	= BFAC["Alliance"],
-		[3]	= BFAC["Horde"]
-	}
-	function addon:addLookupList(DB, ID, name, location, coord_x, coord_y, faction)
-		if DB[ID] then
-			self:Debug("Duplicate lookup: %d - %s.", ID, name)
-			return
-		end
-
-		DB[ID] = {
-			["name"]	= name,
-			["location"]	= location,
-			["faction"]	= faction and FACTION_NAMES[faction + 1] or FACTION_NAMES[1]
-		}
-
-		if coord_x and coord_y then
-			DB[ID]["coord_x"] = coord_x
-			DB[ID]["coord_y"] = coord_y
-		end
-
-		--@alpha@
-		if not location and DB ~= private.custom_list then
-			self:Debug("Lookup ID: %d (%s) has an unknown location.", ID, DB[ID].name or _G.UNKNOWN)
-		end
-
-		if faction and DB == private.mob_list then
-			self:Debug("Mob %d (%s) has been assigned to faction %s.", ID, name, DB[ID].faction)
-		end
-		--@end-alpha@
-	end
-end	-- do
-
--------------------------------------------------------------------------------
--- Filter flag functions
--------------------------------------------------------------------------------
-do
-	local COMMON1 = private.common_flags_word1
-	local CLASS1 = private.class_flags_word1
-	local REP1 = private.rep_flags_word1
-	local REP2 = private.rep_flags_word2
-	local ITEM1 = private.item_flags_word1
-
-	-- HardFilterFlags and SoftFilterFlags are used to determine if a recipe should be shown based on the value of the key compared to the value of its saved_var.
-	-- Its keys and values are populated the first time CanDisplayRecipe() is called.
-	local HardFilterFlags, SoftFilterFlags, RepFilterFlags, RepFilterFlags2
-
-	local ClassFilterFlags = {
-		["deathknight"]	= CLASS1.DK,
-		["druid"]	= CLASS1.DRUID,
-		["hunter"]	= CLASS1.HUNTER,
-		["mage"]	= CLASS1.MAGE,
-		["paladin"]	= CLASS1.PALADIN,
-		["priest"]	= CLASS1.PRIEST,
-		["shaman"]	= CLASS1.SHAMAN,
-		["rogue"]	= CLASS1.ROGUE,
-		["warlock"]	= CLASS1.WARLOCK,
-		["warrior"]	= CLASS1.WARRIOR,
-	}
-
-	---Scans a specific recipe to determine if it is to be displayed or not.
-	-- For flag info see comments at start of file in comments
-	local function CanDisplayRecipe(recipe)
-		if addon.db.profile.exclusionlist[recipe.spell_id] and not addon.db.profile.ignoreexclusionlist then
-			return false
-		end
-		local filter_db = addon.db.profile.filters
-		local general_filters = filter_db.general
-
-		-- See Documentation file for logic explanation
-		-------------------------------------------------------------------------------
-		-- Stage 1
-		-- Loop through exclusive flags (hard filters)
-		-- If one of these does not pass we do not display the recipe
-		-- So to be more efficient we'll just leave this function if there's a false
-		-------------------------------------------------------------------------------
-
-		-- Display both horde and alliance factions?
-		if not general_filters.faction and not Player:HasRecipeFaction(recipe) then
-			return false
-		end
-
-		-- Display all skill levels?
-		if not general_filters.skill and recipe.skill_level > Player["ProfessionLevel"] then
-			return false
-		end
-
-		-- Display all specialities?
-		if not general_filters.specialty then
-			local specialty = recipe.specialty
-
-			if specialty and specialty ~= Player["Specialty"] then
-				return false
-			end
-		end
-
-		-- Display retired recipes?
-		if not general_filters.retired and bit.band(recipe.flags.common1, COMMON1.RETIRED) == COMMON1.RETIRED then
-			return false
-		end
-		local obtain_filters = filter_db.obtain
-		local game_version = private.game_versions[recipe.genesis]
-		local V = private.game_versions
-
-		-- Filter out game recipes
-		if not obtain_filters.expansion0 and game_version == V.ORIG then
-			return false
-		end
-
-		if not obtain_filters.expansion1 and game_version == V.TBC then
-			return false
-		end
-
-		if not obtain_filters.expansion2 and game_version == V.WOTLK then
-			return false
-		end
-		local quality_filters = filter_db.quality
-		local recipe_quality = recipe.quality
-		local Q = private.item_qualities
-
-		-- Filter out certain recipe quality types.
-		if not quality_filters.common and recipe_quality == Q.COMMON then
-			return false
-		end
-
-		if not quality_filters.uncommon and recipe_quality == Q.UNCOMMON then
-			return false
-		end
-
-		if not quality_filters.rare and recipe_quality == Q.RARE then
-			return false
-		end
-
-		if not quality_filters.epic and recipe_quality == Q.EPIC then
-			return false
-		end
-
-		-------------------------------------------------------------------------------
-		-- Check the hard filter flags
-		-------------------------------------------------------------------------------
-		if not HardFilterFlags then
-			local binding_filters	= filter_db.binding
-			local player_filters	= filter_db.player
-			local armor_filters	= filter_db.item.armor
-			local weapon_filters	= filter_db.item.weapon
-
-			HardFilterFlags = {
-				------------------------------------------------------------------------------------------------
-				-- Binding flags.
-				------------------------------------------------------------------------------------------------
-				["itemboe"]	= { flag = COMMON1.IBOE,	index = 1,	sv_root = binding_filters },
-				["itembop"]	= { flag = COMMON1.IBOP,	index = 1,	sv_root = binding_filters },
-				["itemboa"]	= { flag = COMMON1.IBOA,	index = 1,	sv_root = binding_filters },
-				["recipeboe"]	= { flag = COMMON1.RBOE,	index = 1,	sv_root = binding_filters },
-				["recipebop"]	= { flag = COMMON1.RBOP,	index = 1,	sv_root = binding_filters },
-				["recipeboa"]	= { flag = COMMON1.RBOA,	index = 1,	sv_root = binding_filters },
-				------------------------------------------------------------------------------------------------
-				-- Player Type flags.
-				------------------------------------------------------------------------------------------------
-				["melee"]	= { flag = COMMON1.DPS,		index = 1,	sv_root = player_filters },
-				["tank"]	= { flag = COMMON1.TANK,	index = 1,	sv_root = player_filters },
-				["healer"]	= { flag = COMMON1.HEALER,	index = 1,	sv_root = player_filters },
-				["caster"]	= { flag = COMMON1.CASTER,	index = 1,	sv_root = player_filters },
-				------------------------------------------------------------------------------------------------
-				-- Armor flags.
-				------------------------------------------------------------------------------------------------
-				["cloth"]	= { flag = ITEM1.CLOTH,		index = 5,	sv_root = armor_filters },
-				["leather"]	= { flag = ITEM1.LEATHER,	index = 5,	sv_root = armor_filters },
-				["mail"]	= { flag = ITEM1.MAIL,		index = 5,	sv_root = armor_filters },
-				["plate"]	= { flag = ITEM1.PLATE,		index = 5,	sv_root = armor_filters },
-				["trinket"]	= { flag = ITEM1.TRINKET,	index = 5,	sv_root = armor_filters },
-				["cloak"]	= { flag = ITEM1.CLOAK,		index = 5,	sv_root = armor_filters },
-				["ring"]	= { flag = ITEM1.RING,		index = 5,	sv_root = armor_filters },
-				["necklace"]	= { flag = ITEM1.NECK,		index = 5,	sv_root = armor_filters },
-				["shield"]	= { flag = ITEM1.SHIELD,	index = 5,	sv_root = armor_filters },
-				------------------------------------------------------------------------------------------------
-				-- Weapon flags.
-				------------------------------------------------------------------------------------------------
-				["onehand"]	= { flag = ITEM1.ONE_HAND,	index = 5,	sv_root = weapon_filters },
-				["twohand"]	= { flag = ITEM1.TWO_HAND,	index = 5,	sv_root = weapon_filters },
-				["axe"]		= { flag = ITEM1.AXE,		index = 5,	sv_root = weapon_filters },
-				["sword"]	= { flag = ITEM1.SWORD,		index = 5,	sv_root = weapon_filters },
-				["mace"]	= { flag = ITEM1.MACE,		index = 5,	sv_root = weapon_filters },
-				["polearm"]	= { flag = ITEM1.POLEARM,	index = 5,	sv_root = weapon_filters },
-				["dagger"]	= { flag = ITEM1.DAGGER,	index = 5,	sv_root = weapon_filters },
-				["fist"]	= { flag = ITEM1.FIST,		index = 5,	sv_root = weapon_filters },
-				["gun"]		= { flag = ITEM1.GUN,		index = 5,	sv_root = weapon_filters },
-				["staff"]	= { flag = ITEM1.STAFF,		index = 5,	sv_root = weapon_filters },
-				["wand"]	= { flag = ITEM1.WAND,		index = 5,	sv_root = weapon_filters },
-				["thrown"]	= { flag = ITEM1.THROWN,	index = 5,	sv_root = weapon_filters },
-				["bow"]		= { flag = ITEM1.BOW,		index = 5,	sv_root = weapon_filters },
-				["crossbow"]	= { flag = ITEM1.XBOW,		index = 5,	sv_root = weapon_filters },
-				["ammo"]	= { flag = ITEM1.AMMO,		index = 5,	sv_root = weapon_filters },
-			}
-		end
-
-		for filter, data in pairs(HardFilterFlags) do
-			local bitfield = recipe.flags[private.flag_members[data.index]]
-
-			if bitfield and bit.band(bitfield, data.flag) == data.flag and not data.sv_root[filter] then
-				return false
-			end
-		end
-
-		-------------------------------------------------------------------------------
-		-- Check the reputation filter flags
-		-------------------------------------------------------------------------------
-		if not RepFilterFlags then
-			RepFilterFlags = {
-				[REP1.ARGENTDAWN]		= "argentdawn",
-				[REP1.CENARION_CIRCLE]		= "cenarioncircle",
-				[REP1.THORIUM_BROTHERHOOD]	= "thoriumbrotherhood",
-				[REP1.TIMBERMAW_HOLD]		= "timbermaw",
-				[REP1.ZANDALAR]			= "zandalar",
-				[REP1.ALDOR]			= "aldor",
-				[REP1.ASHTONGUE]		= "ashtonguedeathsworn",
-				[REP1.CENARION_EXPEDITION]	= "cenarionexpedition",
-				[REP1.HELLFIRE]			= "hellfire",
-				[REP1.CONSORTIUM]		= "consortium",
-				[REP1.KOT]			= "keepersoftime",
-				[REP1.LOWERCITY]		= "lowercity",
-				[REP1.NAGRAND]			= "nagrand",
-				[REP1.SCALE_SANDS]		= "scaleofthesands",
-				[REP1.SCRYER]			= "scryer",
-				[REP1.SHATAR]			= "shatar",
-				[REP1.SHATTEREDSUN]		= "shatteredsun",
-				[REP1.SPOREGGAR]		= "sporeggar",
-				[REP1.VIOLETEYE]		= "violeteye",
-				[REP1.ARGENTCRUSADE]		= "argentcrusade",
-				[REP1.FRENZYHEART]		= "frenzyheart",
-				[REP1.EBONBLADE]		= "ebonblade",
-				[REP1.KIRINTOR]			= "kirintor",
-				[REP1.HODIR]			= "sonsofhodir",
-				[REP1.KALUAK]			= "kaluak",
-				[REP1.ORACLES]			= "oracles",
-				[REP1.WYRMREST]			= "wyrmrest",
-				[REP1.WRATHCOMMON1]		= "wrathcommon1",
-				[REP1.WRATHCOMMON2]		= "wrathcommon2",
-				[REP1.WRATHCOMMON3]		= "wrathcommon3",
-				[REP1.WRATHCOMMON4]		= "wrathcommon4",
-				[REP1.WRATHCOMMON5]		= "wrathcommon5",
-			}
-		end
-
-		if not RepFilterFlags2 then
-			RepFilterFlags2 = {
-				[REP2.ASHEN_VERDICT]	= "ashenverdict",
-			}
-		end
-		-- Now we check to see if _all_ of the pertinent reputation or class flags are toggled off. If even one is toggled on, we still show the recipe.
-		local toggled_off, toggled_on = 0, 0
-
-		for flag, name in pairs(RepFilterFlags) do
-			local bitfield = recipe.flags.reputation1
-
-			if bitfield and bit.band(bitfield, flag) == flag then
-				if filter_db.rep[name] then
-					toggled_on = toggled_on + 1
-				else
-					toggled_off = toggled_off + 1
-				end
-			end
-		end
-
-		if toggled_off > 0 and toggled_on == 0 then
-			return false
-		end
-
-		toggled_off, toggled_on = 0, 0
-
-		for flag, name in pairs(RepFilterFlags2) do
-			local bitfield = recipe.flags.reputation2
-
-			if bitfield and bit.band(bitfield, flag) == flag then
-				if filter_db.rep[name] then
-					toggled_on = toggled_on + 1
-				else
-					toggled_off = toggled_off + 1
-				end
-			end
-		end
-
-		if toggled_off > 0 and toggled_on == 0 then
-			return false
-		end
-
-		-------------------------------------------------------------------------------
-		-- Check the class filter flags
-		-------------------------------------------------------------------------------
-		local class_filters = filter_db.classes
-
-		toggled_off, toggled_on = 0, 0
-
-		for class, flag in pairs(ClassFilterFlags) do
-			local bitfield = recipe.flags.class1
-
-			if bitfield and bit.band(bitfield, flag) == flag then
-				if class_filters[class] then
-					toggled_on = toggled_on + 1
-				else
-					toggled_off = toggled_off + 1
-				end
-			end
-		end
-
-		if toggled_off > 0 and toggled_on == 0 then
-			return false
-		end
-
-		------------------------------------------------------------------------------------------------
-		-- Stage 2
-		-- loop through nonexclusive (soft filters) flags until one is true
-		-- If one of these is true (ie: we want to see trainers and there is a trainer flag) we display the recipe
-		------------------------------------------------------------------------------------------------
-		if not SoftFilterFlags then
-			SoftFilterFlags = {
-				["trainer"]	= { flag = COMMON1.TRAINER,	index = 1,	sv_root = obtain_filters },
-				["vendor"]	= { flag = COMMON1.VENDOR,	index = 1,	sv_root = obtain_filters },
-				["instance"]	= { flag = COMMON1.INSTANCE,	index = 1,	sv_root = obtain_filters },
-				["raid"]	= { flag = COMMON1.RAID,	index = 1,	sv_root = obtain_filters },
-				["seasonal"]	= { flag = COMMON1.SEASONAL,	index = 1,	sv_root = obtain_filters },
-				["quest"]	= { flag = COMMON1.QUEST,	index = 1,	sv_root = obtain_filters },
-				["pvp"]		= { flag = COMMON1.PVP,		index = 1,	sv_root = obtain_filters },
-				["worlddrop"]	= { flag = COMMON1.WORLD_DROP,	index = 1,	sv_root = obtain_filters },
-				["mobdrop"]	= { flag = COMMON1.MOB_DROP,	index = 1,	sv_root = obtain_filters },
-				["discovery"]	= { flag = COMMON1.DISC,	index = 1,	sv_root = obtain_filters },
-			}
-		end
-
-		for filter, data in pairs(SoftFilterFlags) do
-			local bitfield = recipe.flags[private.flag_members[data.index]]
-
-			if bitfield and bit.band(bitfield, data.flag) == data.flag and data.sv_root[filter] then
-				return true
-			end
-		end
-
-		-- If we get here it means that no flags matched our values
-		return false
-	end
-
-	---Scans the recipe listing and updates the filters according to user preferences
-	function addon:UpdateFilters(is_linked)
-		local general_filters = addon.db.profile.filters.general
-		local recipes_total = 0
-		local recipes_known = 0
-		local recipes_total_filtered = 0
-		local recipes_known_filtered = 0
-		local can_display = false
-		local current_profession = self.Frame.prof_name or private.ordered_professions[self.Frame.profession]
-		local recipe_list = private.recipe_list
-		local SF = private.recipe_state_flags
-
-		for recipe_id, recipe in pairs(recipe_list) do
-			recipe:RemoveState("VISIBLE")
-
-			if recipe.profession == current_profession then
-				local is_known
-
-				if is_linked then
-					is_known = recipe:HasState("LINKED")
-				else
-					is_known = recipe:HasState("KNOWN")
-				end
-
-				can_display = CanDisplayRecipe(recipe)
-				recipes_total = recipes_total + 1
-				recipes_known = recipes_known + (is_known and 1 or 0)
-
-				if can_display then
-					recipes_total_filtered = recipes_total_filtered + 1
-					recipes_known_filtered = recipes_known_filtered + (is_known and 1 or 0)
-
-					if not general_filters.known and is_known then
-						can_display = false
-					end
-
-					if not general_filters.unknown and not is_known then
-						can_display = false
-					end
-				end
-			else
-				can_display = false
-			end
-
-			if can_display then
-				recipe:AddState("VISIBLE")
-			end
-		end
-		Player.recipes_total = recipes_total
-		Player.recipes_known = recipes_known
-		Player.recipes_total_filtered = recipes_total_filtered
-		Player.recipes_known_filtered = recipes_known_filtered
-		end
-
-end	-- do
-
--------------------------------------------------------------------------------
--- 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_INITS[profession]
-
-	if func then
-		return func(addon)
-	else
-		addon:Print(L["UnknownTradeSkill"]:format(profession))
-		return 0
-	end
-end
-
--- Determines what to do when the slash command is called.
-function addon:ChatCommand(input)
-
-	-- Open About panel if there's no parameters or if we do /arl about
-	if not input or (input and input:trim() == "") or input == strlower(L["Sorting"]) or input == strlower(L["Sort"])  or input == strlower(_G.DISPLAY) then
-		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
-	elseif (input == strlower(L["About"])) then
-		if (self.optionsFrame["About"]) then
-			InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["About"])
-		else
-			InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
-		end
-	elseif (input == strlower(L["Profile"])) then
-		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Profiles"])
-	elseif (input == strlower(_G.FILTER)) then
-		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Filters"])
-	elseif (input == strlower(L["Documentation"])) then
-		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Documentation"])
-	elseif (input == strlower(L["Scan"])) then
-		self:Scan(false)
-	elseif (input == strlower("scandata")) then
-		self:ScanSkillLevelData()
-	elseif (input == strlower("scanprof")) then
-		self:ScanProfession("all")
-	elseif (input == strlower("tradelinks")) then
-		self:GenerateLinks()
-	else
-		-- What happens when we get here?
-		LibStub("AceConfigCmd-3.0"):HandleCommand("arl", "Ackis Recipe List", input)
-	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 = {}
-
-	--- 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 = GetTradeSkillLine()
-
-		-- Bail if we haven't opened a tradeskill frame.
-		if current_prof == "UNKNOWN" then
-			self:Print(L["OpenTradeSkillWindow"])
-			return
-		end
-
-		-- Set the current profession level, and update the cached data.
-		Player["ProfessionLevel"] = 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 = IsTradeSkillLinked()
-
-		if not is_linked and Player.professions[current_prof] then
-			Player.professions[current_prof] = prof_level
-			Player.has_scanned[current_prof] = true
-		end
-
-		-- Get the current profession Specialty
-		local specialty = SpecialtyTable[current_prof]
-
-		for index = 1, 25, 1 do
-			local spellName = GetSpellName(index, BOOKTYPE_SPELL)
-
-			if not spellName or index == 25 then
-				Player["Specialty"] = nil
-				break
-			elseif specialty and specialty[spellName] then
-				Player["Specialty"] = specialty[spellName]
-				break
-			end
-		end
-
-		if self.InitializeLookups then
-			self:InitializeLookups()
-		end
-		-- Add the recipes to the database
-		-- TODO: Figure out what this variable was supposed to be for - it isn't used anywhere. -Torhal
-		Player.totalRecipes = addon:InitializeProfession(current_prof)
-
-		-------------------------------------------------------------------------------
-		-- Scan all recipes and mark the ones we know
-		-------------------------------------------------------------------------------
-		twipe(header_list)
-
-		-- Save the state of the "Have Materials" checkbox.
-		local have_materials = TradeSkillFrameAvailableFilterCheckButton:GetChecked()
-
-		if MRTUIUtils_PushFilterSelection then
-			MRTUIUtils_PushFilterSelection()
-		else
-			if not Skillet and TradeSkillFrameAvailableFilterCheckButton:GetChecked() then
-				TradeSkillFrameAvailableFilterCheckButton:SetChecked(false)
-				TradeSkillOnlyShowMakeable(false)
-			end
-
-			-- Clear the inventory slot filter
-			UIDropDownMenu_Initialize(TradeSkillInvSlotDropDown, TradeSkillInvSlotDropDown_Initialize)
-			UIDropDownMenu_SetSelectedID(TradeSkillInvSlotDropDown, 1)
-			SetTradeSkillInvSlotFilter(0, 1, 1)
-
-			-- Clear the sub-classes filters
-			UIDropDownMenu_Initialize(TradeSkillSubClassDropDown, TradeSkillSubClassDropDown_Initialize)
-			UIDropDownMenu_SetSelectedID(TradeSkillSubClassDropDown, 1)
-			SetTradeSkillSubClassFilter(0, 1, 1)
-
-			-- Expand all headers so we can see all the recipes there are
-			for i = GetNumTradeSkills(), 1, -1 do
-				local name, tradeType, _, isExpanded = GetTradeSkillInfo(i)
-
-				if tradeType == "header" and not isExpanded then
-					header_list[name] = true
-					ExpandTradeSkillSubClass(i)
-				end
-			end
-		end
-		local recipe_list = private.recipe_list
-		local recipes_found = 0
-		local SF = private.recipe_state_flags
-
-		for i = 1, GetNumTradeSkills() do
-			local tradeName, tradeType = GetTradeSkillInfo(i)
-
-			if tradeType ~= "header" then
-				-- Get the trade skill link for the specified recipe
-				local SpellLink = GetTradeSkillRecipeLink(i)
-				local SpellString = strmatch(SpellLink, "^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)")
-				local recipe = recipe_list[tonumber(SpellString)]
-
-				if recipe then
-					if not is_linked then
-						recipe:AddState("KNOWN")
-						recipe:RemoveState("LINKED")
-					else
-						recipe:AddState("LINKED")
-					end
-					recipes_found = recipes_found + 1
-				else
-					self:Debug(tradeName .. " " .. SpellString .. L["MissingFromDB"])
-				end
-			end
-		end
-
-		-- Close all the headers we've opened
-		-- If Mr Trader is installed use that API
-		if MRTUIUtils_PopFilterSelection then
-			MRTUIUtils_PopFilterSelection()
-		else
-			-- Collapse all headers that were collapsed before
-			for i = GetNumTradeSkills(), 1, -1 do
-				local name, tradeType, _, isExpanded = GetTradeSkillInfo(i)
-
-				if header_list[name] then
-					CollapseTradeSkillSubClass(i)
-				end
-			end
-			-- Restore the state of the "Have Materials" checkbox.
-			TradeSkillFrameAvailableFilterCheckButton:SetChecked(have_materials)
-			TradeSkillOnlyShowMakeable(have_materials)
-		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["Reputation"] = Player["Reputation"] or {}
-
-		table.wipe(header_list)
-
-		-- Number of factions before expansion
-		local num_factions = GetNumFactions()
-
-		-- Expand all the headers, storing those which were collapsed.
-		for i = num_factions, 1, -1 do
-			local name, _, _, _, _, _, _, _, _, isCollapsed = GetFactionInfo(i)
-
-			if isCollapsed then
-				ExpandFactionHeader(i)
-				header_list[name] = true
-			end
-		end
-
-		-- Number of factions with everything expanded
-		num_factions = GetNumFactions()
-
-		-- Get the rep levels
-		for i = 1, num_factions, 1 do
-			local name, _, replevel = GetFactionInfo(i)
-
-			-- If the rep is greater than neutral
-			if replevel > 4 then
-				-- We use levels of 0, 1, 2, 3, 4 internally for reputation levels, make it correspond here
-				Player["Reputation"][name] = replevel - 4
-			end
-		end
-
-		-- Collapse the headers again
-		for i = num_factions, 1, -1 do
-			local name = GetFactionInfo(i)
-
-			if header_list[name] then
-				CollapseFactionHeader(i)
-			end
-		end
-
-		-------------------------------------------------------------------------------
-		-- Everything is ready - display the GUI or dump the list to text.
-		-------------------------------------------------------------------------------
-		if textdump then
-			self:DisplayTextDump(recipe_list, current_prof)
-		else
-			self.Frame:Display(current_prof, is_linked)
-		end
-	end
-end
-
--------------------------------------------------------------------------------
--- Text dumping functions
--------------------------------------------------------------------------------
-do
-	-------------------------------------------------------------------------------
-	-- Provides a string of comma separated values for all recipe information
-	-------------------------------------------------------------------------------
-	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 = (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"],
-				}
-			end
-			return FILTER_NAMES
-		end
-	end	-- do
-
-	---Dumps the recipe database in a format that is readable to humans.
-	function addon:GetTextDump(profession)
-		local output = addon.db.profile.textdumpformat
-		twipe(text_table)
-
-		if not output or output == "Comma" then
-			tinsert(text_table, strformat("Ackis Recipe List Text Dump for %s's %s, in the form of Comma Separated Values.\n  ", UnitName("player"), profession))
-			tinsert(text_table, "Spell ID,Recipe Name,Skill Level,ARL Filter Flags,Acquire Methods,Known\n")
-		elseif output == "BBCode" then
-			tinsert(text_table, strformat("Ackis Recipe List Text Dump for %s's %s, in the form of BBCode.\n", UnitName("player"), profession))
-		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 = 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
-					tinsert(text_table, recipe_id)
-					tinsert(text_table, ",")
-					tinsert(text_table, recipe.name)
-					tinsert(text_table, ",")
-					tinsert(text_table, recipe.skill_level)
-					tinsert(text_table, ",\"")
-				-- BBCode
-				elseif output == "BBCode" then
-					-- Make the entry red
-					if not is_known then
-						tinsert(text_table, "[color=red]")
-					end
-					tinsert(text_table, "\n[b]" .. recipe_id .. "[/b] - " .. recipe.name .. " (" .. recipe.skill_level .. ")\n")
-
-					-- Close Color tag
-					if not is_known then
-						tinsert(text_table, "[/color]\nRecipe Flags:\n[list]")
-					elseif is_known then
-						tinsert(text_table, "\nRecipe Flags:\n[list]")
-					end
-				--Name
-				elseif output == "Name" then
-					tinsert(text_table, recipe.name.."\n")
-				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
-									tinsert(text_table, ",")
-								end
-								tinsert(text_table, filter_names[private.filter_flags[flag_name]])
-								prev = true
-								-- BBCode
-							elseif output == "BBCode" then
-								tinsert(text_table, "[*]" .. filter_names[private.filter_flags[flag_name]])
-							end
-						end
-					end
-				end
-
-				if not output or output == "Comma" then
-					tinsert(text_table, "\",\"")
-				elseif output == "BBCode" then
-					tinsert(text_table, "[/list]\nAcquire Methods:\n[list]")
-				end
-
-				-- Find out which unique acquire methods we have
-				local acquire_data = recipe["acquire_data"]
-				twipe(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
-							tinsert(text_table, ",")
-						end
-						tinsert(text_table, i)
-						prev = true
-					elseif output == "BBCode" then
-						tinsert(text_table, "[*] " .. i)
-					end
-				end
-
-				if not output or output == "Comma" then
-					if is_known then
-						tinsert(text_table, "\",true\n")
-					else
-						tinsert(text_table, "\",false\n")
-					end
-				elseif output == "BBCode" then
-					tinsert(text_table, "\n[/list]")
-				end
-			end
-		end	-- for
-		return tconcat(text_table, "")
-	end
-end
diff --git a/AckisRecipeList.toc b/AckisRecipeList.toc
index 55d10a2..f0376d6 100644
--- a/AckisRecipeList.toc
+++ b/AckisRecipeList.toc
@@ -62,13 +62,17 @@ embeds.xml
 # Localization files
 locale.xml

+# Constants should be loaded first - many files use them in their main chunk.
 Constants.lua
-ARL.lua
+
+core.lua
 Config.lua
 Waypoint.lua
-Frame.lua
 Scanner.lua
 Player.lua

+# User Interface files
+Frame.lua
+
 # Database files
 database.xml
diff --git a/core.lua b/core.lua
new file mode 100644
index 0000000..8522c39
--- /dev/null
+++ b/core.lua
@@ -0,0 +1,2188 @@
+--[[
+************************************************************************
+ARL.lua
+************************************************************************
+File date: @file-date-iso@
+File hash: @file-abbreviated-hash@
+Project hash: @project-abbreviated-hash@
+Project version: @project-version@
+************************************************************************
+Authors: Ackis, Zhinjio, Jim-Bim, Torhal, Pompachomp
+************************************************************************
+Please see http://www.wowace.com/addons/arl/ for more information.
+************************************************************************
+This source code is released under All Rights Reserved.
+************************************************************************
+**AckisRecipeList** provides an interface for scanning professions for missing recipes.
+There are a set of functions which allow you make use of the ARL database outside of ARL.
+ARL supports all professions currently in World of Warcraft 3.3.2
+@class file
+@name ARL.lua
+@release 1.0
+************************************************************************
+]]
+
+-------------------------------------------------------------------------------
+-- Localized Lua globals.
+-------------------------------------------------------------------------------
+local _G = getfenv(0)
+
+local tostring = _G.tostring
+local tonumber = _G.tonumber
+
+local pairs, ipairs = _G.pairs, _G.ipairs
+local select = _G.select
+
+local table = _G.table
+local twipe = table.wipe
+local tconcat = table.concat
+local tinsert = table.insert
+
+local bit = _G.bit
+
+local string = _G.string
+local strformat = string.format
+local strfind = string.find
+local strmatch = string.match
+local strlower = string.lower
+
+-------------------------------------------------------------------------------
+-- Localized Blizzard API.
+-------------------------------------------------------------------------------
+local GetNumTradeSkills = _G.GetNumTradeSkills
+local GetSpellInfo = _G.GetSpellInfo
+
+-------------------------------------------------------------------------------
+-- AddOn namespace.
+-------------------------------------------------------------------------------
+local LibStub	= _G.LibStub
+local MODNAME	= "Ackis Recipe List"
+local addon	= LibStub("AceAddon-3.0"):NewAddon(MODNAME, "AceConsole-3.0", "AceEvent-3.0")
+_G.AckisRecipeList = addon
+
+--@alpha@
+_G.ARL = addon
+--@end-alpha@
+
+local L		= LibStub("AceLocale-3.0"):GetLocale(MODNAME)
+local BFAC 	= LibStub("LibBabble-Faction-3.0"):GetLookupTable()
+local BZ	= LibStub("LibBabble-Zone-3.0"):GetLookupTable()
+
+local debugger	= _G.tekDebug and _G.tekDebug:GetFrame(MODNAME)
+
+------------------------------------------------------------------------------
+-- Constants.
+------------------------------------------------------------------------------
+local PROFESSION_INITS = {}	-- Professions initialization functions.
+
+------------------------------------------------------------------------------
+-- Database tables
+------------------------------------------------------------------------------
+local AllSpecialtiesTable = {}
+local SpecialtyTable
+
+-- Set up the private intra-file namespace.
+local private	= select(2, ...)
+
+private.build_num = select(2, 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	= {}
+
+-- Filter flags and acquire types - defined in Constants.lua
+local F 	= private.filter_flags
+local A		= private.acquire_types
+
+------------------------------------------------------------------------------
+-- Data which is stored regarding a players statistics (luadoc copied from Collectinator, needs updating)
+------------------------------------------------------------------------------
+-- @class table
+-- @name Player
+-- @field known_filtered Total number of items known filtered during the scan.
+-- @field Faction Player's faction
+-- @field Class Player's class
+-- @field ["Reputation"] Listing of players reputation levels
+local Player = {}
+private.Player = Player
+
+-- 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(strformat(L["MISSING_LIBRARY"], 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
+
+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)
+		twipe(output)
+		tinsert(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
+				tinsert(output, key.. " ("..val_type..")")
+				count = count + 1
+			end
+		end
+		tinsert(output, string.format("\n%d found\n", count))
+		self:DisplayTextDump(nil, nil, tconcat(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,
+					expansion0 = true,
+					expansion1 = true,
+					expansion2 = 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,
+				},
+				-------------------------------------------------------------------------------
+				-- 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 = GetAddOnMetadata("AckisRecipeList", "Version")
+	self.version = (version == "@project-version@") and "Devel" or version
+
+	self:SetupOptions()
+
+	-- Register slash commands
+	self:RegisterChatCommand("arl", "ChatCommand")
+	self:RegisterChatCommand("ackisrecipelist", "ChatCommand")
+
+	-------------------------------------------------------------------------------
+	-- Create the scan button
+	-------------------------------------------------------------------------------
+	local scan_button = CreateFrame("Button", nil, UIParent, "UIPanelButtonTemplate")
+	scan_button:SetHeight(20)
+
+	scan_button:RegisterForClicks("LeftButtonUp")
+	scan_button:SetScript("OnClick",
+			      function(self, button, down)
+				      local cur_profession = GetTradeSkillLine()
+				      local prev_profession = addon.Frame.prof_name or private.ordered_professions[addon.Frame.profession]
+
+				      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 not shift_key and alt_key and not ctrl_key then
+					      addon:ClearWaypoints()
+				      elseif not shift_key and not alt_key and not ctrl_key then
+					      if addon.Frame:IsVisible() and prev_profession == cur_profession then
+						      addon.Frame:Hide()
+					      else
+						      addon:Scan(false)
+						      addon:AddWaypoint()
+					      end
+				      end
+			      end)
+
+	scan_button:SetScript("OnEnter",
+			      function(this)
+				      GameTooltip_SetDefaultAnchor(GameTooltip, this)
+				      GameTooltip:SetText(L["SCAN_RECIPES_DESC"])
+				      GameTooltip:Show()
+			      end)
+	scan_button:SetScript("OnLeave", function() GameTooltip:Hide() end)
+	scan_button:SetText(L["Scan"])
+
+	self.scan_button = scan_button
+
+	-------------------------------------------------------------------------------
+	-- Populate the profession initialization functions.
+	-------------------------------------------------------------------------------
+	PROFESSION_INITS[GetSpellInfo(51304)] = addon.InitAlchemy
+	PROFESSION_INITS[GetSpellInfo(51300)] = addon.InitBlacksmithing
+	PROFESSION_INITS[GetSpellInfo(51296)] = addon.InitCooking
+	PROFESSION_INITS[GetSpellInfo(51313)] = addon.InitEnchanting
+	PROFESSION_INITS[GetSpellInfo(51306)] = addon.InitEngineering
+	PROFESSION_INITS[GetSpellInfo(45542)] = addon.InitFirstAid
+	PROFESSION_INITS[GetSpellInfo(51302)] = addon.InitLeatherworking
+	PROFESSION_INITS[GetSpellInfo(32606)] = addon.InitSmelting
+	PROFESSION_INITS[GetSpellInfo(51309)] = addon.InitTailoring
+	PROFESSION_INITS[GetSpellInfo(51311)] = addon.InitJewelcrafting
+	PROFESSION_INITS[GetSpellInfo(45363)] = addon.InitInscription
+	PROFESSION_INITS[private.runeforging_name] = addon.InitRuneforging
+
+	-------------------------------------------------------------------------------
+	-- Hook GameTooltip so we can show information on mobs that drop/sell/train
+	-------------------------------------------------------------------------------
+        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 = UnitGUID(unit)
+
+			       if not guid then
+				       return
+			       end
+			       local GUID = tonumber(string.sub(guid, 8, 12), 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 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 = 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 = GetItemQualityColor(recipe.quality)
+
+						       self:AddLine(string.format("%s: %s%s|r (%d)", 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 Skillet and Skillet:IsActive() then
+		scan_button:SetParent(SkilletFrame)
+		Skillet:AddButtonToTradeskillWindow(scan_button)
+		scan_button:SetWidth(80)
+	elseif MRTUIUtils_RegisterWindowOnShow then
+		MRTUIUtils_RegisterWindowOnShow(function()
+							scan_button:SetParent(MRTSkillFrame)
+							scan_button:ClearAllPoints()
+							scan_button:SetPoint("RIGHT", MRTSkillFrameCloseButton, "LEFT", 4, 0)
+							scan_button:SetWidth(scan_button:GetTextWidth() + 10)
+							scan_button:Show()
+						end)
+  	elseif ATSWFrame then
+		scan_button:SetParent(ATSWFrame)
+		scan_button:ClearAllPoints()
+
+		if TradeJunkieMain and TJ_OpenButtonATSW then
+			scan_button:SetPoint("RIGHT", TJ_OpenButtonATSW, "LEFT", 0, 0)
+		else
+			scan_button:SetPoint("RIGHT", ATSWOptionsButton, "LEFT", 0, 0)
+		end
+		scan_button:SetHeight(ATSWOptionsButton:GetHeight())
+		scan_button:SetWidth(ATSWOptionsButton:GetWidth())
+	elseif CauldronFrame then
+		scan_button:SetParent(CauldronFrame)
+		scan_button:ClearAllPoints()
+		scan_button:SetPoint("TOP", CauldronFrame, "TOPRIGHT", -58, -52)
+		scan_button:SetWidth(90)
+	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 Manufac then
+		Manufac.options.args.ARLScan = {
+			type = 'execute',
+			name = L["Scan"],
+			desc = L["SCAN_RECIPES_DESC"],
+			func = function() addon:Scan(false) end,
+			order = 550,
+		}
+	end
+
+--[[
+	-- If we're using Skillet, use Skillet's API to work with getting tradeskills
+	if (Skillet) and (Skillet.GetNumTradeSkills) and
+	(Skillet.GetTradeSkillLine) and (Skillet.GetTradeSkillInfo) and
+	(Skillet.GetTradeSkillRecipeLink) and (Skillet.ExpandTradeSkillSubClass) then
+		self:Print("Enabling Skillet advanced features.")
+		GetNumTradeSkills = function(...) return Skillet:GetNumTradeSkills(...) end
+		GetTradeSkillLine = function(...) return Skillet:GetTradeSkillLine(...) end
+		GetTradeSkillInfo = function(...) return Skillet:GetTradeSkillInfo(...) end
+		GetTradeSkillRecipeLink = function(...) return Skillet:GetTradeSkillRecipeLink(...) end
+		ExpandTradeSkillSubClass = function(...) return Skillet:ExpandTradeSkillSubClass(...) end
+	end
+]]--
+	-------------------------------------------------------------------------------
+	-- Initialize the player's data.
+	-------------------------------------------------------------------------------
+	do
+		Player.faction = UnitFactionGroup("player")
+		Player["Class"] = select(2, UnitClass("player"))
+
+		-------------------------------------------------------------------------------
+		-- Get the player's professions.
+		-------------------------------------------------------------------------------
+		Player.professions = {
+			[GetSpellInfo(51304)]	= false, -- Alchemy
+			[GetSpellInfo(51300)]	= false, -- Blacksmithing
+			[GetSpellInfo(51296)]	= false, -- Cooking
+			[GetSpellInfo(51313)]	= false, -- Enchanting
+			[GetSpellInfo(51306)]	= false, -- Engineering
+			[GetSpellInfo(45542)]	= false, -- First Aid
+			[GetSpellInfo(51302)]	= false, -- Leatherworking
+			[GetSpellInfo(2656)]	= false, -- Smelting
+			[GetSpellInfo(51309)]	= false, -- Tailoring
+			[GetSpellInfo(51311)]	= false, -- Jewelcrafting
+			[GetSpellInfo(45363)]	= false, -- Inscription
+			[private.runeforging_name]	= false, -- Runeforging
+		}
+		Player:SetProfessions()
+
+		-------------------------------------------------------------------------------
+		-- Set the scanned state for all professions to false.
+		-------------------------------------------------------------------------------
+		Player.has_scanned = {}
+
+		for profession in pairs(Player.professions) do
+			Player.has_scanned[profession] = false
+		end
+
+	end	-- do
+
+	-------------------------------------------------------------------------------
+	-- Initialize the SpecialtyTable and AllSpecialtiesTable.
+	-------------------------------------------------------------------------------
+	do
+		local AlchemySpec = {
+			[GetSpellInfo(28674)] = 28674,
+			[GetSpellInfo(28678)] = 28678,
+			[GetSpellInfo(28676)] = 28676,
+		}
+
+		local BlacksmithSpec = {
+			[GetSpellInfo(9788)] = 9788,	-- Armorsmith
+			[GetSpellInfo(17041)] = 17041,	-- Master Axesmith
+			[GetSpellInfo(17040)] = 17040,	-- Master Hammersmith
+			[GetSpellInfo(17039)] = 17039,	-- Master Swordsmith
+			[GetSpellInfo(9787)] = 9787,	-- Weaponsmith
+		}
+
+		local EngineeringSpec = {
+			[GetSpellInfo(20219)] = 20219, -- Gnomish
+			[GetSpellInfo(20222)] = 20222, -- Goblin
+		}
+
+		local LeatherworkSpec = {
+			[GetSpellInfo(10657)] = 10657, -- Dragonscale
+			[GetSpellInfo(10659)] = 10659, -- Elemental
+			[GetSpellInfo(10661)] = 10661, -- Tribal
+		}
+
+		local TailorSpec = {
+			[GetSpellInfo(26797)] = 26797, -- Spellfire
+			[GetSpellInfo(26801)] = 26801, -- Shadoweave
+			[GetSpellInfo(26798)] = 26798, -- Primal Mooncloth
+		}
+
+		SpecialtyTable = {
+			[GetSpellInfo(51304)] = AlchemySpec,
+			[GetSpellInfo(51300)] = BlacksmithSpec,
+			[GetSpellInfo(51306)] = EngineeringSpec,
+			[GetSpellInfo(51302)] = LeatherworkSpec,
+			[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()
+	addon.Frame:Hide()
+
+	-- Remove the option from Manufac
+	if Manufac then
+		Manufac.options.args.ARLScan = nil
+	end
+end
+
+-------------------------------------------------------------------------------
+-- Event handling functions
+-------------------------------------------------------------------------------
+
+---Event used for datamining when a trainer is shown.
+function addon:TRAINER_SHOW()
+	self:ScanSkillLevelData(true)
+	self:ScanTrainerData(true)
+end
+
+---Event used for datamining when a vendor is shown.
+function addon:MERCHANT_SHOW()
+	addon:ScanVendor()
+end
+
+do
+	local GetTradeSkillListLink = _G.GetTradeSkillListLink
+	local UnitName = _G.UnitName
+	local GetRealmName = _G.GetRealmName
+	local IsTradeSkillLinked = _G.IsTradeSkillLinked
+
+	function addon:TRADE_SKILL_SHOW()
+		-- If this is our own skill, save it, if not don't save it
+		if not IsTradeSkillLinked() then
+			local tradelink = GetTradeSkillListLink()
+
+			if tradelink then
+				local pname = UnitName("player")
+				local prealm = GetRealmName()
+				local tradename = 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 {}
+
+				addon.db.global.tradeskill[prealm][pname][tradename] = tradelink
+			end
+		end
+		local scan_button = self.scan_button
+		local scan_parent = scan_button:GetParent()
+
+		if not scan_parent or scan_parent == UIParent then
+			scan_button:SetParent(TradeSkillFrame)
+			scan_parent = scan_button:GetParent()
+		end
+
+		if scan_parent == TradeSkillFrame then
+			scan_button:ClearAllPoints()
+
+			local loc = addon.db.profile.scanbuttonlocation
+
+			if loc == "TR" then
+				scan_button:SetPoint("RIGHT", TradeSkillFrameCloseButton, "LEFT",4,0)
+			elseif loc == "TL" then
+				scan_button:SetPoint("LEFT", TradeSkillFramePortrait, "RIGHT",2,12)
+			elseif loc == "BR" then
+				scan_button:SetPoint("TOP", TradeSkillCancelButton, "BOTTOM",0,-5)
+			elseif loc == "BL" then
+				scan_button:SetPoint("TOP", TradeSkillCreateAllButton, "BOTTOM",0,-5)
+			end
+			scan_button:SetWidth(scan_button:GetTextWidth() + 10)
+		end
+		scan_button:Show()
+	end
+end
+
+function addon:TRADE_SKILL_CLOSE()
+	if addon.db.profile.closeguionskillclose then
+		self.Frame:Hide()
+	end
+
+	if not Skillet then
+		addon.scan_button:Hide()
+	end
+end
+
+do
+	local last_update = 0
+	local updater = CreateFrame("Frame", nil, UIParent)
+
+	updater:Hide()
+	updater:SetScript("OnUpdate",
+			  function(self, elapsed)
+				  last_update = last_update + elapsed
+
+				  if last_update >= 0.5 then
+					  local profession = 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:IsVisible() then
+			return
+		end
+
+		if not updater:IsVisible() then
+			last_update = 0
+			updater:Show()
+		end
+	end
+end
+
+-------------------------------------------------------------------------------
+-- Tradeskill functions
+-- Recipe DB Structures are defined in Documentation.lua
+-------------------------------------------------------------------------------
+
+do
+	local SF = private.recipe_state_flags
+
+	-------------------------------------------------------------------------------
+	-- Recipe member functions for bit flags.
+	-------------------------------------------------------------------------------
+	local function Recipe_HasState(self, state_name)
+		return self.state and (bit.band(self.state, SF[state_name]) == SF[state_name]) or false
+	end
+
+	local function Recipe_AddState(self, state_name)
+		if not self.state then
+			self.state = 0
+		end
+
+		if bit.band(self.state, SF[state_name]) == SF[state_name] then
+			return
+		end
+		self.state = bit.bxor(self.state, SF[state_name])
+	end
+
+	local function Recipe_RemoveState(self, state_name)
+		if not self.state then
+			return
+		end
+
+		if bit.band(self.state, SF[state_name]) ~= SF[state_name] then
+			return
+		end
+		self.state = bit.bxor(self.state, SF[state_name])
+
+		if self.state == 0 then
+			self.state = nil
+		end
+	end
+
+	local BITFIELD_MAP = {
+		["common1"]	= private.common_flags_word1,
+		["class1"]	= private.class_flags_word1,
+		["reputation1"]	= private.rep_flags_word1,
+		["reputation2"]	= private.rep_flags_word2,
+		["item1"]	= private.item_flags_word1,
+	}
+
+	local function Recipe_IsFlagged(self, field_name, flag_name)
+		local bitfield = self.flags[field_name]
+		local bitset = BITFIELD_MAP[field_name]
+		local value = bitset[flag_name]
+
+		return bitfield and (bit.band(bitfield, value) == value) or false
+	end
+
+	--- Adds a tradeskill recipe into the specified recipe database
+	-- @name AckisRecipeList:AddRecipe
+	-- @usage AckisRecipeList:AddRecipe(28927, 305, 23109, Q.UNCOMMON, V.TBC, 305, 305, 325, 345)
+	-- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe being added to the database
+	-- @param skill_level The skill level at which the recipe can be initially learned
+	-- @param item_id The [[http://www.wowwiki.com/ItemLink|Item ID]] that is created by the recipe, or nil
+	-- @param quality The quality/rarity of the recipe
+	-- @param profession The profession ID that uses the recipe.  See [[API/database-documentation]] for a listing of profession IDs
+	-- @param specialty The specialty that uses the recipe (ie: goblin engineering) or nil or blank
+	-- @param genesis Game version that the recipe was first introduced in, for example, Original, BC, or WoTLK
+	-- @param optimal_level Level at which recipe is considered orange
+	-- @param medium_level Level at which recipe is considered yellow
+	-- @param easy_level Level at which recipe is considered green
+	-- @param trivial_level Level at which recipe is considered grey
+	-- @return None, array is passed as a reference
+	function addon:AddRecipe(spell_id, skill_level, item_id, quality, profession, specialty, genesis, optimal_level, medium_level, easy_level, trivial_level)
+		local recipe_list = private.recipe_list
+
+		if recipe_list[spell_id] then
+			--@alpha@
+			self:Print("Duplicate recipe: "..recipe_list[spell_id].profession.." "..tostring(spell_id).." "..recipe_list[spell_id].name)
+			--@end-alpha@
+			return
+		end
+
+		local recipe = {
+			["spell_id"]		= spell_id,
+			["skill_level"]		= skill_level,
+			["item_id"]		= item_id,
+			["quality"]		= quality,
+			["profession"]		= GetSpellInfo(profession),
+			["name"]		= GetSpellInfo(spell_id),
+			["flags"]		= {},
+			["acquire_data"]	= {},
+			["specialty"]		= specialty,			-- Assumption: there will only be 1 speciality for a trade skill
+			["genesis"]		= private.game_version_names[genesis],
+			["optimal_level"]	= optimal_level or skill_level,
+			["medium_level"]	= medium_level or skill_level + 10,
+			["easy_level"]		= easy_level or skill_level + 15,
+			["trivial_level"]	= trivial_level or skill_level + 20,
+
+			-- Function members
+			["HasState"]		= Recipe_HasState,
+			["AddState"]		= Recipe_AddState,
+			["RemoveState"]		= Recipe_RemoveState,
+			["IsFlagged"]		= Recipe_IsFlagged,
+		}
+
+		if not recipe.name then
+			self:Print(strformat(L["SpellIDCache"], spell_id))
+		end
+		recipe_list[spell_id] = recipe
+	end
+end	-- do
+
+-- Public API function for retrieving specific information about a recipe.
+-- @name AckisRecipeList:GetRecipeData
+-- @usage AckisRecipeList:GetRecipeData(28972, "profession")
+-- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe being queried.
+-- @param data Which member of the recipe table is being queried.
+-- @return Variable, depending upon which member of the recipe table is queried.
+function addon:GetRecipeData(spell_id, data)
+	local recipe = private.recipe_list[spell_id]
+	return recipe and recipe[data] or nil
+end
+
+--- Adds filtering flags to a specific tradeskill.
+-- @name AckisRecipeList:AddRecipeFlags
+-- @usage AckisRecipeList:AddRecipeFlags(28927, F.ALLIANCE, F.VENDOR, F.IBOE, F.RBOP, F.HEALER, F.CASTER, F.ALDOR)
+-- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe which the filter flags are being added to
+-- @param ... A listing of filtering flags.  See [[API/database-documentation]] for a listing of filter flags
+-- @return None, array is passed as a reference.
+function addon:AddRecipeFlags(spell_id, ...)
+	local num_flags = select('#',...)
+	local recipe = private.recipe_list[spell_id]
+
+	for index = 1, num_flags, 1 do
+		local flag = select(index, ...)
+		local flag_name = private.filter_strings[flag]
+
+		local bitfield
+		local member_name
+
+		for table_index, bits in ipairs(private.bit_flags) do
+			if bits[flag_name] then
+				bitfield = bits
+				member_name = private.flag_members[table_index]
+			end
+		end
+
+		if not bitfield or not member_name then
+			return
+		end
+
+		if not recipe.flags[member_name] then
+			recipe.flags[member_name] = 0
+		end
+		recipe.flags[member_name] = bit.bxor(recipe.flags[member_name], bitfield[flag_name])
+	end
+end
+
+--- Adds acquire methods to a specific tradeskill.
+-- @name AckisRecipeList:AddRecipeAcquire
+-- @usage AckisRecipeList:AddRecipeAcquire(28927, A.REPUTATION, FAC.ALDOR, REP.HONORED, 19321)
+-- @param spell_id The [[http://www.wowwiki.com/SpellLink|Spell ID]] of the recipe which acquire methods are being added to
+-- @param ... A listing of acquire methods.  See [[API/database-documentation]] for a listing of acquire methods and how they work
+-- @return None, array is passed as a reference.
+do
+	local location_list = private.location_list
+	local acquire_list = private.acquire_list
+
+	function addon:AddRecipeAcquire(spell_id, ...)
+		local numvars = select('#', ...)	-- Find out how many flags we're adding
+		local i = 1				-- Index for which variables we're parsing through
+		local recipe_list = private.recipe_list
+		local acquire_data = recipe_list[spell_id].acquire_data
+
+		while i <= numvars do
+			local location, affiliation
+
+			local acquire_type, acquire_id = select(i, ...)
+			i = i + 2
+
+			if not acquire_type then
+				self:Debug("Spell ID: %d has no acquire type.", spell_id)
+			else
+				acquire_data[acquire_type] = acquire_data[acquire_type] or {}
+
+				local acquire = acquire_data[acquire_type]
+
+				if not acquire_id then
+					self:Debug("Spell ID %d: %s ID is nil.", spell_id, private.acquire_strings[acquire_type])
+				else
+					if acquire_type == A.TRAINER then
+						local trainer_list = private.trainer_list
+						local trainer = trainer_list[acquire_id]
+
+						if not trainer then
+							self:Debug("Spell ID "..spell_id..": TrainerID "..acquire_id.." does not exist in the database.")
+						else
+							acquire[acquire_id] = true
+
+							affiliation = trainer.faction
+							location = trainer.location
+
+							trainer.item_list = trainer.item_list or {}
+							trainer.item_list[spell_id] = true
+						end
+					elseif acquire_type == A.VENDOR then
+						local vendor_list = private.vendor_list
+						local vendor = vendor_list[acquire_id]
+
+						if not vendor then
+							self:Debug("Spell ID "..spell_id..": VendorID "..acquire_id.." does not exist in the database.")
+						else
+							acquire[acquire_id] = true
+
+							affiliation = vendor.faction
+							location = vendor.location
+
+							vendor.item_list = vendor.item_list or {}
+							vendor.item_list[spell_id] = true
+						end
+					elseif acquire_type == A.MOB_DROP then
+						local mob_list = private.mob_list
+						local mob = mob_list[acquire_id]
+
+						if not mob then
+							self:Debug("Spell ID "..spell_id..": Mob ID "..acquire_id.." does not exist in the database.")
+						else
+							acquire[acquire_id] = true
+
+							affiliation = mob.faction
+							location = mob.location
+
+							mob_list[acquire_id].item_list = mob_list[acquire_id].item_list or {}
+							mob_list[acquire_id].item_list[spell_id] = true
+						end
+					elseif acquire_type == A.QUEST then
+						local quest_list = private.quest_list
+						local quest = quest_list[acquire_id]
+
+						if not quest then
+							self:Debug("Spell ID "..spell_id..": Quest ID "..acquire_id.." does not exist in the database.")
+						else
+							acquire[acquire_id] = true
+
+							affiliation = quest.faction
+							location = quest.location
+						end
+					elseif acquire_type == A.REPUTATION then
+						local vendor_list = private.vendor_list
+						local rep_level, vendor_id = select(i, ...)
+						i = i + 2
+
+						if not private.reputation_list[acquire_id] then
+							self:Debug("Spell ID "..spell_id..": ReputationID "..acquire_id.." does not exist in the database.")
+						else
+							if not vendor_id then
+								self:Debug("Spell ID "..spell_id..": Reputation Vendor ID is nil.")
+							elseif not vendor_list[vendor_id] then
+								self:Debug("Spell ID "..spell_id..": Reputation Vendor ID "..vendor_id.." does not exist in the database.")
+							else
+								acquire[acquire_id] = acquire[acquire_id] or {}
+
+								local faction = acquire[acquire_id]
+								faction[rep_level] = faction[rep_level] or {}
+								faction[rep_level][vendor_id] = true
+
+								local rep_vendor = vendor_list[vendor_id]
+
+								affiliation = rep_vendor.faction
+								location = rep_vendor.location
+
+								rep_vendor.item_list = rep_vendor.item_list or {}
+								rep_vendor.item_list[spell_id] = true
+							end
+						end
+					elseif acquire_type == A.WORLD_DROP then
+						acquire[acquire_id] = true
+						location = type(acquire_id) == "string" and BZ[acquire_id] or nil
+
+						if location then
+							affiliation = "world_drop"
+						else
+							addon:Debug("WORLD_DROP with no location: %d %s", spell_id, recipe_list[spell_id].name)
+						end
+					elseif acquire_type == A.SEASONAL then
+						acquire[acquire_id] = true
+					elseif acquire_type == A.CUSTOM then
+						acquire[acquire_id] = true
+						location = private.custom_list[acquire_id].location
+					else
+						-- Unhandled acquire_type
+						acquire[acquire_id] = true
+						location = private.acquire_strings[acquire_type] or _G.UNKNOWN
+					end
+				end	-- acquire_id
+				acquire_list[acquire_type] = acquire_list[acquire_type] or {}
+				acquire_list[acquire_type].recipes = acquire_list[acquire_type].recipes or {}
+
+				acquire_list[acquire_type].name = private.acquire_names[acquire_type]
+				acquire_list[acquire_type].recipes[spell_id] = affiliation or true
+			end	-- acquire_type
+
+			if location then
+				location_list[location] = location_list[location] or {}
+				location_list[location].recipes = location_list[location].recipes or {}
+
+				location_list[location].name = location
+				location_list[location].recipes[spell_id] = affiliation or true
+			end
+		end	-- while
+	end
+
+	local function GenericAddRecipeAcquire(spell_id, acquire_type, type_string, unit_list, ...)
+		local num_vars = select('#', ...)
+		local cur_var = 1
+		local recipe = private.recipe_list[spell_id]
+
+		local acquire_data = recipe.acquire_data
+		acquire_data[acquire_type] = acquire_data[acquire_type] or {}
+
+		local acquire = acquire_data[acquire_type]
+
+		while cur_var <= num_vars do
+			local location, affiliation
+			local id_num = select(cur_var, ...)
+			cur_var = cur_var + 1
+
+			-- A quantity of true means unlimited - normal vendor item.
+			local quantity = true
+
+			if type_string == "Limited Vendor" then
+				quantity = select(cur_var, ...)
+				cur_var = cur_var + 1
+			end
+			acquire[id_num] = true
+
+			if unit_list and not unit_list[id_num] then
+				addon:Debug("Spell ID %d: %s ID %d does not exist in the database.", spell_id, type_string, id_num)
+			else
+				if not unit_list then
+					location = type(id_num) == "string" and BZ[id_num] or nil
+
+					if location then
+						affiliation = "world_drop"
+					else
+						addon:Debug("WORLD_DROP with no location: %d %s", spell_id, private.recipe_list[spell_id].name)
+					end
+				else
+					local unit = unit_list[id_num]
+
+					affiliation = unit.faction
+					location = unit.location
+
+					unit.item_list = unit.item_list or {}
+					unit.item_list[spell_id] = quantity
+				end
+			end
+			acquire_list[acquire_type] = acquire_list[acquire_type] or {}
+			acquire_list[acquire_type].recipes = acquire_list[acquire_type].recipes or {}
+
+			acquire_list[acquire_type].name = private.acquire_names[acquire_type]
+			acquire_list[acquire_type].recipes[spell_id] = affiliation or true
+
+			if location then
+				location_list[location] = location_list[location] or {}
+				location_list[location].recipes = location_list[location].recipes or {}
+
+				location_list[location].name = location
+				location_list[location].recipes[spell_id] = affiliation or true
+			end
+		end
+	end
+
+	function addon:AddRecipeMobDrop(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.MOB_DROP, "Mob", private.mob_list, ...)
+	end
+
+	function addon:AddRecipeTrainer(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.TRAINER, "Trainer", private.trainer_list, ...)
+	end
+
+	function addon:AddRecipeVendor(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.VENDOR, "Vendor", private.vendor_list, ...)
+	end
+
+	function addon:AddRecipeLimitedVendor(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.VENDOR, "Limited Vendor", private.vendor_list, ...)
+	end
+
+	function addon:AddRecipeWorldDrop(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.WORLD_DROP, nil, nil, ...)
+	end
+
+	function addon:AddRecipeQuest(spell_id, ...)
+		GenericAddRecipeAcquire(spell_id, A.QUEST, "Quest", private.quest_list, ...)
+	end
+
+	-- This function can NOT use GenericAddRecipeAcquire() - reputation vendors are more complicated than the other acquire types.
+	function addon:AddRecipeRepVendor(spell_id, faction_id, rep_level, ...)
+		local num_vars = select('#', ...)
+		local cur_var = 1
+
+		local recipe = private.recipe_list[spell_id]
+		local vendor_list = private.vendor_list
+
+		local acquire_data = recipe.acquire_data
+		acquire_data[A.REPUTATION] = acquire_data[A.REPUTATION] or {}
+
+		local acquire = acquire_data[A.REPUTATION]
+		acquire[faction_id] = acquire[faction_id] or {}
+
+		local faction = acquire[faction_id]
+		faction[rep_level] = faction[rep_level] or {}
+
+		while cur_var <= num_vars do
+			local location, affiliation
+			local vendor_id = select(cur_var, ...)
+			cur_var = cur_var + 1
+
+			if not private.reputation_list[faction_id] then
+				--@alpha@
+				self:Printf("Spell ID %d: Faction ID %d does not exist in the database.", spell_id, faction_id)
+				--@end-alpha@
+			else
+				if not vendor_id then
+					--@alpha@
+					self:Print("Spell ID "..spell_id..": Reputation Vendor ID is nil.")
+					--@end-alpha@
+				elseif not vendor_list[vendor_id] then
+					--@alpha@
+					self:Print("Spell ID "..spell_id..": Reputation Vendor ID "..vendor_id.." does not exist in the database.")
+					--@end-alpha@
+				else
+					faction[rep_level][vendor_id] = true
+
+					local rep_vendor = vendor_list[vendor_id]
+
+					affiliation = rep_vendor.faction
+					location = rep_vendor.location
+
+					rep_vendor.item_list = rep_vendor.item_list or {}
+					rep_vendor.item_list[spell_id] = true
+				end
+			end
+			acquire_list[A.REPUTATION] = acquire_list[A.REPUTATION] or {}
+			acquire_list[A.REPUTATION].recipes = acquire_list[A.REPUTATION].recipes or {}
+
+			acquire_list[A.REPUTATION].name = private.acquire_names[A.REPUTATION]
+			acquire_list[A.REPUTATION].recipes[spell_id] = affiliation or true
+
+			if location then
+				location_list[location] = location_list[location] or {}
+				location_list[location].recipes = location_list[location].recipes or {}
+
+				location_list[location].name = location
+				location_list[location].recipes[spell_id] = affiliation or true
+			end
+		end
+	end
+end	-- do block
+
+--- Adds an item to a specific database listing (ie: vendor, mob, etc)
+-- @name AckisRecipeList:addLookupList
+-- @usage AckisRecipeList:addLookupList(DB,NPC ID, NPC Name, NPC Location, X Coord, Y Coord, Faction)
+-- @param DB Database which the entry will be stored
+-- @param ID Unique identified for the entry
+-- @param name Name of the entry
+-- @param location Location of the entry in the world
+-- @param coord_x X coordinate of where the entry is found
+-- @param coord_y Y coordinate of where the entry is found
+-- @param faction Faction identifier for the entry
+-- @return None, array is passed as a reference
+--For individual database structures, see Documentation.lua
+do
+	local FACTION_NAMES = {
+		[1]	= BFAC["Neutral"],
+		[2]	= BFAC["Alliance"],
+		[3]	= BFAC["Horde"]
+	}
+	function addon:addLookupList(DB, ID, name, location, coord_x, coord_y, faction)
+		if DB[ID] then
+			self:Debug("Duplicate lookup: %d - %s.", ID, name)
+			return
+		end
+
+		DB[ID] = {
+			["name"]	= name,
+			["location"]	= location,
+			["faction"]	= faction and FACTION_NAMES[faction + 1] or FACTION_NAMES[1]
+		}
+
+		if coord_x and coord_y then
+			DB[ID]["coord_x"] = coord_x
+			DB[ID]["coord_y"] = coord_y
+		end
+
+		--@alpha@
+		if not location and DB ~= private.custom_list then
+			self:Debug("Lookup ID: %d (%s) has an unknown location.", ID, DB[ID].name or _G.UNKNOWN)
+		end
+
+		if faction and DB == private.mob_list then
+			self:Debug("Mob %d (%s) has been assigned to faction %s.", ID, name, DB[ID].faction)
+		end
+		--@end-alpha@
+	end
+end	-- do
+
+-------------------------------------------------------------------------------
+-- Filter flag functions
+-------------------------------------------------------------------------------
+do
+	local COMMON1 = private.common_flags_word1
+	local CLASS1 = private.class_flags_word1
+	local REP1 = private.rep_flags_word1
+	local REP2 = private.rep_flags_word2
+	local ITEM1 = private.item_flags_word1
+
+	-- HardFilterFlags and SoftFilterFlags are used to determine if a recipe should be shown based on the value of the key compared to the value of its saved_var.
+	-- Its keys and values are populated the first time CanDisplayRecipe() is called.
+	local HardFilterFlags, SoftFilterFlags, RepFilterFlags, RepFilterFlags2
+
+	local ClassFilterFlags = {
+		["deathknight"]	= CLASS1.DK,
+		["druid"]	= CLASS1.DRUID,
+		["hunter"]	= CLASS1.HUNTER,
+		["mage"]	= CLASS1.MAGE,
+		["paladin"]	= CLASS1.PALADIN,
+		["priest"]	= CLASS1.PRIEST,
+		["shaman"]	= CLASS1.SHAMAN,
+		["rogue"]	= CLASS1.ROGUE,
+		["warlock"]	= CLASS1.WARLOCK,
+		["warrior"]	= CLASS1.WARRIOR,
+	}
+
+	---Scans a specific recipe to determine if it is to be displayed or not.
+	-- For flag info see comments at start of file in comments
+	local function CanDisplayRecipe(recipe)
+		if addon.db.profile.exclusionlist[recipe.spell_id] and not addon.db.profile.ignoreexclusionlist then
+			return false
+		end
+		local filter_db = addon.db.profile.filters
+		local general_filters = filter_db.general
+
+		-- See Documentation file for logic explanation
+		-------------------------------------------------------------------------------
+		-- Stage 1
+		-- Loop through exclusive flags (hard filters)
+		-- If one of these does not pass we do not display the recipe
+		-- So to be more efficient we'll just leave this function if there's a false
+		-------------------------------------------------------------------------------
+
+		-- Display both horde and alliance factions?
+		if not general_filters.faction and not Player:HasRecipeFaction(recipe) then
+			return false
+		end
+
+		-- Display all skill levels?
+		if not general_filters.skill and recipe.skill_level > Player["ProfessionLevel"] then
+			return false
+		end
+
+		-- Display all specialities?
+		if not general_filters.specialty then
+			local specialty = recipe.specialty
+
+			if specialty and specialty ~= Player["Specialty"] then
+				return false
+			end
+		end
+
+		-- Display retired recipes?
+		if not general_filters.retired and bit.band(recipe.flags.common1, COMMON1.RETIRED) == COMMON1.RETIRED then
+			return false
+		end
+		local obtain_filters = filter_db.obtain
+		local game_version = private.game_versions[recipe.genesis]
+		local V = private.game_versions
+
+		-- Filter out game recipes
+		if not obtain_filters.expansion0 and game_version == V.ORIG then
+			return false
+		end
+
+		if not obtain_filters.expansion1 and game_version == V.TBC then
+			return false
+		end
+
+		if not obtain_filters.expansion2 and game_version == V.WOTLK then
+			return false
+		end
+		local quality_filters = filter_db.quality
+		local recipe_quality = recipe.quality
+		local Q = private.item_qualities
+
+		-- Filter out certain recipe quality types.
+		if not quality_filters.common and recipe_quality == Q.COMMON then
+			return false
+		end
+
+		if not quality_filters.uncommon and recipe_quality == Q.UNCOMMON then
+			return false
+		end
+
+		if not quality_filters.rare and recipe_quality == Q.RARE then
+			return false
+		end
+
+		if not quality_filters.epic and recipe_quality == Q.EPIC then
+			return false
+		end
+
+		-------------------------------------------------------------------------------
+		-- Check the hard filter flags
+		-------------------------------------------------------------------------------
+		if not HardFilterFlags then
+			local binding_filters	= filter_db.binding
+			local player_filters	= filter_db.player
+			local armor_filters	= filter_db.item.armor
+			local weapon_filters	= filter_db.item.weapon
+
+			HardFilterFlags = {
+				------------------------------------------------------------------------------------------------
+				-- Binding flags.
+				------------------------------------------------------------------------------------------------
+				["itemboe"]	= { flag = COMMON1.IBOE,	index = 1,	sv_root = binding_filters },
+				["itembop"]	= { flag = COMMON1.IBOP,	index = 1,	sv_root = binding_filters },
+				["itemboa"]	= { flag = COMMON1.IBOA,	index = 1,	sv_root = binding_filters },
+				["recipeboe"]	= { flag = COMMON1.RBOE,	index = 1,	sv_root = binding_filters },
+				["recipebop"]	= { flag = COMMON1.RBOP,	index = 1,	sv_root = binding_filters },
+				["recipeboa"]	= { flag = COMMON1.RBOA,	index = 1,	sv_root = binding_filters },
+				------------------------------------------------------------------------------------------------
+				-- Player Type flags.
+				------------------------------------------------------------------------------------------------
+				["melee"]	= { flag = COMMON1.DPS,		index = 1,	sv_root = player_filters },
+				["tank"]	= { flag = COMMON1.TANK,	index = 1,	sv_root = player_filters },
+				["healer"]	= { flag = COMMON1.HEALER,	index = 1,	sv_root = player_filters },
+				["caster"]	= { flag = COMMON1.CASTER,	index = 1,	sv_root = player_filters },
+				------------------------------------------------------------------------------------------------
+				-- Armor flags.
+				------------------------------------------------------------------------------------------------
+				["cloth"]	= { flag = ITEM1.CLOTH,		index = 5,	sv_root = armor_filters },
+				["leather"]	= { flag = ITEM1.LEATHER,	index = 5,	sv_root = armor_filters },
+				["mail"]	= { flag = ITEM1.MAIL,		index = 5,	sv_root = armor_filters },
+				["plate"]	= { flag = ITEM1.PLATE,		index = 5,	sv_root = armor_filters },
+				["trinket"]	= { flag = ITEM1.TRINKET,	index = 5,	sv_root = armor_filters },
+				["cloak"]	= { flag = ITEM1.CLOAK,		index = 5,	sv_root = armor_filters },
+				["ring"]	= { flag = ITEM1.RING,		index = 5,	sv_root = armor_filters },
+				["necklace"]	= { flag = ITEM1.NECK,		index = 5,	sv_root = armor_filters },
+				["shield"]	= { flag = ITEM1.SHIELD,	index = 5,	sv_root = armor_filters },
+				------------------------------------------------------------------------------------------------
+				-- Weapon flags.
+				------------------------------------------------------------------------------------------------
+				["onehand"]	= { flag = ITEM1.ONE_HAND,	index = 5,	sv_root = weapon_filters },
+				["twohand"]	= { flag = ITEM1.TWO_HAND,	index = 5,	sv_root = weapon_filters },
+				["axe"]		= { flag = ITEM1.AXE,		index = 5,	sv_root = weapon_filters },
+				["sword"]	= { flag = ITEM1.SWORD,		index = 5,	sv_root = weapon_filters },
+				["mace"]	= { flag = ITEM1.MACE,		index = 5,	sv_root = weapon_filters },
+				["polearm"]	= { flag = ITEM1.POLEARM,	index = 5,	sv_root = weapon_filters },
+				["dagger"]	= { flag = ITEM1.DAGGER,	index = 5,	sv_root = weapon_filters },
+				["fist"]	= { flag = ITEM1.FIST,		index = 5,	sv_root = weapon_filters },
+				["gun"]		= { flag = ITEM1.GUN,		index = 5,	sv_root = weapon_filters },
+				["staff"]	= { flag = ITEM1.STAFF,		index = 5,	sv_root = weapon_filters },
+				["wand"]	= { flag = ITEM1.WAND,		index = 5,	sv_root = weapon_filters },
+				["thrown"]	= { flag = ITEM1.THROWN,	index = 5,	sv_root = weapon_filters },
+				["bow"]		= { flag = ITEM1.BOW,		index = 5,	sv_root = weapon_filters },
+				["crossbow"]	= { flag = ITEM1.XBOW,		index = 5,	sv_root = weapon_filters },
+				["ammo"]	= { flag = ITEM1.AMMO,		index = 5,	sv_root = weapon_filters },
+			}
+		end
+
+		for filter, data in pairs(HardFilterFlags) do
+			local bitfield = recipe.flags[private.flag_members[data.index]]
+
+			if bitfield and bit.band(bitfield, data.flag) == data.flag and not data.sv_root[filter] then
+				return false
+			end
+		end
+
+		-------------------------------------------------------------------------------
+		-- Check the reputation filter flags
+		-------------------------------------------------------------------------------
+		if not RepFilterFlags then
+			RepFilterFlags = {
+				[REP1.ARGENTDAWN]		= "argentdawn",
+				[REP1.CENARION_CIRCLE]		= "cenarioncircle",
+				[REP1.THORIUM_BROTHERHOOD]	= "thoriumbrotherhood",
+				[REP1.TIMBERMAW_HOLD]		= "timbermaw",
+				[REP1.ZANDALAR]			= "zandalar",
+				[REP1.ALDOR]			= "aldor",
+				[REP1.ASHTONGUE]		= "ashtonguedeathsworn",
+				[REP1.CENARION_EXPEDITION]	= "cenarionexpedition",
+				[REP1.HELLFIRE]			= "hellfire",
+				[REP1.CONSORTIUM]		= "consortium",
+				[REP1.KOT]			= "keepersoftime",
+				[REP1.LOWERCITY]		= "lowercity",
+				[REP1.NAGRAND]			= "nagrand",
+				[REP1.SCALE_SANDS]		= "scaleofthesands",
+				[REP1.SCRYER]			= "scryer",
+				[REP1.SHATAR]			= "shatar",
+				[REP1.SHATTEREDSUN]		= "shatteredsun",
+				[REP1.SPOREGGAR]		= "sporeggar",
+				[REP1.VIOLETEYE]		= "violeteye",
+				[REP1.ARGENTCRUSADE]		= "argentcrusade",
+				[REP1.FRENZYHEART]		= "frenzyheart",
+				[REP1.EBONBLADE]		= "ebonblade",
+				[REP1.KIRINTOR]			= "kirintor",
+				[REP1.HODIR]			= "sonsofhodir",
+				[REP1.KALUAK]			= "kaluak",
+				[REP1.ORACLES]			= "oracles",
+				[REP1.WYRMREST]			= "wyrmrest",
+				[REP1.WRATHCOMMON1]		= "wrathcommon1",
+				[REP1.WRATHCOMMON2]		= "wrathcommon2",
+				[REP1.WRATHCOMMON3]		= "wrathcommon3",
+				[REP1.WRATHCOMMON4]		= "wrathcommon4",
+				[REP1.WRATHCOMMON5]		= "wrathcommon5",
+			}
+		end
+
+		if not RepFilterFlags2 then
+			RepFilterFlags2 = {
+				[REP2.ASHEN_VERDICT]	= "ashenverdict",
+			}
+		end
+		-- Now we check to see if _all_ of the pertinent reputation or class flags are toggled off. If even one is toggled on, we still show the recipe.
+		local toggled_off, toggled_on = 0, 0
+
+		for flag, name in pairs(RepFilterFlags) do
+			local bitfield = recipe.flags.reputation1
+
+			if bitfield and bit.band(bitfield, flag) == flag then
+				if filter_db.rep[name] then
+					toggled_on = toggled_on + 1
+				else
+					toggled_off = toggled_off + 1
+				end
+			end
+		end
+
+		if toggled_off > 0 and toggled_on == 0 then
+			return false
+		end
+
+		toggled_off, toggled_on = 0, 0
+
+		for flag, name in pairs(RepFilterFlags2) do
+			local bitfield = recipe.flags.reputation2
+
+			if bitfield and bit.band(bitfield, flag) == flag then
+				if filter_db.rep[name] then
+					toggled_on = toggled_on + 1
+				else
+					toggled_off = toggled_off + 1
+				end
+			end
+		end
+
+		if toggled_off > 0 and toggled_on == 0 then
+			return false
+		end
+
+		-------------------------------------------------------------------------------
+		-- Check the class filter flags
+		-------------------------------------------------------------------------------
+		local class_filters = filter_db.classes
+
+		toggled_off, toggled_on = 0, 0
+
+		for class, flag in pairs(ClassFilterFlags) do
+			local bitfield = recipe.flags.class1
+
+			if bitfield and bit.band(bitfield, flag) == flag then
+				if class_filters[class] then
+					toggled_on = toggled_on + 1
+				else
+					toggled_off = toggled_off + 1
+				end
+			end
+		end
+
+		if toggled_off > 0 and toggled_on == 0 then
+			return false
+		end
+
+		------------------------------------------------------------------------------------------------
+		-- Stage 2
+		-- loop through nonexclusive (soft filters) flags until one is true
+		-- If one of these is true (ie: we want to see trainers and there is a trainer flag) we display the recipe
+		------------------------------------------------------------------------------------------------
+		if not SoftFilterFlags then
+			SoftFilterFlags = {
+				["trainer"]	= { flag = COMMON1.TRAINER,	index = 1,	sv_root = obtain_filters },
+				["vendor"]	= { flag = COMMON1.VENDOR,	index = 1,	sv_root = obtain_filters },
+				["instance"]	= { flag = COMMON1.INSTANCE,	index = 1,	sv_root = obtain_filters },
+				["raid"]	= { flag = COMMON1.RAID,	index = 1,	sv_root = obtain_filters },
+				["seasonal"]	= { flag = COMMON1.SEASONAL,	index = 1,	sv_root = obtain_filters },
+				["quest"]	= { flag = COMMON1.QUEST,	index = 1,	sv_root = obtain_filters },
+				["pvp"]		= { flag = COMMON1.PVP,		index = 1,	sv_root = obtain_filters },
+				["worlddrop"]	= { flag = COMMON1.WORLD_DROP,	index = 1,	sv_root = obtain_filters },
+				["mobdrop"]	= { flag = COMMON1.MOB_DROP,	index = 1,	sv_root = obtain_filters },
+				["discovery"]	= { flag = COMMON1.DISC,	index = 1,	sv_root = obtain_filters },
+			}
+		end
+
+		for filter, data in pairs(SoftFilterFlags) do
+			local bitfield = recipe.flags[private.flag_members[data.index]]
+
+			if bitfield and bit.band(bitfield, data.flag) == data.flag and data.sv_root[filter] then
+				return true
+			end
+		end
+
+		-- If we get here it means that no flags matched our values
+		return false
+	end
+
+	---Scans the recipe listing and updates the filters according to user preferences
+	function addon:UpdateFilters(is_linked)
+		local general_filters = addon.db.profile.filters.general
+		local recipes_total = 0
+		local recipes_known = 0
+		local recipes_total_filtered = 0
+		local recipes_known_filtered = 0
+		local can_display = false
+		local current_profession = self.Frame.prof_name or private.ordered_professions[self.Frame.profession]
+		local recipe_list = private.recipe_list
+		local SF = private.recipe_state_flags
+
+		for recipe_id, recipe in pairs(recipe_list) do
+			recipe:RemoveState("VISIBLE")
+
+			if recipe.profession == current_profession then
+				local is_known
+
+				if is_linked then
+					is_known = recipe:HasState("LINKED")
+				else
+					is_known = recipe:HasState("KNOWN")
+				end
+
+				can_display = CanDisplayRecipe(recipe)
+				recipes_total = recipes_total + 1
+				recipes_known = recipes_known + (is_known and 1 or 0)
+
+				if can_display then
+					recipes_total_filtered = recipes_total_filtered + 1
+					recipes_known_filtered = recipes_known_filtered + (is_known and 1 or 0)
+
+					if not general_filters.known and is_known then
+						can_display = false
+					end
+
+					if not general_filters.unknown and not is_known then
+						can_display = false
+					end
+				end
+			else
+				can_display = false
+			end
+
+			if can_display then
+				recipe:AddState("VISIBLE")
+			end
+		end
+		Player.recipes_total = recipes_total
+		Player.recipes_known = recipes_known
+		Player.recipes_total_filtered = recipes_total_filtered
+		Player.recipes_known_filtered = recipes_known_filtered
+		end
+
+end	-- do
+
+-------------------------------------------------------------------------------
+-- 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_INITS[profession]
+
+	if func then
+		return func(addon)
+	else
+		addon:Print(L["UnknownTradeSkill"]:format(profession))
+		return 0
+	end
+end
+
+-- Determines what to do when the slash command is called.
+function addon:ChatCommand(input)
+
+	-- Open About panel if there's no parameters or if we do /arl about
+	if not input or (input and input:trim() == "") or input == strlower(L["Sorting"]) or input == strlower(L["Sort"])  or input == strlower(_G.DISPLAY) then
+		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
+	elseif (input == strlower(L["About"])) then
+		if (self.optionsFrame["About"]) then
+			InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["About"])
+		else
+			InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
+		end
+	elseif (input == strlower(L["Profile"])) then
+		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Profiles"])
+	elseif (input == strlower(_G.FILTER)) then
+		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Filters"])
+	elseif (input == strlower(L["Documentation"])) then
+		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame["Documentation"])
+	elseif (input == strlower(L["Scan"])) then
+		self:Scan(false)
+	elseif (input == strlower("scandata")) then
+		self:ScanSkillLevelData()
+	elseif (input == strlower("scanprof")) then
+		self:ScanProfession("all")
+	elseif (input == strlower("tradelinks")) then
+		self:GenerateLinks()
+	else
+		-- What happens when we get here?
+		LibStub("AceConfigCmd-3.0"):HandleCommand("arl", "Ackis Recipe List", input)
+	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 = {}
+
+	--- 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 = GetTradeSkillLine()
+
+		-- Bail if we haven't opened a tradeskill frame.
+		if current_prof == "UNKNOWN" then
+			self:Print(L["OpenTradeSkillWindow"])
+			return
+		end
+
+		-- Set the current profession level, and update the cached data.
+		Player["ProfessionLevel"] = 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 = IsTradeSkillLinked()
+
+		if not is_linked and Player.professions[current_prof] then
+			Player.professions[current_prof] = prof_level
+			Player.has_scanned[current_prof] = true
+		end
+
+		-- Get the current profession Specialty
+		local specialty = SpecialtyTable[current_prof]
+
+		for index = 1, 25, 1 do
+			local spellName = GetSpellName(index, BOOKTYPE_SPELL)
+
+			if not spellName or index == 25 then
+				Player["Specialty"] = nil
+				break
+			elseif specialty and specialty[spellName] then
+				Player["Specialty"] = specialty[spellName]
+				break
+			end
+		end
+
+		if self.InitializeLookups then
+			self:InitializeLookups()
+		end
+		-- Add the recipes to the database
+		-- TODO: Figure out what this variable was supposed to be for - it isn't used anywhere. -Torhal
+		Player.totalRecipes = addon:InitializeProfession(current_prof)
+
+		-------------------------------------------------------------------------------
+		-- Scan all recipes and mark the ones we know
+		-------------------------------------------------------------------------------
+		twipe(header_list)
+
+		-- Save the state of the "Have Materials" checkbox.
+		local have_materials = TradeSkillFrameAvailableFilterCheckButton:GetChecked()
+
+		if MRTUIUtils_PushFilterSelection then
+			MRTUIUtils_PushFilterSelection()
+		else
+			if not Skillet and TradeSkillFrameAvailableFilterCheckButton:GetChecked() then
+				TradeSkillFrameAvailableFilterCheckButton:SetChecked(false)
+				TradeSkillOnlyShowMakeable(false)
+			end
+
+			-- Clear the inventory slot filter
+			UIDropDownMenu_Initialize(TradeSkillInvSlotDropDown, TradeSkillInvSlotDropDown_Initialize)
+			UIDropDownMenu_SetSelectedID(TradeSkillInvSlotDropDown, 1)
+			SetTradeSkillInvSlotFilter(0, 1, 1)
+
+			-- Clear the sub-classes filters
+			UIDropDownMenu_Initialize(TradeSkillSubClassDropDown, TradeSkillSubClassDropDown_Initialize)
+			UIDropDownMenu_SetSelectedID(TradeSkillSubClassDropDown, 1)
+			SetTradeSkillSubClassFilter(0, 1, 1)
+
+			-- Expand all headers so we can see all the recipes there are
+			for i = GetNumTradeSkills(), 1, -1 do
+				local name, tradeType, _, isExpanded = GetTradeSkillInfo(i)
+
+				if tradeType == "header" and not isExpanded then
+					header_list[name] = true
+					ExpandTradeSkillSubClass(i)
+				end
+			end
+		end
+		local recipe_list = private.recipe_list
+		local recipes_found = 0
+		local SF = private.recipe_state_flags
+
+		for i = 1, GetNumTradeSkills() do
+			local tradeName, tradeType = GetTradeSkillInfo(i)
+
+			if tradeType ~= "header" then
+				-- Get the trade skill link for the specified recipe
+				local SpellLink = GetTradeSkillRecipeLink(i)
+				local SpellString = strmatch(SpellLink, "^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)")
+				local recipe = recipe_list[tonumber(SpellString)]
+
+				if recipe then
+					if not is_linked then
+						recipe:AddState("KNOWN")
+						recipe:RemoveState("LINKED")
+					else
+						recipe:AddState("LINKED")
+					end
+					recipes_found = recipes_found + 1
+				else
+					self:Debug(tradeName .. " " .. SpellString .. L["MissingFromDB"])
+				end
+			end
+		end
+
+		-- Close all the headers we've opened
+		-- If Mr Trader is installed use that API
+		if MRTUIUtils_PopFilterSelection then
+			MRTUIUtils_PopFilterSelection()
+		else
+			-- Collapse all headers that were collapsed before
+			for i = GetNumTradeSkills(), 1, -1 do
+				local name, tradeType, _, isExpanded = GetTradeSkillInfo(i)
+
+				if header_list[name] then
+					CollapseTradeSkillSubClass(i)
+				end
+			end
+			-- Restore the state of the "Have Materials" checkbox.
+			TradeSkillFrameAvailableFilterCheckButton:SetChecked(have_materials)
+			TradeSkillOnlyShowMakeable(have_materials)
+		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["Reputation"] = Player["Reputation"] or {}
+
+		table.wipe(header_list)
+
+		-- Number of factions before expansion
+		local num_factions = GetNumFactions()
+
+		-- Expand all the headers, storing those which were collapsed.
+		for i = num_factions, 1, -1 do
+			local name, _, _, _, _, _, _, _, _, isCollapsed = GetFactionInfo(i)
+
+			if isCollapsed then
+				ExpandFactionHeader(i)
+				header_list[name] = true
+			end
+		end
+
+		-- Number of factions with everything expanded
+		num_factions = GetNumFactions()
+
+		-- Get the rep levels
+		for i = 1, num_factions, 1 do
+			local name, _, replevel = GetFactionInfo(i)
+
+			-- If the rep is greater than neutral
+			if replevel > 4 then
+				-- We use levels of 0, 1, 2, 3, 4 internally for reputation levels, make it correspond here
+				Player["Reputation"][name] = replevel - 4
+			end
+		end
+
+		-- Collapse the headers again
+		for i = num_factions, 1, -1 do
+			local name = GetFactionInfo(i)
+
+			if header_list[name] then
+				CollapseFactionHeader(i)
+			end
+		end
+
+		-------------------------------------------------------------------------------
+		-- Everything is ready - display the GUI or dump the list to text.
+		-------------------------------------------------------------------------------
+		if textdump then
+			self:DisplayTextDump(recipe_list, current_prof)
+		else
+			self.Frame:Display(current_prof, is_linked)
+		end
+	end
+end
+
+-------------------------------------------------------------------------------
+-- Text dumping functions
+-------------------------------------------------------------------------------
+do
+	-------------------------------------------------------------------------------
+	-- Provides a string of comma separated values for all recipe information
+	-------------------------------------------------------------------------------
+	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 = (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"],
+				}
+			end
+			return FILTER_NAMES
+		end
+	end	-- do
+
+	---Dumps the recipe database in a format that is readable to humans.
+	function addon:GetTextDump(profession)
+		local output = addon.db.profile.textdumpformat
+		twipe(text_table)
+
+		if not output or output == "Comma" then
+			tinsert(text_table, strformat("Ackis Recipe List Text Dump for %s's %s, in the form of Comma Separated Values.\n  ", UnitName("player"), profession))
+			tinsert(text_table, "Spell ID,Recipe Name,Skill Level,ARL Filter Flags,Acquire Methods,Known\n")
+		elseif output == "BBCode" then
+			tinsert(text_table, strformat("Ackis Recipe List Text Dump for %s's %s, in the form of BBCode.\n", UnitName("player"), profession))
+		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 = 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
+					tinsert(text_table, recipe_id)
+					tinsert(text_table, ",")
+					tinsert(text_table, recipe.name)
+					tinsert(text_table, ",")
+					tinsert(text_table, recipe.skill_level)
+					tinsert(text_table, ",\"")
+				-- BBCode
+				elseif output == "BBCode" then
+					-- Make the entry red
+					if not is_known then
+						tinsert(text_table, "[color=red]")
+					end
+					tinsert(text_table, "\n[b]" .. recipe_id .. "[/b] - " .. recipe.name .. " (" .. recipe.skill_level .. ")\n")
+
+					-- Close Color tag
+					if not is_known then
+						tinsert(text_table, "[/color]\nRecipe Flags:\n[list]")
+					elseif is_known then
+						tinsert(text_table, "\nRecipe Flags:\n[list]")
+					end
+				--Name
+				elseif output == "Name" then
+					tinsert(text_table, recipe.name.."\n")
+				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
+									tinsert(text_table, ",")
+								end
+								tinsert(text_table, filter_names[private.filter_flags[flag_name]])
+								prev = true
+								-- BBCode
+							elseif output == "BBCode" then
+								tinsert(text_table, "[*]" .. filter_names[private.filter_flags[flag_name]])
+							end
+						end
+					end
+				end
+
+				if not output or output == "Comma" then
+					tinsert(text_table, "\",\"")
+				elseif output == "BBCode" then
+					tinsert(text_table, "[/list]\nAcquire Methods:\n[list]")
+				end
+
+				-- Find out which unique acquire methods we have
+				local acquire_data = recipe["acquire_data"]
+				twipe(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
+							tinsert(text_table, ",")
+						end
+						tinsert(text_table, i)
+						prev = true
+					elseif output == "BBCode" then
+						tinsert(text_table, "[*] " .. i)
+					end
+				end
+
+				if not output or output == "Comma" then
+					if is_known then
+						tinsert(text_table, "\",true\n")
+					else
+						tinsert(text_table, "\",false\n")
+					end
+				elseif output == "BBCode" then
+					tinsert(text_table, "\n[/list]")
+				end
+			end
+		end	-- for
+		return tconcat(text_table, "")
+	end
+end