Updated for API 100011 and provisioning system changes.

katkat42 [03-04-15 - 02:29]
Updated for API 100011 and provisioning system changes.
Filename
Common.lua
Inventory.lua
Provisioning.lua
SousChef.lua
SousChef.txt
Strings.lua
Utility.lua
libs/LibAddonMenu-2.0/LICENSE
libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
libs/LibAddonMenu-2.0/controls/button.lua
libs/LibAddonMenu-2.0/controls/checkbox.lua
libs/LibAddonMenu-2.0/controls/colorpicker.lua
libs/LibAddonMenu-2.0/controls/custom.lua
libs/LibAddonMenu-2.0/controls/description.lua
libs/LibAddonMenu-2.0/controls/dropdown.lua
libs/LibAddonMenu-2.0/controls/editbox.lua
libs/LibAddonMenu-2.0/controls/header.lua
libs/LibAddonMenu-2.0/controls/panel.lua
libs/LibAddonMenu-2.0/controls/slider.lua
libs/LibAddonMenu-2.0/controls/submenu.lua
libs/LibAddonMenu-2.0/controls/texture.lua
diff --git a/Common.lua b/Common.lua
index 01f28c5..67885a5 100644
--- a/Common.lua
+++ b/Common.lua
@@ -30,9 +30,17 @@ local SOUPSTEW  = [[/esoui/art/treeicons/provisioner_indexicon_stew_down.dds]]
 local BEER  = [[/esoui/art/treeicons/provisioner_indexicon_beer_down.dds]]
 local SPIRITS  = [[/esoui/art/treeicons/provisioner_indexicon_spirits_down.dds]]
 local WINE  = [[/esoui/art/treeicons/provisioner_indexicon_wine_down.dds]]
+local GENERAL_DRINK = [[/esoui/art/inventory/inventory_quest_tabicon_active.dds]]
+local FRUIT = [[//esoui/art/progression/progression_indexicon_race_down.dds]]
+local VEGGIES = [[/esoui/art/compass/ava_farm_neutral.dds]]
+local TONICS = [[/esoui/art/crafting/alchemy_tabicon_solvent_down.dds]]

-m.COOKING = { COOKING_RANK_1, COOKING_RANK_2, COOKING_RANK_3, COOKING_RANK_4, COOKING_RANK_5, COOKING_RANK_6, COOKING_FLAVOUR, COOKING_SPICE, GRILLED, BREADPIE, SOUPSTEW, BEER, SPIRITS, WINE}
-m.COOKINGB = { COOKING_RANK_1B, COOKING_RANK_2B, COOKING_RANK_3B, COOKING_RANK_4B, COOKING_RANK_5B, COOKING_RANK_6B, COOKING_FLAVOURB, COOKING_SPICEB, GRILLED, BREADPIE, SOUPSTEW, BEER, SPIRITS, WINE}
+--			1-food spice, 2-drink flavoring, 3-meat, 4-fruit, 5-veg, 6-booze, 7-teas, 8-tonics, 9-general foods, 10-general drinks
+m.COOKING = {COOKING_SPICE, COOKING_FLAVOUR, GRILLED, FRUIT, VEGGIES, SPIRITS, BEER, TONICS, SOUPSTEW, GENERAL_DRINK}
+--m.COOKINGB = {COOKING_SPICEB, COOKING_FLAVOURB, GRILLED, SOUPSTEW, BREADPIE, BEER, SPIRITS, WINE, COOKING_RANK_1B, COOKING_RANK_2B}
+
+--m.COOKING = { COOKING_RANK_1, COOKING_RANK_2, COOKING_RANK_3, COOKING_RANK_4, COOKING_RANK_5, COOKING_RANK_6, COOKING_FLAVOUR, COOKING_SPICE, GRILLED, BREADPIE, SOUPSTEW, BEER, SPIRITS, WINE}
+--m.COOKINGB = { COOKING_RANK_1B, COOKING_RANK_2B, COOKING_RANK_3B, COOKING_RANK_4B, COOKING_RANK_5B, COOKING_RANK_6B, COOKING_FLAVOURB, COOKING_SPICEB, GRILLED, BREADPIE, SOUPSTEW, BEER, SPIRITS, WINE}

 m.CANLEARN = [[/esoui/art/loot/loot_finesseitem.dds]]

@@ -121,13 +129,15 @@ function SousChef.AddDetails(row)

 	-- item is a recipe
 	if GetItemLinkItemType(itemLink) == ITEMTYPE_RECIPE then
-		ZO_Tooltip_AddDivider(ItemTooltip)
+		ZO_Tooltip_AddDivider(ItemTooltip)
 		ItemTooltip:AddLine(zo_strformat(str.TOOLTIP_CREATES, GetItemLinkRequiredLevel(GetItemLinkRecipeResultItemLink(itemLink)), GetItemLinkName(GetItemLinkRecipeResultItemLink(itemLink))), "ZoFontWinH5", 1, 1, 1, BOTTOM)
-        local knownBy = SousChef.settings.Cookbook[u.CleanString(GetItemLinkName(GetItemLinkRecipeResultItemLink(itemLink)))]
-        if knownBy then
-            ItemTooltip:AddLine(str.TOOLTIP_KNOWN_BY, "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
-            ItemTooltip:AddLine(u.TableKeyConcat(knownBy))
-        end
+		if SousChef.settings.showAltKnowledge then
+			local knownBy = SousChef.settings.Cookbook[u.CleanString(GetItemLinkName(GetItemLinkRecipeResultItemLink(itemLink)))]
+			if knownBy then
+				ItemTooltip:AddLine(str.TOOLTIP_KNOWN_BY, "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
+				ItemTooltip:AddLine(u.TableKeyConcat(knownBy))
+			end
+		end
 		return false
 	end

diff --git a/Inventory.lua b/Inventory.lua
index 3eb3e01..e442149 100644
--- a/Inventory.lua
+++ b/Inventory.lua
@@ -20,10 +20,10 @@ function SousChef.AddRankToSlot(row, funcs)
 	else
 		rankIcon:SetDimensions(30, 30)
 		rankIcon:ClearAnchors()
-		rankIcon:SetAnchor(RIGHT, row, RIGHT, -50)
+		rankIcon:SetAnchor(RIGHT, row, RIGHT, -50)
 	end

-	rankIcon:SetHidden(true)
+	rankIcon:SetHidden(true)

 	--Are we gold or soulgem slot? Stay hidden and go away
 	if not bagId or not slot.name or slot.name == "" then return end
@@ -34,14 +34,14 @@ function SousChef.AddRankToSlot(row, funcs)
 	if (itemType ~= ITEMTYPE_FLAVORING) and (itemType ~= ITEMTYPE_INGREDIENT) and (itemType ~= ITEMTYPE_RECIPE) and (itemType ~= ITEMTYPE_SPICE) then
 		return
 	end
-
+
 	--are we an ingredient?
 	local id = u.GetItemID(itemLink)
 	local texture = SousChef.Pantry[id]
 	if SousChef.settings.showAltIngredientKnowledge then texture = SousChef.settings.Pantry[id] end
 	if texture then
 		rankIcon:SetHidden(false)
-
+
 		if SousChef.settings.boldIcon then
 			rankIcon:SetTexture(m.COOKINGB[texture])
 		else
@@ -56,7 +56,7 @@ function SousChef.AddRankToSlot(row, funcs)
 		end
 		return
 	end
-
+
 	--are we a recipe?
     if SousChef.settings.processRecipes then
 		if u.MatchInIgnoreList(slot.name) then return end
diff --git a/Provisioning.lua b/Provisioning.lua
index 89efbb3..bc12e4d 100644
--- a/Provisioning.lua
+++ b/Provisioning.lua
@@ -3,40 +3,6 @@ local u = SousChef.Utility
 local m = SousChef.Media
 local str = SousChef.Strings[SousChef.lang]

--- SousChef:UpdateProvisioningTable() adds the Quality checkbox to the provisioner window and overrides the filtering function to incorporate it
-function SousChef:UpdateProvisioningTable()
-    local function OnFilterChanged()
-        self.settings.qualityChecked = ZO_CheckButton_IsChecked(self.qualityCheckBox)
-        PROVISIONER:DirtyRecipeList()
-    end
-	-- set up the quality checkbox
-    self.qualityCheckBox = SousChef_ControllerOnlyQuality
-    self.qualityCheckBox:SetParent(ZO_ProvisionerTopLevel)
-    ZO_CheckButton_SetLabelText(self.qualityCheckBox, str.PROVISIONING_QUALITY)
-    ZO_CheckButton_SetToggleFunction(self.qualityCheckBox, OnFilterChanged)
-    ZO_CraftingUtils_ConnectCheckBoxToCraftingProcess(self.qualityCheckBox)
-    ZO_CheckButton_SetCheckState(self.qualityCheckBox, self.settings.qualityChecked)
-
-    -- make room for the checkbox
-	if SousChef.lang == "fr" then
-		-- the french strings are really long and need extra room
-		ZO_ProvisionerTopLevelNavigationDivider:ClearAnchors()
-		ZO_ProvisionerTopLevelNavigationDivider:SetAnchor(TOPLEFT, ZO_ProvisionerTopLevelMenuBarDivider, BOTTOMLEFT, 0, 62)
-		self.qualityCheckBox:ClearAnchors()
-		self.qualityCheckBox:SetAnchor(TOP, ZO_ProvisionerTopLevelHaveIngredientsLabel, BOTTOM, 0, 5)
-	else
-		ZO_ProvisionerTopLevelHaveSkills:ClearAnchors()
-		ZO_ProvisionerTopLevelHaveSkills:SetAnchor( LEFT, ZO_ProvisionerTopLevelHaveIngredientsLabel, RIGHT, 20 )
-	end
-
-	-- incorporate new checkbox into the filter
-    SousChef.filter = ZO_SharedProvisioner.DoesRecipePassFilter
-    ZO_SharedProvisioner.DoesRecipePassFilter = function(control, specialIngredientType, checkNumCreatable, numCreatable, checkSkills, provisionerLevelReq, qualityReq)
-		if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end
-		return SousChef.filter(control, specialIngredientType, checkNumCreatable, numCreatable, checkSkills, provisionerLevelReq, qualityReq)
-	end
-end
-
 -- this is our "Mark Recipe" button definition
 SousChef.ProvisioningButton=
 {{
@@ -176,37 +142,6 @@ function SousChef:HookGetRecipeInfo()
 			return SousChef.ZO_ProvisionerRow_GetTextColor(self)
 		end
 	end
-
-    if SousChef.settings.sortProvisioningTable then
-        SousChef.OldRefreshRecipeList = ZO_Provisioner.RefreshRecipeList
-        ZO_Provisioner.RefreshRecipeList = function()
-			return SousChef.RefreshRecipeList(PROVISIONER)
-		end
-    end
-end
-
-function SousChef:UnhookGetRecipeInfo()
-	if not SousChef.settings.sortProvisioningTable then
-		if SousChef.OldRefreshRecipeList ~= nil then
-			ZO_Provisioner.RefreshRecipeList = SousChef.OldRefreshRecipeList
-		end
-	end
-end
-
-local function SortRecipe(a, b)
-    if a.provisionerLevelReq == b.provisionerLevelReq then
-		if a.useLevelReq == b.useLevelReq then
-			if a.qualityReq == b.qualityReq then
-				if a.name == b.name then
-					return a.recipeIndex < b.recipeIndex
-				end
-				return a.name < b.name
-			end
-			return a.qualityReq < b.qualityReq
-		end
-		return a.useLevelReq < b.useLevelReq
-    end
-    return a.provisionerLevelReq < b.provisionerLevelReq
 end

 local function CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients)
@@ -225,76 +160,6 @@ local function CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numI
     return minCount or 0
 end

--- This is an almost direct clone of the existing function
--- Except for two parts.
--- 1) Storing the parent in the data (for each category of recipe)
--- 2) Putting them all in a table first, then sorting, then adding them to the tree
-function SousChef:RefreshRecipeList()
-    self.dirty = false
-
-    self.recipeTree:Reset()
-
-    local hasAnyRecipesInTab = false
-	local hasRecipesWithFilter = false
-	local checkNumCreatable = ZO_CheckButton_IsChecked(self.haveIngredientsCheckBox)
-	local checkSkills = ZO_CheckButton_IsChecked(self.haveSkillsCheckBox)
-    local RecipeLines = {}
-    for recipeListIndex = 1, GetNumRecipeLists() do
-        local recipeListName, numRecipes, upIcon, downIcon, overIcon, disabledIcon, createSound = GetRecipeListInfo(recipeListIndex)
-        local parent
-
-        for recipeIndex = 1, numRecipes do
-            local known, recipeName, numIngredients, provisionerLevelReq, qualityReq, specialIngredientType = GetRecipeInfo(recipeListIndex, recipeIndex)
-			local useLevelReq = GetItemLinkRequiredLevel(GetRecipeResultItemLink(recipeListIndex, recipeIndex))
-            if known and self.filterType == specialIngredientType then
-                local numCreatable = self:CalculateHowManyCouldBeCreated(recipeListIndex, recipeIndex, numIngredients)
-                if self:DoesRecipePassFilter(specialIngredientType, checkNumCreatable, numCreatable, checkSkills, provisionerLevelReq, qualityReq) then
-                    parent = parent or self.recipeTree:AddNode("ZO_IconHeader", { recipeListIndex = recipeListIndex, name = recipeListName, upIcon = upIcon, downIcon = downIcon, overIcon = overIcon, disabledIcon = disabledIcon }, nil, SOUNDS.PROVISIONING_BLADE_SELECTED)
-                    local data = {
-                        recipeListIndex = recipeListIndex,
-                        recipeIndex = recipeIndex,
-                        name = recipeName,
-                        provisionerLevelReq = provisionerLevelReq,
-                        qualityReq = qualityReq,
-						useLevelReq = useLevelReq,
-                        specialIngredientType = specialIngredientType,
-                        numIngredients = numIngredients,
-                        numCreatable = numCreatable,
-                        createSound = createSound,
-                        parent = parent,
-                    }
-
-                    table.insert(RecipeLines, data)
-                    hasRecipesWithFilter = true
-                end
-				hasAnyRecipesInTab = true
-            end
-        end
-    end
-
-    table.sort(RecipeLines, SortRecipe)
-    for i,data in ipairs(RecipeLines) do
-        self.recipeTree:AddNode("ZO_ProvisionerNavigationEntry", data, data.parent, SOUNDS.PROVISIONING_ENTRY_SELECTED)
-    end
-    self.recipeTree:Commit()
-
-    self.noRecipesLabel:SetHidden(hasRecipesWithFilter)
-	ZO_CheckButton_SetEnableState(self.haveIngredientsCheckBox, hasAnyRecipesInTab)
-	ZO_CheckButton_SetEnableState(self.haveSkillsCheckBox, hasAnyRecipesInTab)
-	ZO_CheckButton_SetEnableState(SousChef.qualityCheckBox, hasAnyRecipesInTab)
-    if not hasRecipesWithFilter then
-		if hasAnyRecipesInTab then
-			self.noRecipesLabel:SetText(GetString(SI_PROVISIONER_NO_MATCHING_RECIPES))
-		else
-			self.noRecipesLabel:SetText(GetString(self.filterType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_SPICES and SI_PROVISIONER_NO_COOKING_RECIPES or SI_PROVISIONER_NO_BREWING_RECIPES))
-			ZO_CheckButton_SetChecked(self.haveIngredientsCheckBox)
-			ZO_CheckButton_SetChecked(self.haveSkillsCheckBox)
-			ZO_CheckButton_SetUnchecked(SousChef.qualityCheckBox)
-		end
-        self:RefreshRecipeDetails()
-    end
-end
-
 local function Lighten(...)
     r, g, b = ...
     return r + 0.1, g + 0.1, b + 0.1
diff --git a/SousChef.lua b/SousChef.lua
index aef7a70..1242806 100644
--- a/SousChef.lua
+++ b/SousChef.lua
@@ -10,7 +10,7 @@ Thanks to Ayantir for the French translations, and sirinsidiator for the German
 SousChef = {}
 SousChef.Utility = {}
 SousChef.Media = {}
-SousChef.version = "2.18"
+SousChef.version = "2.19-beta1"

 local SousChef = SousChef
 local u = SousChef.Utility
@@ -34,30 +34,6 @@ if SousChef.lang ~= "en" and SousChef.lang ~= "de" and SousChef.lang ~= "fr" the

 local rowHandler = {}

-local typeIconLookup = {
-	-- en
-	["Grilled"] = 9,
-	["Bread and Pies"] = 10,
-	["Soup and Stew"] = 11,
-	["Beer"] = 12,
-	["Spirits"] = 13,
-	["Wine"] = 14,
-	-- de
-	["Gegrillt"] = 9,
-	["Brot und Kuchen"] = 10,
-	["Suppen und Eintöpfe"] = 11,
-	["Bier"] = 12,
-	["Getränke"] = 13,
-	["Wein"] = 14,
-	-- fr
-	["Grillades"] = 9,
-	["Pain et Tartes"] = 10,
-	["Soupe et Ragoût"] = 11,
-	["Bi\195\169re"] = 12,
-	["Spiritueux"] = 13,
-	["Vin"] = 14,
-}
-
 -- FUNCTIONS
 -- AddRecipe(Cookbook, link) adds the linked recipe to the player cookbook if it isn't there already.
 local function AddRecipe(Cookbook, link)
@@ -88,14 +64,40 @@ local function ChangeMainChar()
 	if SousChef.CookbookIndex == nil then SousChef.CookbookIndex = {} end
 	for name, data in pairs(SousChef.CookbookIndex) do
 		SousChef.Cookbook[u.CleanString((GetRecipeResultItemInfo(data.listIndex, data.recipeIndex)))] = true
-		local _, _, _, level, _, specialType = GetRecipeInfo(data.listIndex, data.recipeIndex)
+		local _, _, _, level, color, specialType = GetRecipeInfo(data.listIndex, data.recipeIndex)
 		for ingredient = 1, data.numIngredients do
 			local ingredientID = u.GetItemID(GetRecipeIngredientItemLink(data.listIndex, data.recipeIndex, ingredient))
-			if ingredient < 3 or not SousChef.settings.showSpecialIngredients then
-				SousChef.Pantry[ingredientID] = math.max(level, SousChef.Pantry[ingredientID] or 0)
-			else
-				SousChef.Pantry[ingredientID] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8
-			end
+			if SousChef.Pantry[ingredientID] == nil then
+				if GetItemLinkItemType(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex)) == ITEMTYPE_FLAVOR then
+					SousChef.settings.Pantry[link] = 2
+				elseif GetItemLinkItemType(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex)) == ITEMTYPE_SPICE then
+					SousChef.settings.Pantry[link] = 1
+				elseif ingredient <= color then
+					-- if this is a base ingredient, record the skill it governs
+					if ingredient == 1 and (data.listIndex == 1 or data.listIndex == 4 or data.listIndex == 5 or data.listIndex == 7) then
+						-- meats
+						SousChef.Pantry[ingredientID] = 3
+					elseif (ingredient == 1 and (data.listIndex == 2 or data.listIndex == 6) or (ingredient == 2 and (data.listIndex == 4 or data.listIndex == 7))) then
+						-- fruits
+						SousChef.Pantry[ingredientID] = 4
+					elseif (ingredient == 1 and data.listIndex == 3) or (ingredient == 2 and (data.listIndex == 5 or data.listIndex == 6)) or (ingredient == 3 and data.listIndex == 7) then
+						-- veggies
+						SousChef.Pantry[ingredientID] = 5
+					elseif (ingredient == 1 and (data.listIndex == 8 or data.listIndex == 11 or data.listIndex == 12 or data.listIndex == 14)) then
+						-- booze
+						SousChef.Pantry[ingredientID] = 6
+					elseif (ingredient == 1 and (data.listIndex == 9 or data.listIndex == 13)) or (ingredient == 2 and (data.listIndex == 11 or data.listIndex == 14)) then
+						-- tea
+						SousChef.Pantry[ingredientID] = 7
+					else
+						-- probably tonics
+						SousChef.Pantry[ingredientID] = 8
+					end
+				else
+					-- this is a leveller, record whether it makes food or drinks
+					SousChef.Pantry[ingredientID] = specialType + 8
+				end
+			end
 			if not SousChef.ReverseCookbook[ingredientID] then SousChef.ReverseCookbook[ingredientID] = {} end
 			AddRecipe(SousChef.ReverseCookbook[ingredientID], name)
 		end
@@ -112,14 +114,11 @@ function SousChef:ParseRecipes()
 			if GetRecipeInfo(listIndex, recipeIndex) then
 				-- Store the recipes known:
 				local recipeName = u.CleanString((GetRecipeResultItemInfo(listIndex, recipeIndex)))
-				-- in this character's cookbook
-                --SousChef.Cookbook[recipeName] = true
-				-- and in the settings, so other characters can see what recipes this character knows
 				if not SousChef.settings.Cookbook[recipeName] then SousChef.settings.Cookbook[recipeName] = {} end
                 SousChef.settings.Cookbook[recipeName][GetUnitName("player")] = true

 				-- now record information about the recipe's ingregients
-				local _, _, ingredientCount, level, _, specialType = GetRecipeInfo(listIndex, recipeIndex)
+				local _, _, ingredientCount, level, color, specialType = GetRecipeInfo(listIndex, recipeIndex)
 				-- store the recipe's index numbers and number of ingredients
 				local resultLink = GetRecipeResultItemLink(listIndex, recipeIndex)
 				local coloredName = u.GetColoredLinkName(resultLink)
@@ -128,23 +127,39 @@ function SousChef:ParseRecipes()
 				-- now, for every ingredient in the current recipe...
 				for ingredientIndex = 1, ingredientCount do
 					local link = u.GetItemID(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex, LINK_STYLE_DEFAULT))
-					-- Store the fact that the ingredient is used
-                    if ingredientIndex < 3 or not SousChef.settings.showSpecialIngredients then
-						-- if this isn't a special ingredient, or if the user doesn't want special ingredients marked as special, just record the highest-tier recipe this ingredient appears in
-						-- for this character,
-                        --SousChef.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0)
-						-- and across characters
-                        SousChef.settings.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0)
-                    else
-						-- if this is a special ingredient, record:
-						-- 						type icon number if user wants type icons,								7 if ingredient is a flavoring,				8 otherwise (ie, ingredient is a spice)
-                        --SousChef.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8
-                        SousChef.settings.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8
-                    end
-					-- Store the recipe it's used in to the character reverseCookbook
-					--if not SousChef.ReverseCookbook[link] then SousChef.ReverseCookbook[link] = {} end
-					--AddRecipe(SousChef.ReverseCookbook[link], coloredName)
-					-- ...and to the account-wide reverseCookbook
+					-- Store the fact that the ingredient is used, if we don't already know that
+					if SousChef.settings.Pantry[link] == nil then
+						if GetItemLinkItemType(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex)) == ITEMTYPE_FLAVOR then
+							SousChef.settings.Pantry[link] = 2
+						elseif GetItemLinkItemType(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex)) == ITEMTYPE_SPICE then
+							SousChef.settings.Pantry[link] = 1
+						elseif ingredientIndex <= color then
+							-- if this is a base ingredient, record the skill it governs
+							if ingredientIndex == 1 and (listIndex == 1 or listIndex == 4 or listIndex == 5 or listIndex == 7) then
+								-- meats
+								SousChef.settings.Pantry[link] = 3
+							elseif (ingredientIndex == 1 and (listIndex == 2 or listIndex == 6) or (ingredientIndex == 2 and (listIndex == 4 or listIndex == 7))) then
+								-- fruits
+								SousChef.settings.Pantry[link] = 4
+							elseif (ingredientIndex == 1 and listIndex == 3) or (ingredientIndex == 2 and (listIndex == 5 or listIndex == 6)) or (ingredientIndex == 3 and listIndex == 7) then
+								-- veggies
+								SousChef.settings.Pantry[link] = 5
+							elseif (ingredientIndex == 1 and (listIndex == 8 or listIndex == 11 or listIndex == 12 or listIndex == 14)) then
+								-- booze
+								SousChef.settings.Pantry[link] = 6
+							elseif (ingredientIndex == 1 and (listIndex == 9 or listIndex == 13)) or (ingredientIndex == 2 and (listIndex == 11 or listIndex == 14)) then
+								-- tea
+								SousChef.settings.Pantry[link] = 7
+							else
+								-- probably tonics
+								SousChef.settings.Pantry[link] = 8
+							end
+						else
+							-- this is a leveller, record whether it makes food or drinks
+							SousChef.settings.Pantry[link] = specialType + 8
+						end
+					end
+					-- Store the recipe it's used in to the reverseCookbook
 					if not SousChef.settings.ReverseCookbook[link] then SousChef.settings.ReverseCookbook[link] = {} end
 					AddRecipe(SousChef.settings.ReverseCookbook[link], coloredName)
 				end
@@ -187,227 +202,189 @@ local function SousChefCreateSettings()

 	LAM:RegisterAddonPanel("SousChefSettings", panelData)

-	local optionsMenu = {
-		[1] = {
-			type = "header",
-			name = str.MENU_RECIPE_HEADER,
-			width = "full",
-		},
-		[2] = {
-			type = "checkbox",
-			name = str.MENU_PROCESS_RECIPES,
-			tooltip = str.MENU_PROCESS_RECIPES_TOOLTIP,
-			getFunc = function() return SousChef.settings.processRecipes end,
-			setFunc = function(value) SousChef.settings.processRecipes = value end,
-			width = "full",
-		},
-		[3] = {
-			type = "dropdown",
-			name = str.MENU_MAIN_CHAR,
-			tooltip = str.MENU_MAIN_CHAR_TOOLTIP,
-			choices = SousChef.settings.knownChars,
-			getFunc = function() return SousChef.settings.mainChar end,
-			setFunc = function(value)
-				SousChef.settings.mainChar = value
-				ChangeMainChar()
-			end,
-			disabled = function() return not SousChef.settings.processRecipes end,
-		},
-		[4] = {
-			type = "dropdown",
-			name = str.MENU_MARK_IF_KNOWN,
-			tooltip = str.MENU_MARK_IF_KNOWN_TOOLTIP,
-			choices = {str.MENU_KNOWN, str.MENU_UNKNOWN},
-			getFunc = function()
-				if SousChef.settings.checkKnown == "known" then
-					return str.MENU_KNOWN
-				elseif SousChef.settings.checkKnown == "unknown" then
-					return str.MENU_UNKNOWN
-				else
-					-- can't happen
-					d("Yikes! MENU_MARK_IF_KNOWN getter")
-					return str.MENU_UNKNOWN
-				end
-			end,
-			setFunc = function(valueString)
-				if valueString == str.MENU_KNOWN then
-					SousChef.settings.checkKnown = "known"
-				elseif valueString == str.MENU_UNKNOWN then
-					SousChef.settings.checkKnown = "unknown"
-				else
-					-- can't happen
-					d("Oops! MENU_MARK_IF_KNOWN setter")
-					SousChef.settings.checkKnown = "unknown"
-				end
-			end,
-			disabled = function() return not SousChef.settings.processRecipes end,
-		},
-		[5] = {
-			type = "checkbox",
-			name = str.MENU_MARK_IF_ALT_KNOWS,
-			tooltip = str.MENU_MARK_IF_ALT_KNOWS_TOOLTIP,
-			getFunc = function() return SousChef.settings.markAlt end,
-			setFunc = function(value) SousChef.settings.markAlt = value SousChef:RefreshViews() end,
-			disabled = function() return (not SousChef.settings.processRecipes) or (SousChef.settings.checkKnown == "known") end,
-		},
-		[6] = {
-			type = "checkbox",
-			name = str.MENU_TOOLTIP_IF_ALT_KNOWS,
-			tooltip = str.MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP,
-			getFunc = function() return SousChef.settings.showAltKnowledge end,
-			setFunc = function(value) SousChef.settings.showAltKnowledge = value SousChef:RefreshViews() end,
-			disabled = function() return not SousChef.settings.processRecipes end,
-		},
-		[7] = {
-			type = "checkbox",
-			name = str.MENU_MATCHER,
-			tooltip = str.MENU_MATCHER_TOOLTIP,
-			getFunc = function() return SousChef.settings.experimentalMatch end,
-			setFunc = function(value) SousChef.settings.experimentalMatch = value end,
-			disabled = function() return not SousChef.settings.processRecipes end,
-		},
-		[8] = {
-			type = "checkbox",
-			name = str.MENU_SORT_PROVISIONING,
-			tooltip = str.MENU_SORT_PROVISIONING_TOOLTIP,
-			getFunc = function() return SousChef.settings.sortProvisioningTable end,
-			setFunc = function(value)
-				SousChef.settings.sortProvisioningTable = value
-				if value then
-					SousChef:HookGetRecipeInfo()
-				else
-					SousChef:UnhookGetRecipeInfo()
-				end
-			end,
-		},
-
-		[9] = {
-			type = "header",
-			name = str.MENU_TOOLTIP_HEADER,
-			width = "full",
-		},
-		[10] = {
-			type = "checkbox",
-			name = str.MENU_TOOLTIP_CLICK,
-			tooltip = str.MENU_TOOLTIP_CLICK_TOOLTIP,
-			warning = str.MENU_RELOAD,
-			getFunc = function() return SousChef.settings.showOnClick end,
-			setFunc = function(value) SousChef.settings.showOnClick = value end,
-		},
-		[11] = {
-			type = "checkbox",
-			name = str.MENU_RESULT_COUNTS,
-			tooltip = str.MENU_RESULT_COUNTS_TOOLTIP,
-			getFunc = function() return SousChef.settings.showCounts end,
-			setFunc = function(value) SousChef.settings.showCounts = value end,
-		},
-		[12] = {
-			type = "checkbox",
-			name = str.MENU_ALT_USE,
-			tooltip = str.MENU_ALT_USE_TOOLTIP,
-			getFunc = function() return SousChef.settings.showAltIngredientKnowledge end,
-			setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = value SousChef:RefreshViews() end,
-		},
+	local optionsMenu = { }
+	table.insert(optionsMenu, {
+		type = "dropdown",
+		name = str.MENU_MAIN_CHAR,
+		tooltip = str.MENU_MAIN_CHAR_TOOLTIP,
+		choices = SousChef.settings.knownChars,
+		getFunc = function() return SousChef.settings.mainChar end,
+		setFunc = function(value)
+			SousChef.settings.mainChar = value
+			ChangeMainChar()
+			SousChef.RefreshViews()
+		end,
+		disabled = function() return not SousChef.settings.processRecipes end,
+	})
+	table.insert(optionsMenu, {
+		type = "header",
+		name = str.MENU_RECIPE_HEADER,
+		width = "full",
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_PROCESS_RECIPES,
+		tooltip = str.MENU_PROCESS_RECIPES_TOOLTIP,
+		getFunc = function() return SousChef.settings.processRecipes end,
+		setFunc = function(value) SousChef.settings.processRecipes = value SousChef.RefreshViews() end,
+		width = "full",
+	})
+	table.insert(optionsMenu, {
+		type = "dropdown",
+		name = str.MENU_MARK_IF_KNOWN,
+		tooltip = str.MENU_MARK_IF_KNOWN_TOOLTIP,
+		choices = {str.MENU_KNOWN, str.MENU_UNKNOWN},
+		getFunc = function()
+			if SousChef.settings.checkKnown == "known" then
+				return str.MENU_KNOWN
+			elseif SousChef.settings.checkKnown == "unknown" then
+				return str.MENU_UNKNOWN
+			else
+				-- can't happen
+				d("Yikes! MENU_MARK_IF_KNOWN getter")
+				return str.MENU_UNKNOWN
+			end
+		end,
+		setFunc = function(valueString)
+			if valueString == str.MENU_KNOWN then
+				SousChef.settings.checkKnown = "known"
+			elseif valueString == str.MENU_UNKNOWN then
+				SousChef.settings.checkKnown = "unknown"
+			else
+				-- can't happen
+				d("Oops! MENU_MARK_IF_KNOWN setter")
+				SousChef.settings.checkKnown = "unknown"
+			end
+			SousChef.RefreshViews()
+		end,
+		disabled = function() return not SousChef.settings.processRecipes end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_MARK_IF_ALT_KNOWS,
+		tooltip = str.MENU_MARK_IF_ALT_KNOWS_TOOLTIP,
+		getFunc = function() return SousChef.settings.markAlt end,
+		setFunc = function(value) SousChef.settings.markAlt = value SousChef:RefreshViews() SousChef.RefreshViews() end,
+		disabled = function() return (not SousChef.settings.processRecipes) or (SousChef.settings.checkKnown == "known") end,
+	})
+
+	table.insert(optionsMenu, {
+		type = "header",
+		name = str.MENU_RECIPE_TOOLTIP_HEADER,
+		width = "full",
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_TOOLTIP_IF_ALT_KNOWS,
+		tooltip = str.MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP,
+		getFunc = function() return SousChef.settings.showAltKnowledge end,
+		setFunc = function(value) SousChef.settings.showAltKnowledge = value SousChef:RefreshViews() end,
+		disabled = function() return not SousChef.settings.processRecipes end,
+	})
+
+	table.insert(optionsMenu, {
+		type = "header",
+		name = str.MENU_TOOLTIP_HEADER,
+		width = "full",
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_TOOLTIP_CLICK,
+		tooltip = str.MENU_TOOLTIP_CLICK_TOOLTIP,
+		warning = str.MENU_RELOAD,
+		getFunc = function() return SousChef.settings.showOnClick end,
+		setFunc = function(value) SousChef.settings.showOnClick = value end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_RESULT_COUNTS,
+		tooltip = str.MENU_RESULT_COUNTS_TOOLTIP,
+		getFunc = function() return SousChef.settings.showCounts end,
+		setFunc = function(value) SousChef.settings.showCounts = value end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_ALT_USE,
+		tooltip = str.MENU_ALT_USE_TOOLTIP,
+		getFunc = function() return SousChef.settings.showAltIngredientKnowledge end,
+		setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = value SousChef:RefreshViews() end,
+	})

-		[13] = {
-			type = "header",
-			name = str.MENU_INDICATOR_HEADER,
-			width = "full",
-		},
-		[14] = {
-			type = "checkbox",
-			name = str.MENU_ICON_SET,
-			tooltip = str.MENU_ICON_SET_TOOLTIP,
-			getFunc = function() return SousChef.settings.boldIcon end,
-			setFunc = function(value) SousChef.settings.boldIcon = value SousChef:RefreshViews() end,
-		},
-		[15] = {
-			type = "checkbox",
-			name = str.MENU_SPECIAL_ICONS,
-			tooltip = str.MENU_SPECIAL_ICONS_TOOLTIP,
-			getFunc = function() return SousChef.settings.showSpecialIngredients end,
-			setFunc = function(value)
-				SousChef.settings.showSpecialIngredients = value
-				SousChef.ParseRecipes()
-			end,
-		},
-		[16] = {
-			type = "checkbox",
-			name = str.MENU_SPECIAL_TYPES,
-			tooltip = str.MENU_SPECIAL_TYPES_TOOLTIP,
-			getFunc = function() return SousChef.settings.typeIcon end,
-			setFunc = function(value) SousChef.settings.typeIcon = value SousChef.ParseRecipes() SousChef:RefreshViews() end,
-			disabled = function() return not SousChef.settings.showSpecialIngredients end,
-		},
-		[17] = {
-			type = "colorpicker",
-			name = str.MENU_INDICATOR_COLOR,
-			tooltip = str.MENU_INDICATOR_COLOR_TOOLTIP,
-			getFunc = function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end,
-			setFunc = function(r,g,b)
-				SousChef.settings.colour[1] = r
-				SousChef.settings.colour[2] = g
-				SousChef.settings.colour[3] = b
-				SousChef:RefreshViews()
-			end,
-		},
-		[18] = {
-			type = "colorpicker",
-			name = str.MENU_SHOPPING_COLOR,
-			tooltip = str.MENU_SHOPPING_COLOR_TOOLTIP,
-			getFunc = function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end,
-			setFunc = function(r,g,b)
-				SousChef.settings.shoppingColour[1] = r
-				SousChef.settings.shoppingColour[2] = g
-				SousChef.settings.shoppingColour[3] = b
-				SousChef:RefreshViews()
-			end,
-		},
-		[19] = {
-			type = "checkbox",
-			name = str.MENU_SHOW_ALT_SHOPPING,
-			tooltip = str.MENU_SHOW_ALT_SHOPPING_TOOLTIP,
-			getFunc = function() return SousChef.settings.showAltShopping end,
-			setFunc = function(value) SousChef.settings.showAltShopping = value SousChef:RefreshViews() end,
-		},
-		[20] = {
-			type = "checkbox",
-			name = str.MENU_ONLY_MARK_SHOPPING,
-			tooltip = str.MENU_ONLY_MARK_SHOPPING_TOOLTIP,
-			getFunc = function() return SousChef.settings.onlyShowShopping end,
-			setFunc = function(value) SousChef.settings.onlyShowShopping = value SousChef:RefreshViews() end,
-		},
-		[21] = {
-			type = "checkbox",
-			name = str.MENU_AUTO_JUNK,
-			tooltip = str.MENU_AUTO_JUNK_TOOLTIP,
-			getFunc = function() return SousChef.settings.autoJunk end,
-			setFunc = function(value)
-				if value then
-					SousChef.settings.autoJunk = true
-					EVENT_MANAGER:RegisterForEvent("SousChefLootJunker", EVENT_LOOT_CLOSED, function(...) zo_callLater(AutoJunker, 100) end)
-				else
-					SousChef.settings.autoJunk = false
-					EVENT_MANAGER:UnregisterForEvent("SousChefLootJunker", EVENT_LOOT_CLOSED)
-				end
-			end,
-			warning = str.MENU_AUTO_JUNK_WARNING,
-		},
-		[22] = {
-			type = "checkbox",
-			name = str.MENU_SORT_INGREDIENTS,
-			tooltip = str.MENU_SORT_INGREDIENTS_TOOLTIP,
-			getFunc = function() return SousChef.settings.sortKnownIngredients end,
-			setFunc = function(value)
-				SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients
-				if not SousChef.settings.sortKnownIngredients then
-					SousChef.UnregisterSort()
-				else
-					SousChef.SetupSort()
-				end
-			end,
-		},
-	}
+	table.insert(optionsMenu, {
+		type = "header",
+		name = str.MENU_INDICATOR_HEADER,
+		width = "full",
+	})
+	table.insert(optionsMenu, {
+		type = "colorpicker",
+		name = str.MENU_INDICATOR_COLOR,
+		tooltip = str.MENU_INDICATOR_COLOR_TOOLTIP,
+		getFunc = function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end,
+		setFunc = function(r,g,b)
+			SousChef.settings.colour[1] = r
+			SousChef.settings.colour[2] = g
+			SousChef.settings.colour[3] = b
+			SousChef:RefreshViews()
+		end,
+	})
+	table.insert(optionsMenu, {
+		type = "colorpicker",
+		name = str.MENU_SHOPPING_COLOR,
+		tooltip = str.MENU_SHOPPING_COLOR_TOOLTIP,
+		getFunc = function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end,
+		setFunc = function(r,g,b)
+			SousChef.settings.shoppingColour[1] = r
+			SousChef.settings.shoppingColour[2] = g
+			SousChef.settings.shoppingColour[3] = b
+			SousChef:RefreshViews()
+		end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_SHOW_ALT_SHOPPING,
+		tooltip = str.MENU_SHOW_ALT_SHOPPING_TOOLTIP,
+		getFunc = function() return SousChef.settings.showAltShopping end,
+		setFunc = function(value) SousChef.settings.showAltShopping = value SousChef:RefreshViews() end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_ONLY_MARK_SHOPPING,
+		tooltip = str.MENU_ONLY_MARK_SHOPPING_TOOLTIP,
+		getFunc = function() return SousChef.settings.onlyShowShopping end,
+		setFunc = function(value) SousChef.settings.onlyShowShopping = value SousChef:RefreshViews() end,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_AUTO_JUNK,
+		tooltip = str.MENU_AUTO_JUNK_TOOLTIP,
+		getFunc = function() return SousChef.settings.autoJunk end,
+		setFunc = function(value)
+			if value then
+				SousChef.settings.autoJunk = true
+				EVENT_MANAGER:RegisterForEvent("SousChefLootJunker", EVENT_LOOT_CLOSED, function(...) zo_callLater(AutoJunker, 100) end)
+			else
+				SousChef.settings.autoJunk = false
+				EVENT_MANAGER:UnregisterForEvent("SousChefLootJunker", EVENT_LOOT_CLOSED)
+			end
+		end,
+		warning = str.MENU_AUTO_JUNK_WARNING,
+	})
+	table.insert(optionsMenu, {
+		type = "checkbox",
+		name = str.MENU_SORT_INGREDIENTS,
+		tooltip = str.MENU_SORT_INGREDIENTS_TOOLTIP,
+		getFunc = function() return SousChef.settings.sortKnownIngredients end,
+		setFunc = function(value)
+			SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients
+			if not SousChef.settings.sortKnownIngredients then
+				SousChef.UnregisterSort()
+			else
+				SousChef.SetupSort()
+			end
+			SousChef.RefreshViews()
+		end,
+	})
+
 	LAM:RegisterOptionControls("SousChefSettings", optionsMenu)
 end

@@ -430,7 +407,6 @@ local function SousChef_Loaded(eventCode, addOnName)
 		showAltIngredientKnowledge = false,
 		boldIcon = false,
 		typeIcon = true,
-        experimentalMatch = false,
         processRecipes = true,
         showSpecialIngredients = false,
         ignoredRecipes = {},
@@ -439,7 +415,6 @@ local function SousChef_Loaded(eventCode, addOnName)
         shoppingList = {},
         onlyShowShopping = false,
         qualityChecked = false,
-        sortProvisioningTable = true,
         sortKnownIngredients = false,
 		mainChar = GetUnitName("player"),
 		knownChars = { "(current)" },
@@ -450,7 +425,7 @@ local function SousChef_Loaded(eventCode, addOnName)
 	local localized = SousChef.Strings[SousChef.lang]

 	-- Fetch the saved variables
-    SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 10, SousChef.lang, defaults)
+    SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 11, SousChef.lang, defaults)
 	-- if this character isn't in the list of known chars, add it
 	local addMe = true
 	local addCurrent = true
@@ -481,7 +456,6 @@ local function SousChef_Loaded(eventCode, addOnName)
 	-- parse the recipes this character knows, in a second
 	zo_callLater(SousChef.ParseRecipes, 500)

-	SousChef:UpdateProvisioningTable()
 	SousChef:HookGetRecipeInfo()

 	if SousChef.settings.sortKnownIngredients then SousChef.SetupSort() end
diff --git a/SousChef.txt b/SousChef.txt
index 8941f5a..f8a8cef 100644
--- a/SousChef.txt
+++ b/SousChef.txt
@@ -1,7 +1,7 @@
 ## Title: Sous Chef by Wobin, CrazyDutchGuy & KatKat42
 ## Author: Wobin & CrazyDutchGuy & KatKat42
 ## Version: @project-version@
-## APIVersion: 100010
+## APIVersion: 100011
 ## SavedVariables: SousChef_Settings
 ## OptionalDependsOn: LibStub LibSort LibAddonMenu-2.0

@@ -30,5 +30,5 @@ Common.lua
 Inventory.lua
 TradingHouse.lua
 Provisioning.lua
-SousChef.xml
+; SousChef.xml
 Bindings.xml
diff --git a/Strings.lua b/Strings.lua
index c5aed17..d743cb3 100644
--- a/Strings.lua
+++ b/Strings.lua
@@ -11,39 +11,33 @@ SousChef.Strings = {
 		SC_IGNORED = "Ignoring:",

 		-- Menu items
-		MENU_RECIPE_HEADER = "Recipe Options",
-		MENU_PROCESS_RECIPES = "Have Sous Chef display info for recipes",
-		MENU_PROCESS_RECIPES_TOOLTIP = "Non English clients may want to untick this if the experimental matching isn't sufficient",
 		MENU_MAIN_CHAR = "Main Provisioner Character",
-		MENU_MAIN_CHAR_TOOLTIP = "Select the character whose recipe knowledge you want shown by the indicators",
-		MENU_MARK_IF_KNOWN = "Mark recipe if it is ",
+		MENU_MAIN_CHAR_TOOLTIP = "Select the character whose knowledge you want shown by the indicators",
+		MENU_RECIPE_HEADER = "Recipe Indicators",
+		MENU_PROCESS_RECIPES = "Display Recipe Indicators",
+		MENU_PROCESS_RECIPES_TOOLTIP = "Do you want Sous Chef to display indicators for recipes in the inventory view?",
 		MENU_KNOWN = "known",
 		MENU_UNKNOWN = "unknown",
+		MENU_MARK_IF_KNOWN = "Mark recipe if it is ",
 		MENU_MARK_IF_KNOWN_TOOLTIP = "When do you want Sous Chef to display an indicator by a recipe?",
-		MENU_MARK_IF_ALT_KNOWS = "Alternate Character Indicator",
+		MENU_MARK_IF_ALT_KNOWS = "Fade Indicator if Alt Knows",
 		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Fade the indicator for unknown recipes if an alt knows the recipe.",
-		MENU_TOOLTIP_IF_ALT_KNOWS = "List Character Recipe Knowledge in Tooltips",
+
+		MENU_RECIPE_TOOLTIP_HEADER = "Recipe Tooltips",
+		MENU_TOOLTIP_IF_ALT_KNOWS = "List Characters Who Know Recipe",
 		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Show in tooltips which characters know a recipe",
-		MENU_MATCHER = "Use the Experimental Recipe Matcher",
-		MENU_MATCHER_TOOLTIP = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)",
-		MENU_SORT_PROVISIONING = "Sort the Provisioning Table",
-		MENU_SORT_PROVISIONING_TOOLTIP = "Will sort the provisioning table by Level, Quality, then Name",
-		MENU_TOOLTIP_HEADER = "Ingredient Tooltip Options",
+
+		MENU_TOOLTIP_HEADER = "Ingredient Tooltips",
 		MENU_TOOLTIP_CLICK = "Require Mouse Click to Show Sous Chef Data",
 		MENU_TOOLTIP_CLICK_TOOLTIP = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space",
 		MENU_RESULT_COUNTS = "Show Recipe Result Counts",
-		MENU_RESULT_COUNTS_TOOLTIP = "Show how many of each recipe can be made in the Ingredient tooltip",
-		MENU_ALT_USE = "Alternate Character Ingredient Usage",
-		MENU_ALT_USE_TOOLTIP = "Indicate if an alt uses an ingredient",
-		MENU_INDICATOR_HEADER = "Indicator Options",
-		MENU_ICON_SET = "Use bolder icons",
-		MENU_ICON_SET_TOOLTIP = "Swap out rank icons to a more flat display",
-		MENU_SPECIAL_ICONS = "Special Icons for Special Ingredients",
-		MENU_SPECIAL_ICONS_TOOLTIP = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it",
-		MENU_SPECIAL_TYPES = "Show Special Ingredient Types",
-		MENU_SPECIAL_TYPES_TOOLTIP = "Use the icon for the type of food it's a special ingredient for, eg Grilled",
+		MENU_RESULT_COUNTS_TOOLTIP = "Show how many of each recipe can be made in the Ingredient tooltip, next to the recipe's name",
+		MENU_ALT_USE = "Use Alts' Ingredient Knowledge",
+		MENU_ALT_USE_TOOLTIP = "If the main character doesn't know how to use an ingredient, but an alt does, use the alt's knowledge",
+
+		MENU_INDICATOR_HEADER = "Ingredient Indicators",
 		MENU_INDICATOR_COLOR = "Indicator Colour",
-		MENU_INDICATOR_COLOR_TOOLTIP = "Allows you to set the colour of the recipe indicator",
+		MENU_INDICATOR_COLOR_TOOLTIP = "Allows you to set the colour of the ingredient's indicator",
 		MENU_SHOPPING_COLOR = "Shopping List Indicator Colour",
 		MENU_SHOPPING_COLOR_TOOLTIP = "Allows you to set the colour of the indicator for ingredients in your Shopping List",
 		MENU_SHOW_ALT_SHOPPING = "Shop for Alts' Shopping Lists?",
@@ -83,11 +77,11 @@ SousChef.Strings = {
 		SC_IGNORED = "Ignoriert:",

 		-- Menu items
-		MENU_RECIPE_HEADER = "Rezept Einstellungen",
-		MENU_PROCESS_RECIPES = "Rezeptsinfos anzeigen",
-		MENU_PROCESS_RECIPES_TOOLTIP = "Diese Option abw\195\164hlen, wenn der experimentelle Rezeptnamensvergleich nicht ausreicht",
 		MENU_MAIN_CHAR = "Main Provisioner Character",
 		MENU_MAIN_CHAR_TOOLTIP = "Select the character whose recipe knowledge you want shown by the indicators",
+		MENU_RECIPE_HEADER = "Rezept Einstellungen",
+		MENU_PROCESS_RECIPES = "Rezeptsinfos anzeigen",
+		MENU_PROCESS_RECIPES_TOOLTIP = "Soll Sous Chef Rezepts markieren?",
 		MENU_MARK_IF_KNOWN = "Rezept markieren wenn?",
 		MENU_KNOWN = "bekannt",
 		MENU_UNKNOWN = "unbekannt",
@@ -96,10 +90,7 @@ SousChef.Strings = {
 		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Markierung f\195\188r unbekannte Rezepte ausblenden, wenn ein anderer Charakter dieses Rezept bereits kennt.",
 		MENU_TOOLTIP_IF_ALT_KNOWS = "Charakter Rezeptsammlung in Kurzinfos auflisten",
 		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Zeige in den Kurzinfos welche Spielfiguren ein Rezept kennen",
-		MENU_MATCHER = "Experimentellen Rezeptnamensvergleich nutzen",
-		MENU_MATCHER_TOOLTIP = "Derzeit kann Sous Chef in Deutsch nicht eindeutig zuordnen welches Rezept welches Gericht herstellt (z.B. stellt das Rezept Geißelw\195\188rzenconfit das Gericht Geißelw\195\188rzeconfit her - mit einem n weniger bei w\195\188rzen). Es wird daher versucht Teile des Rezeptnamens wegzulassen, um bessere Ergebnisse zu erzielen. (HINWEIS: Bitte melde einen Fehler an Zenimax wenn ein Rezeptname nicht exakt mit dem Gericht \195\188bereinstimmt.)",
-		MENU_SORT_PROVISIONING = "Rezeptliste sortieren",
-		MENU_SORT_PROVISIONING_TOOLTIP = "Sortiert die Rezepte im Versorgungsmen\195\188 nach Level, Qualit\195\164t und Namen",
+
 		MENU_TOOLTIP_HEADER = "Zutatenkurzinfo Einstellungen",
 		MENU_TOOLTIP_CLICK = "Sous Chef Daten nur durch Mausklick anzeigen",
 		MENU_TOOLTIP_CLICK_TOOLTIP = "Zeige Sous Chef Informationen in Zutatenkurzinfos erst nach einem Mausklick, um Platz zu sparen",
@@ -107,6 +98,7 @@ SousChef.Strings = {
 		MENU_RESULT_COUNTS_TOOLTIP = "Zeige in den Zutatenkurzinfos, wieviele Gerichte mit einem Rezept gekocht werden k\195\182nnen",
 		MENU_ALT_USE = "Zutatenverbrauch anderer Spielfiguren",
 		MENU_ALT_USE_TOOLTIP = "Anzeigen wenn ein anderer Charakter eine Zutat verwendet",
+
 		MENU_INDICATOR_HEADER = "Markierungs Einstellungen",
 		MENU_ICON_SET = "Fettere Symbole verwenden",
 		MENU_ICON_SET_TOOLTIP = "Ersetzt die Rangsymbole mit besser sichtbaren Versionen",
@@ -155,11 +147,11 @@ SousChef.Strings = {
 		SC_IGNORED = "Recettes ignorées:",

 		-- Menu items
+		MENU_MAIN_CHAR = "Main Provisioner Character",
+		MENU_MAIN_CHAR_TOOLTIP = "Select the character whose recipe knowledge you want shown by the indicators",
 		MENU_RECIPE_HEADER = "Recettes",
 		MENU_PROCESS_RECIPES = "Afficher des infos complémentaires aux recettes",
 		MENU_PROCESS_RECIPES_TOOLTIP = "Si votre jeu n'est pas en anglais, il faudra peut-être désactiver cette option si la reconnaissance des recettes ne fonctionne pas correctement",
-		MENU_MAIN_CHAR = "Main Provisioner Character",
-		MENU_MAIN_CHAR_TOOLTIP = "Select the character whose recipe knowledge you want shown by the indicators",
 		MENU_MARK_IF_KNOWN = "Indiquer si la recette est ",
 		MENU_KNOWN = "connue",
 		MENU_UNKNOWN = "inconnue",
@@ -168,10 +160,7 @@ SousChef.Strings = {
 		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Masque la coche indiquant qu'une recette est inconnue si un de vos autres personnages la connait déjà",
 		MENU_TOOLTIP_IF_ALT_KNOWS = "Recettes connues dans les info-bulles",
 		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Affiche dans les info-bulles quel personnage connait quelle recette",
-		MENU_MATCHER = "Détection expérimentale des recettes",
-		MENU_MATCHER_TOOLTIP = "Pour l'instant, Sous Chef ne peut savoir exactement si vous connaisse une recette. Cette option permettra à Sous Chef de détecter au mieux celles-ci en supprimant les éléments de grammaire superflus. (NOTE: Merci de signaler un ticket à Zenimax si vous trouvez des recettes dont leur nom ne correspond pas au résultat fabriqué)",
-		MENU_SORT_PROVISIONING = "Trier la liste des recettes",
-		MENU_SORT_PROVISIONING_TOOLTIP = "La liste des recettes sera triée par niveau puis qualité et enfin par nom",
+
 		MENU_TOOLTIP_HEADER = "Options pour les ingrédients",
 		MENU_TOOLTIP_CLICK = "Cliquer pour afficher les infos de Sous Chef",
 		MENU_TOOLTIP_CLICK_TOOLTIP = "N'affichera seulement les informations additionnelles de Sous Chef sur les info-bulles des ingrédients qu'après avoir cliqué dessus pour économiser de l'espace",
@@ -179,6 +168,7 @@ SousChef.Strings = {
 		MENU_RESULT_COUNTS_TOOLTIP = "Affiche combien de fois chaque recette peut être cuisinée dans l'info-bulle des ingrédients",
 		MENU_ALT_USE = "Vérification des autres personnages",
 		MENU_ALT_USE_TOOLTIP = "Indique si un autre personnage sait utiliser l'ingrédient",
+
 		MENU_INDICATOR_HEADER = "Interface",
 		MENU_ICON_SET = "Utiliser des icônes plus foncées",
 		MENU_ICON_SET_TOOLTIP = "Utiliser des icônes plus lissées que par défaut",
diff --git a/Utility.lua b/Utility.lua
index 3cd7e93..5c463de 100644
--- a/Utility.lua
+++ b/Utility.lua
@@ -44,17 +44,8 @@ function u.StartsWith(String,Start)
     return Start=='' or string.sub(String, 1, string.len(Start))==Start
 end

-local languageElements = {"de ", "à ", "la ", }
 local separators = {"%^[%a:]+", "-", " " }

-function u.StripLanguageIdentifiers(entry)
-    if not entry or entry == "" then return "" end
-    for _,v in pairs(languageElements) do
-        entry = entry:gsub(v, "")
-    end
-    return entry
-end
-
 function u.Compress(entry)
     if not entry or entry == "" then return "" end
     for _,v in pairs(separators) do
@@ -65,9 +56,6 @@ end

 function u.CleanString(entry)
     if not entry or entry == "" then return "" end
-    if SousChef.settings.experimentalMatch then
-        entry = u.StripLanguageIdentifiers(entry)
-    end
     return u.Compress(entry):lower()
 end

@@ -77,32 +65,6 @@ function u.TableKeyConcat(t)
     return table.concat(tt, ", ")
 end

-function u.MatchInCookbook(name)
-    name = u.CleanString(name)
-    for recipe,known in pairs(SousChef.Cookbook) do
-        if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then
-            local difference =  (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name)
-            if  difference < 3 and difference > -3 then
-                return known
-            end
-        end
-    end
-	return nil
-end
-
-function u.MatchInGlobalCookbook(name)
-    name = u.CleanString(name)
-    for recipe,known in pairs(SousChef.settings.Cookbook) do
-        if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then
-            local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name)
-            if difference < 3 and difference > - 3 then
-                return known
-            end
-        end
-    end
-    return nil
-end
-
 function u.MatchInIgnoreList(name)
     name = u.CleanString(name)
     for recipe in pairs(SousChef.settings.ignoredRecipes) do
diff --git a/libs/LibAddonMenu-2.0/LICENSE b/libs/LibAddonMenu-2.0/LICENSE
new file mode 100644
index 0000000..82fcf2f
--- /dev/null
+++ b/libs/LibAddonMenu-2.0/LICENSE
@@ -0,0 +1,201 @@
+               The Artistic License 2.0
+
+           Copyright (c) 2015 Ryan Lakanen (Seerah)
+
+     Everyone is permitted to copy and distribute verbatim copies
+      of this license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or redistributed.
+The intent is that the Copyright Holder maintains some artistic
+control over the development of that Package while still keeping the
+Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package.  If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement.
+
+Definitions
+
+    "Copyright Holder" means the individual(s) or organization(s)
+    named in the copyright notice for the entire Package.
+
+    "Contributor" means any party that has contributed code or other
+    material to the Package, in accordance with the Copyright Holder's
+    procedures.
+
+    "You" and "your" means any person who would like to copy,
+    distribute, or modify the Package.
+
+    "Package" means the collection of files distributed by the
+    Copyright Holder, and derivatives of that collection and/or of
+    those files. A given Package may consist of either the Standard
+    Version, or a Modified Version.
+
+    "Distribute" means providing a copy of the Package or making it
+    accessible to anyone else, or in the case of a company or
+    organization, to others outside of your company or organization.
+
+    "Distributor Fee" means any fee that you charge for Distributing
+    this Package or providing support for this Package to another
+    party.  It does not mean licensing fees.
+
+    "Standard Version" refers to the Package if it has not been
+    modified, or has been modified only in ways explicitly requested
+    by the Copyright Holder.
+
+    "Modified Version" means the Package, if it has been changed, and
+    such changes were not explicitly requested by the Copyright
+    Holder.
+
+    "Original License" means this Artistic License as Distributed with
+    the Standard Version of the Package, in its current version or as
+    it may be modified by The Perl Foundation in the future.
+
+    "Source" form means the source code, documentation source, and
+    configuration files for the Package.
+
+    "Compiled" form means the compiled bytecode, object code, binary,
+    or any other form resulting from mechanical transformation or
+    translation of the Source form.
+
+
+Permission for Use and Modification Without Distribution
+
+(1)  You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+
+Permissions for Redistribution of the Standard Version
+
+(2)  You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers.  At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3)  You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder.  The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+
+Distribution of Modified Versions of the Package as Source
+
+(4)  You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+    (a)  make the Modified Version available to the Copyright Holder
+    of the Standard Version, under the Original License, so that the
+    Copyright Holder may include your modifications in the Standard
+    Version.
+
+    (b)  ensure that installation of your Modified Version does not
+    prevent the user installing or running the Standard Version. In
+    addition, the Modified Version must bear a name that is different
+    from the name of the Standard Version.
+
+    (c)  allow anyone who receives a copy of the Modified Version to
+    make the Source form of the Modified Version available to others
+    under
+
+    (i)  the Original License or
+
+    (ii)  a license that permits the licensee to freely copy,
+    modify and redistribute the Modified Version using the same
+    licensing terms that apply to the copy that the licensee
+    received, and requires that the Source form of the Modified
+    Version, and of any works derived from it, be made freely
+    available in that license fees are prohibited but Distributor
+    Fees are allowed.
+
+
+Distribution of Compiled Forms of the Standard Version
+or Modified Versions without the Source
+
+(5)  You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version.  Such instructions must be
+valid at the time of your distribution.  If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further distribution.
+If you provide valid instructions or cease distribution within thirty
+days after you become aware that the instructions are invalid, then
+you do not forfeit any of your rights under this license.
+
+(6)  You may Distribute a Modified Version in Compiled form without
+the Source, provided that you comply with Section 4 with respect to
+the Source of the Modified Version.
+
+
+Aggregating or Linking the Package
+
+(7)  You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package.  Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+
+Items That are Not Considered Part of a Modified Version
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version.  In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+
+General Provisions
+
+(10)  Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11)  If your Modified Version has been derived from a Modified
+Version made by someone other than you, you are nevertheless required
+to ensure that your Modified Version complies with the requirements of
+this license.
+
+(12)  This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13)  This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14)  Disclaimer of Warranty:
+THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
+LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua b/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
index 05f0670..2e7aa91 100644
--- a/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
+++ b/libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
@@ -1,16 +1,34 @@
---	LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah)	--
---	All Rights Reserved										--
---	Permission is granted to use Seerah's LibAddonMenu-2.0	--
---	in your project. Any modifications to LibAddonMenu-2.0	--
---	may not be redistributed.								--
---------------------------------------------------------------
+--	LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah)		--
+--	Distributed under The Artistic License 2.0 (see LICENSE)	--
+------------------------------------------------------------------


 --Register LAM with LibStub
-local MAJOR, MINOR = "LibAddonMenu-2.0", 16
+local MAJOR, MINOR = "LibAddonMenu-2.0", 17
 local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
-if not lam then return end	--the same or newer version of this lib is already loaded into memory
+if not lam then return end	--the same or newer version of this lib is already loaded into memory

+local messages = {}
+local MESSAGE_PREFIX = "[LAM2] "
+local function PrintLater(msg)
+	if(CHAT_SYSTEM.primaryContainer) then
+		d(MESSAGE_PREFIX .. msg)
+	else
+		messages[#messages + 1] = msg
+	end
+end
+
+local function FlushMessages()
+	for i = 1, #messages do
+		d(MESSAGE_PREFIX .. messages[i])
+	end
+	messages = {}
+end
+
+if(LAMSettingsPanelCreated and not LAMCompatibilityWarning) then
+	PrintLater("An old version of LibAddonMenu with compatibility issues was detected. For more information on how to proceed search for LibAddonMenu on esoui.com")
+	LAMCompatibilityWarning = true
+end

 --UPVALUES--
 local wm = WINDOW_MANAGER
@@ -48,23 +66,31 @@ end
 --METHOD: OPEN TO ADDON PANEL--
 --opens to a specific addon's option panel
 --Usage:
---	panel = userdata; the panel returned by the :RegisterOptionsPanel method
---local settings = {en = "Settings", de = "Einstellungen", fr = "Réglages"}
---local locSettings = settings[GetCVar("Language.2")]
+--  panel = userdata; the panel returned by the :RegisterOptionsPanel method
 local locSettings = GetString(SI_GAME_MENU_SETTINGS)
 function lam:OpenToPanel(panel)
 	SCENE_MANAGER:Show("gameMenuInGame")
 	zo_callLater(function()
-			ZO_GameMenu_InGame.gameMenu.headerControls[locSettings]:SetOpen(true)
-			SCENE_MANAGER:AddFragment(OPTIONS_WINDOW_FRAGMENT)
-			--ZO_OptionsWindow_ChangePanels(lam.panelID)
-			KEYBOARD_OPTIONS:ChangePanels(lam.panelID)
-			--if not lam.panelSubCategoryControl then
-			--	lam.panelSubCategoryControl = _G["ZO_GameMenu_InGameNavigationContainerScrollChildZO_GameMenu_SubCategory"..(lam.panelID + 1)]
-			--end
-			--ZO_TreeEntry_OnMouseUp(lam.panelSubCategoryControl, true)
-			panel:SetHidden(false)
-		end, 200)
+		local settingsMenu = ZO_GameMenu_InGame.gameMenu.headerControls[locSettings]
+		settingsMenu:SetOpen(true)
+		SCENE_MANAGER:AddFragment(OPTIONS_WINDOW_FRAGMENT)
+		KEYBOARD_OPTIONS:ChangePanels(lam.panelID)
+		for i, child in pairs(settingsMenu.children) do
+			if type(child) == "table" and child.data.name == KEYBOARD_OPTIONS.panelNames[lam.panelID] then
+				ZO_TreeEntry_OnMouseUp(child.control, true)
+				break
+			end
+		end
+		local scroll = LAMAddonPanelsMenuScrollChild
+		for i = 1, scroll:GetNumChildren() do
+			local button = scroll:GetChild(i)
+			if button.panel == panel then
+				zo_callHandler(button, "OnClicked")
+				ZO_Scroll_ScrollControlToTop(LAMAddonPanelsMenu, button)
+				break
+			end
+		end
+	end, 200)
 end


@@ -74,62 +100,75 @@ end
 local function CreateOptionsControls(panel)
 	local addonID = panel:GetName()
 	local optionsTable = addonToOptionsMap[addonID]
-
+
 	if optionsTable then
-		local lastAddedControl, lacAtHalfRow
-		for _, widgetData in ipairs(optionsTable) do
-			local widgetType = widgetData.type
+		local isHalf, widget
+		local lastAddedControl, lacAtHalfRow, oIndex, widgetData, widgetType
+		local submenu, subWidgetData, sIndex, subWidgetType, subWidget
+		local anchorOffset = 0
+		local anchorOffsetSub
+		local lastAddedControlSub, lacAtHalfRowSub
+		for oIndex=1,#optionsTable do
+			widgetData = optionsTable[oIndex]
+			widgetType = widgetData.type
 			if widgetType == "submenu" then
-				local submenu = LAMCreateControl[widgetType](panel, widgetData)
+				submenu = LAMCreateControl[widgetType](panel, widgetData)
 				if lastAddedControl then
-					submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
+					submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15 + anchorOffset)
 				else
 					submenu:SetAnchor(TOPLEFT)
 				end
 				lastAddedControl = submenu
 				lacAtHalfRow = false
-
-				local lastAddedControlSub, lacAtHalfRowSub
-				for _, subWidgetData in ipairs(widgetData.controls) do
-					local subWidgetType = subWidgetData.type
-					local subWidget = LAMCreateControl[subWidgetType](submenu, subWidgetData)
-					local isHalf = subWidgetData.width == "half"
+
+				anchorOffsetSub = 0
+				lacAtHalfRowSub = nil
+				lastAddedControlSub = nil
+				for sIndex=1,#widgetData.controls do
+					subWidgetData = widgetData.controls[sIndex]
+					subWidgetType = subWidgetData.type
+					subWidget = LAMCreateControl[subWidgetType](submenu, subWidgetData)
+					isHalf = subWidgetData.width == "half"
 					if lastAddedControlSub then
 						if lacAtHalfRowSub and isHalf then
 							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, TOPRIGHT, 5, 0)
 							lacAtHalfRowSub = false
+							anchorOffsetSub = zo_max(0, subWidget:GetHeight() - lastAddedControlSub:GetHeight())
 						else
-							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15)
-							lacAtHalfRowSub = isHalf and true or false
+							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15 + anchorOffsetSub)
+							lacAtHalfRowSub = isHalf
+							anchorOffsetSub = 0
 							lastAddedControlSub = subWidget
 						end
 					else
 						subWidget:SetAnchor(TOPLEFT)
-						lacAtHalfRowSub = isHalf and true or false
+						lacAtHalfRowSub = isHalf
 						lastAddedControlSub = subWidget
 					end
 				end
 			else
-				local widget = LAMCreateControl[widgetType](panel, widgetData)
-				local isHalf = widgetData.width == "half"
+				widget = LAMCreateControl[widgetType](panel, widgetData)
+				isHalf = widgetData.width == "half"
 				if lastAddedControl then
 					if lacAtHalfRow and isHalf then
 						widget:SetAnchor(TOPLEFT, lastAddedControl, TOPRIGHT, 10, 0)
+						anchorOffset = zo_max(0, widget:GetHeight() - lastAddedControl:GetHeight())
 						lacAtHalfRow = false
 					else
-						widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
-						lacAtHalfRow = isHalf and true or false
+						widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15 + anchorOffset)
+						lacAtHalfRow = isHalf
+						anchorOffset = 0
 						lastAddedControl = widget
 					end
 				else
 					widget:SetAnchor(TOPLEFT)
-					lacAtHalfRow = isHalf and true or false
+					lacAtHalfRow = isHalf
 					lastAddedControl = widget
 				end
 			end
-		end
+		end
 	end
-
+
 	optionsCreated[addonID] = true
 	cm:FireCallbacks("LAM-PanelControlsCreated", panel)
 end
@@ -143,14 +182,16 @@ local function ToggleAddonPanels(panel)	--called in OnShow of newly shown panel
 		currentlySelected:SetHidden(true)
 	end
 	LAMAddonPanelsMenu.currentlySelected = panel
-
+
 	if not optionsCreated[panel:GetName()] then	--if this is the first time opening this panel, create these options
 		CreateOptionsControls(panel)
 	end
-
+
 	cm:FireCallbacks("LAM-RefreshPanel", panel)
 end

+local Initialize
+local hasInitialized = false

 --METHOD: REGISTER ADDON PANEL
 --registers your addon with LibAddonMenu and creates a panel
@@ -158,6 +199,7 @@ end
 --	addonID = "string"; unique ID which will be the global name of your panel
 --	panelData = table; data object for your panel - see controls\panel.lua
 function lam:RegisterAddonPanel(addonID, panelData)
+	if(not hasInitialized) then Initialize(addonID) end
 	local panel = lamcc.panel(nil, panelData, addonID)	--addonID==global name of panel
 	panel:SetHidden(true)
 	panel:SetAnchor(TOPLEFT, LAMAddonPanelsMenu, TOPRIGHT, 10, 0)
@@ -235,12 +277,11 @@ local function CreateAddonSettingsPanel()
 			es = "Configura Addons",
 		}

-		ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")] or controlPanelName["en"])
+		ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")] or controlPanelNames["en"], PANEL_TYPE_SETTINGS)

 		lam.panelID = _G[controlPanelID]

-		--ZO_PreHook("ZO_OptionsWindow_ChangePanels", HandlePanelSwitching)
-		ZO_PreHook(ZO_SharedOptions, "ChangePanels", HandlePanelSwitching)
+		ZO_PreHook(ZO_KeyboardOptions, "ChangePanels", HandlePanelSwitching)

 		LAMSettingsPanelCreated = true
 	end
@@ -315,8 +356,29 @@ local function CreateAddonList()
 	return list
 end

-
 --INITIALIZING
-CreateAddonSettingsPanel()
-CreateAddonList()
+local safeToInitialize = false
+
+local eventHandle = table.concat({MAJOR, MINOR}, "r")
+local function OnLoad(_, addonName)
+	-- wait for the first loaded event
+	EVENT_MANAGER:UnregisterForEvent(eventHandle, EVENT_ADD_ON_LOADED)
+	safeToInitialize = true
+end
+EVENT_MANAGER:RegisterForEvent(eventHandle, EVENT_ADD_ON_LOADED, OnLoad)

+local function OnActivated(_, addonName)
+	EVENT_MANAGER:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED)
+	FlushMessages()
+end
+EVENT_MANAGER:RegisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED, OnActivated)
+
+function Initialize(addonID)
+	if(not safeToInitialize) then
+		local msg = string.format("The panel with id '%s' was registered before addon loading has completed. This might break the AddOn Settings menu.", addonID)
+		PrintLater(msg)
+	end
+	CreateAddonSettingsPanel()
+	CreateAddonList()
+	hasInitialized = true
+end
diff --git a/libs/LibAddonMenu-2.0/controls/button.lua b/libs/LibAddonMenu-2.0/controls/button.lua
index 13387a1..49d0059 100644
--- a/libs/LibAddonMenu-2.0/controls/button.lua
+++ b/libs/LibAddonMenu-2.0/controls/button.lua
@@ -11,7 +11,7 @@
 }	]]


-local widgetVersion = 5
+local widgetVersion = 6
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("button", widgetVersion) then return end

@@ -33,13 +33,12 @@ end

 --controlName is optional
 function LAMCreateControl.button(parent, buttonData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or buttonData.reference)
-	control:SetParent(parent.scroll or parent)
-
+	local control = wm:CreateControl(controlName or buttonData.reference, parent.scroll or parent, CT_CONTROL)
+
 	local isHalfWidth = buttonData.width == "half"
 	control:SetDimensions(isHalfWidth and 250 or 510, isHalfWidth and 55 or 28)
 	control:SetMouseEnabled(true)
-
+
 	if buttonData.icon then
 		control.button = wm:CreateControl(nil, control, CT_BUTTON)
 		control.button:SetDimensions(26, 26)
@@ -64,26 +63,26 @@ function LAMCreateControl.button(parent, buttonData, controlName)
 				cm:FireCallbacks("LAM-RefreshPanel", control)
 			end
 		end)
-
+
 	if buttonData.warning then
 		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
 		control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0)
 		--control.warning.tooltipText = buttonData.warning
 		control.warning.data = {tooltipText = buttonData.warning}
 	end
-
+
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = buttonData
-
+
 	if buttonData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
-
+
 		--this is here because buttons don't have an UpdateValue method
 		if control.panel.data.registerForRefresh then	--if our parent window wants to refresh controls, then add this to the list
 			tinsert(control.panel.controlsToRefresh, control)
 		end
 	end
-
+
 	return control
 end
\ No newline at end of file
diff --git a/libs/LibAddonMenu-2.0/controls/checkbox.lua b/libs/LibAddonMenu-2.0/controls/checkbox.lua
index 14b1638..a5142a9 100644
--- a/libs/LibAddonMenu-2.0/controls/checkbox.lua
+++ b/libs/LibAddonMenu-2.0/controls/checkbox.lua
@@ -12,7 +12,7 @@
 }	]]


-local widgetVersion = 7
+local widgetVersion = 8
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("checkbox", widgetVersion) then return end

@@ -36,16 +36,16 @@ local function UpdateDisabled(control)
 	else
 		disable = control.data.disabled
 	end
-
+
 	control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA())
 	control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA())
 	--control:SetMouseEnabled(not disable)
 	--control:SetMouseEnabled(true)
-
+
 	control.isDisabled = disable
 end

-local function ToggleCheckbox(control)
+local function ToggleCheckbox(control)
 	if control.value then
 		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
 		control.checkbox:SetText(control.checkedText)
@@ -69,13 +69,13 @@ local function UpdateValue(control, forceDefault, value)
 		value = control.data.getFunc()
 	end
 	control.value = value
-
+
 	ToggleCheckbox(control)
 end

 local function OnMouseEnter(control)
 	ZO_Options_OnMouseEnter(control)
-
+
 	if control.isDisabled then return end

 	local label = control.label
@@ -88,8 +88,8 @@ local function OnMouseEnter(control)
 end

 local function OnMouseExit(control)
-    ZO_Options_OnMouseExit(control)
-
+	ZO_Options_OnMouseExit(control)
+
 	if control.isDisabled then return end

 	local label = control.label
@@ -104,8 +104,7 @@ end

 --controlName is optional
 function LAMCreateControl.checkbox(parent, checkboxData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or checkboxData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or checkboxData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetMouseEnabled(true)
 	--control.tooltipText = checkboxData.tooltip
 	control:SetHandler("OnMouseEnter", OnMouseEnter)
@@ -116,7 +115,7 @@ function LAMCreateControl.checkbox(parent, checkboxData, controlName)
 			control.value = not control.value
 			control:UpdateValue(false, control.value)
 		end)
-
+
 	control.label = wm:CreateControl(nil, control, CT_LABEL)
 	local label = control.label
 	label:SetFont("ZoFontWinH4")
@@ -143,27 +142,27 @@ function LAMCreateControl.checkbox(parent, checkboxData, controlName)
 		checkbox:SetDimensions(200, 26)
 		checkbox:SetAnchor(RIGHT)
 		label:SetAnchor(LEFT)
-		label:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
+		label:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
 	end
-
+
 	if checkboxData.warning then
 		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
 		control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
 		--control.warning.tooltipText = checkboxData.warning
 		control.warning.data = {tooltipText = checkboxData.warning}
 	end
-
+
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = checkboxData
 	control.data.tooltipText = checkboxData.tooltip
-
+
 	if checkboxData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
 	end
 	control.UpdateValue = UpdateValue
 	control:UpdateValue()
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
diff --git a/libs/LibAddonMenu-2.0/controls/colorpicker.lua b/libs/LibAddonMenu-2.0/controls/colorpicker.lua
index 3918030..e820539 100644
--- a/libs/LibAddonMenu-2.0/controls/colorpicker.lua
+++ b/libs/LibAddonMenu-2.0/controls/colorpicker.lua
@@ -12,7 +12,7 @@
 }	]]


-local widgetVersion = 5
+local widgetVersion = 6
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end

@@ -28,13 +28,13 @@ local function UpdateDisabled(control)
 	else
 		disable = control.data.disabled
 	end
-
+
 	if disable then
 		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
 	else
 		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
 	end
-
+
 	control.isDisabled = disable
 end

@@ -58,13 +58,11 @@ end


 function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or colorpickerData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or colorpickerData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetMouseEnabled(true)
-	--control.tooltipText = colorpickerData.tooltip
 	control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
 	control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
+
 	control.label = wm:CreateControl(nil, control, CT_LABEL)
 	local label = control.label
 	label:SetDimensions(300, 26)
@@ -72,10 +70,10 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
 	label:SetFont("ZoFontWinH4")
 	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
 	label:SetText(colorpickerData.name)
-
+
 	control.color = wm:CreateControl(nil, control, CT_CONTROL)
 	local color = control.color
-
+
 	local isHalfWidth = colorpickerData.width == "half"
 	if isHalfWidth then
 		control:SetDimensions(250, 55)
@@ -88,12 +86,12 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
 		color:SetDimensions(200, 24)
 		color:SetAnchor(TOPRIGHT)
 	end
-
+
 	control.thumb = wm:CreateControl(nil, color, CT_TEXTURE)
 	local thumb = control.thumb
 	thumb:SetDimensions(36, 18)
 	thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
-
+
 	color.border = wm:CreateControl(nil, color, CT_TEXTURE)
 	local border = color.border
 	border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
@@ -104,10 +102,10 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
 	local function ColorPickerCallback(r, g, b, a)
 			control:UpdateValue(false, r, g, b, a)
 		end
-
+
 	control:SetHandler("OnMouseUp", function(self, btn, upInside)
 			if self.isDisabled then return end
-
+
 			if upInside then
 				local r, g, b, a = colorpickerData.getFunc()
 				COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name)
@@ -120,11 +118,11 @@ function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
 		--control.warning.tooltipText = colorpickerData.warning
 		control.warning.data = {tooltipText = colorpickerData.warning}
 	end
-
+
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = colorpickerData
 	control.data.tooltipText = colorpickerData.tooltip
-
+
 	if colorpickerData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
diff --git a/libs/LibAddonMenu-2.0/controls/custom.lua b/libs/LibAddonMenu-2.0/controls/custom.lua
index fcfa618..bb1c2d1 100644
--- a/libs/LibAddonMenu-2.0/controls/custom.lua
+++ b/libs/LibAddonMenu-2.0/controls/custom.lua
@@ -5,7 +5,7 @@
 	width = "full",	--or "half" (optional)
 }	]]

-local widgetVersion = 4
+local widgetVersion = 5
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("custom", widgetVersion) then return end

@@ -19,10 +19,9 @@ local function UpdateValue(control)
 end

 function LAMCreateControl.custom(parent, customData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or customData.reference)
+	local control = wm:CreateControl(controlName or customData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetResizeToFitDescendents(true)
-	control:SetParent(parent.scroll or parent)
-
+
 	local isHalfWidth = customData.width == "half"
 	if isHalfWidth then	--note these restrictions
 		control:SetDimensionConstraints(250, 55, 250, 100)
@@ -34,12 +33,12 @@ function LAMCreateControl.custom(parent, customData, controlName)

 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = customData
-
+
 	control.UpdateValue = UpdateValue
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
-
+
 	return control
 end
\ No newline at end of file
diff --git a/libs/LibAddonMenu-2.0/controls/description.lua b/libs/LibAddonMenu-2.0/controls/description.lua
index aac6d9e..795ac10 100644
--- a/libs/LibAddonMenu-2.0/controls/description.lua
+++ b/libs/LibAddonMenu-2.0/controls/description.lua
@@ -7,7 +7,7 @@
 }	]]


-local widgetVersion = 4
+local widgetVersion = 5
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("description", widgetVersion) then return end

@@ -22,9 +22,8 @@ local function UpdateValue(control)
 end

 function LAMCreateControl.description(parent, descriptionData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or descriptionData.reference)
+	local control = wm:CreateControl(controlName or descriptionData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetResizeToFitDescendents(true)
-	control:SetParent(parent.scroll or parent)
 	local isHalfWidth = descriptionData.width == "half"
 	if isHalfWidth then
 		control:SetDimensionConstraints(250, 55, 250, 100)
@@ -33,7 +32,7 @@ function LAMCreateControl.description(parent, descriptionData, controlName)
 		control:SetDimensionConstraints(510, 40, 510, 100)
 		control:SetDimensions(510, 30)
 	end
-
+
 	control.desc = wm:CreateControl(nil, control, CT_LABEL)
 	local desc = control.desc
 	desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
@@ -55,13 +54,13 @@ function LAMCreateControl.description(parent, descriptionData, controlName)

 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = descriptionData
-
+
 	control.UpdateValue = UpdateValue
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
-
+
 	return control

 end
\ No newline at end of file
diff --git a/libs/LibAddonMenu-2.0/controls/dropdown.lua b/libs/LibAddonMenu-2.0/controls/dropdown.lua
index 10c44eb..346f23d 100644
--- a/libs/LibAddonMenu-2.0/controls/dropdown.lua
+++ b/libs/LibAddonMenu-2.0/controls/dropdown.lua
@@ -14,7 +14,7 @@
 }	]]


-local widgetVersion = 7
+local widgetVersion = 8
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("dropdown", widgetVersion) then return end

@@ -30,7 +30,7 @@ local function UpdateDisabled(control)
 	else
 		disable = control.data.disabled
 	end
-
+
 	control.dropdown:SetEnabled(not disable)
 	if disable then
 		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
@@ -39,7 +39,7 @@ local function UpdateDisabled(control)
 	end
 end

-local function UpdateValue(control, forceDefault, value)
+local function UpdateValue(control, forceDefault, value)
 	if forceDefault then	--if we are forcing defaults
 		value = control.data.default
 		control.data.setFunc(value)
@@ -56,13 +56,13 @@ local function UpdateValue(control, forceDefault, value)
 	end
 end

-local function DropdownCallback(choice, choiceText, choice)
+local function DropdownCallback(control, choiceText, choice)
 	choice.control:UpdateValue(false, choiceText)
 end

 local function UpdateChoices(control, choices)
 	control.dropdown:ClearItems()	--remove previous choices	--(need to call :SetSelectedItem()?)
-
+
 	--build new list of choices
 	local choices = choices or control.data.choices
 	for i = 1, #choices do
@@ -83,15 +83,12 @@ local function GrabSortingInfo(sortInfo)
 end


-local comboboxCount = 1
 function LAMCreateControl.dropdown(parent, dropdownData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or dropdownData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or dropdownData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetMouseEnabled(true)
-	--control.tooltipText = dropdownData.tooltip
 	control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
 	control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
+
 	control.label = wm:CreateControl(nil, control, CT_LABEL)
 	local label = control.label
 	label:SetAnchor(TOPLEFT)
@@ -99,8 +96,16 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
 	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
 	label:SetText(dropdownData.name)

-	control.combobox = wm:CreateControlFromVirtual(parent:GetName().."Combobox"..comboboxCount, control, "ZO_ComboBox")
-	comboboxCount = comboboxCount + 1
+	local countControl = parent
+	local name = parent:GetName()
+	if not name or #name == 0 then
+		countControl = LAMCreateControl
+		name = "LAM"
+	end
+	local comboboxCount = (countControl.comboboxCount or 0) + 1
+	countControl.comboboxCount = comboboxCount
+	control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control, "ZO_ComboBox")
+
 	local combobox = control.combobox
 	combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
 	combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
@@ -111,7 +116,7 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
 		local sortType, sortOrder = sortInfo[1], sortInfo[2]
 		dropdown:SetSortOrder(sortOrder == "up" and ZO_SORT_ORDER_UP or ZO_SORT_ORDER_DOWN, sortType == "name" and ZO_SORT_BY_NAME or ZO_SORT_BY_NAME_NUMERIC)
 	end
-
+
 	local isHalfWidth = dropdownData.width == "half"
 	if isHalfWidth then
 		control:SetDimensions(250, 55)
@@ -124,18 +129,17 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
 		combobox:SetDimensions(200, 26)
 		combobox:SetAnchor(TOPRIGHT)
 	end
-
+
 	if dropdownData.warning then
 		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
 		control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0)
-		--control.warning.tooltipText = dropdownData.warning
 		control.warning.data = {tooltipText = dropdownData.warning}
 	end

 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = dropdownData
 	control.data.tooltipText = dropdownData.tooltip
-
+
 	if dropdownData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
@@ -144,7 +148,7 @@ function LAMCreateControl.dropdown(parent, dropdownData, controlName)
 	control:UpdateChoices(dropdownData.choices)
 	control.UpdateValue = UpdateValue
 	control:UpdateValue()
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
diff --git a/libs/LibAddonMenu-2.0/controls/editbox.lua b/libs/LibAddonMenu-2.0/controls/editbox.lua
index 25396ff..b473f23 100644
--- a/libs/LibAddonMenu-2.0/controls/editbox.lua
+++ b/libs/LibAddonMenu-2.0/controls/editbox.lua
@@ -13,7 +13,7 @@
 }	]]


-local widgetVersion = 6
+local widgetVersion = 7
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("editbox", widgetVersion) then return end

@@ -60,24 +60,22 @@ end


 function LAMCreateControl.editbox(parent, editboxData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or editboxData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or editboxData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetMouseEnabled(true)
 	control:SetResizeToFitDescendents(true)
-	--control.tooltipText = editboxData.tooltip
 	control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
 	control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
+
 	control.label = wm:CreateControl(nil, control, CT_LABEL)
 	local label = control.label
 	label:SetAnchor(TOPLEFT)
 	label:SetFont("ZoFontWinH4")
 	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
 	label:SetText(editboxData.name)
-
+
 	control.bg = wm:CreateControlFromVirtual(nil, control, "ZO_EditBackdrop")
 	local bg = control.bg
-
+
 	if editboxData.isMultiline then
 		control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop")
 		control.editbox:SetHandler("OnMouseWheel", function(self, delta)
@@ -109,7 +107,7 @@ function LAMCreateControl.editbox(parent, editboxData, controlName)
 	editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end)
 	editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
 	editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
-
+
 	local isHalfWidth = editboxData.width == "half"
 	if isHalfWidth then
 		control:SetDimensions(250, 55)
@@ -139,7 +137,7 @@ function LAMCreateControl.editbox(parent, editboxData, controlName)
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = editboxData
 	control.data.tooltipText = editboxData.tooltip
-
+
 	if editboxData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
diff --git a/libs/LibAddonMenu-2.0/controls/header.lua b/libs/LibAddonMenu-2.0/controls/header.lua
index 98df539..14851ee 100644
--- a/libs/LibAddonMenu-2.0/controls/header.lua
+++ b/libs/LibAddonMenu-2.0/controls/header.lua
@@ -6,7 +6,7 @@
 }	]]


-local widgetVersion = 4
+local widgetVersion = 5
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("header", widgetVersion) then return end

@@ -18,11 +18,10 @@ local function UpdateValue(control)
 end

 function LAMCreateControl.header(parent, headerData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or headerData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or headerData.reference, parent.scroll or parent, CT_CONTROL)
 	local isHalfWidth = headerData.width == "half"
 	control:SetDimensions(isHalfWidth and 250 or 510, 30)
-
+
 	control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider")
 	local divider = control.divider
 	divider:SetWidth(isHalfWidth and 250 or 510)
@@ -33,15 +32,15 @@ function LAMCreateControl.header(parent, headerData, controlName)
 	header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT)
 	header:SetAnchor(BOTTOMRIGHT)
 	header:SetText(headerData.name)
-
+
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = headerData
-
+
 	control.UpdateValue = UpdateValue
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
-
+
 	return control
 end
\ No newline at end of file
diff --git a/libs/LibAddonMenu-2.0/controls/panel.lua b/libs/LibAddonMenu-2.0/controls/panel.lua
index 158fd8d..46d39a0 100644
--- a/libs/LibAddonMenu-2.0/controls/panel.lua
+++ b/libs/LibAddonMenu-2.0/controls/panel.lua
@@ -21,10 +21,10 @@ local cm = CALLBACK_MANAGER
 local function RefreshPanel(control)
 	local panel = control.panel or control	--callback can be fired by a single control or by the panel showing
 	local panelControls = panel.controlsToRefresh
-
+
 	for i = 1, #panelControls do
 		local updateControl = panelControls[i]
-		if  updateControl ~= control then
+		if  updateControl ~= control then
 			if updateControl.UpdateValue then
 				updateControl:UpdateValue()
 			end
@@ -37,18 +37,18 @@ end

 local function ForceDefaults(panel)
 	local panelControls = panel.controlsToRefresh
-
+
 	for i = 1, #panelControls do
 		local updateControl = panelControls[i]
 		if updateControl.UpdateValue and updateControl.data.default ~= nil then
 			updateControl:UpdateValue(true)
 		end
 	end
-
+
 	if panel.data.resetFunc then
 		panel.data.resetFunc()
 	end
-
+
 	cm:FireCallbacks("LAM-RefreshPanel", panel)
 end
 ESO_Dialogs["LAM_DEFAULTS"] = {
@@ -81,12 +81,12 @@ function LAMCreateControl.panel(parent, panelData, controlName)
 	bg:SetAnchorFill()
 	bg:SetEdgeTexture("EsoUI\\Art\\miscellaneous\\borderedinsettransparent_edgefile.dds", 128, 16)
 	bg:SetCenterColor(0, 0, 0, 0)
-
+
 	control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
 	local label = control.label
 	label:SetAnchor(TOPLEFT, control, TOPLEFT, 10, 10)
 	label:SetText(panelData.displayName and panelData.displayName or panelData.name)
-
+
 	if panelData.author or panelData.version then
 		control.info = wm:CreateControl(nil, control, CT_LABEL)
 		local info = control.info
@@ -103,7 +103,7 @@ function LAMCreateControl.panel(parent, panelData, controlName)
 			info:SetText("Version: "..panelData.version)
 		end
 	end
-
+
 	control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer")
 	LAMCreateControl.scrollCount = LAMCreateControl.scrollCount + 1
 	local container = control.container
@@ -111,7 +111,7 @@ function LAMCreateControl.panel(parent, panelData, controlName)
 	container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3)
 	control.scroll = GetControl(control.container, "ScrollChild")
 	control.scroll:SetResizeToFitPadding(0, 20)
-
+
 	if panelData.registerForDefaults then
 		control.defaultButton = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultTextButton")
 		local defaultButton = control.defaultButton
@@ -133,6 +133,6 @@ function LAMCreateControl.panel(parent, panelData, controlName)

 	control.data = panelData
 	control.controlsToRefresh = {}
-
+
 	return control
 end
\ No newline at end of file
diff --git a/libs/LibAddonMenu-2.0/controls/slider.lua b/libs/LibAddonMenu-2.0/controls/slider.lua
index e7bc01c..e02cb5d 100644
--- a/libs/LibAddonMenu-2.0/controls/slider.lua
+++ b/libs/LibAddonMenu-2.0/controls/slider.lua
@@ -15,7 +15,7 @@
 }	]]


-local widgetVersion = 5
+local widgetVersion = 6
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("slider", widgetVersion) then return end

@@ -32,7 +32,7 @@ local function UpdateDisabled(control)
 	else
 		disable = control.data.disabled
 	end
-
+
 	control.slider:SetEnabled(not disable)
 	control.slidervalue:SetEditEnabled(not disable)
 	if disable then
@@ -61,15 +61,14 @@ local function UpdateValue(control, forceDefault, value)
 	else
 		value = control.data.getFunc()
 	end
-
+
 	control.slider:SetValue(value)
 	control.slidervalue:SetText(value)
 end


 function LAMCreateControl.slider(parent, sliderData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or sliderData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or sliderData.reference, parent.scroll or parent, CT_CONTROL)
 	local isHalfWidth = sliderData.width == "half"
 	if isHalfWidth then
 		control:SetDimensions(250, 55)
@@ -80,7 +79,7 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 	--control.tooltipText = sliderData.tooltip
 	control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
 	control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-
+
 	control.label = wm:CreateControl(nil, control, CT_LABEL)
 	local label = control.label
 	label:SetFont("ZoFontWinH4")
@@ -88,7 +87,7 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
 	label:SetAnchor(isHalfWidth and TOPLEFT or LEFT)
 	label:SetText(sliderData.name)
-
+
 	--skipping creating the backdrop...  Is this the actual slider texture?
 	control.slider = wm:CreateControl(nil, control, CT_SLIDER)
 	local slider = control.slider
@@ -107,14 +106,14 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 	slider:SetMinMax(minValue, maxValue)
 	slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
 	slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end)
-
+
 	slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP)
 	local bg = slider.bg
 	bg:SetCenterColor(0, 0, 0)
 	bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4)
 	bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4)
 	bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
-
+
 	control.minText = wm:CreateControl(nil, slider, CT_LABEL)
 	local minText = control.minText
 	minText:SetFont("ZoFontGameSmall")
@@ -126,7 +125,7 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 	maxText:SetFont("ZoFontGameSmall")
 	maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT)
 	maxText:SetText(sliderData.max)
-
+
 	control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop")
 	control.slidervalueBG:SetDimensions(50, 16)
 	control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0)
@@ -145,7 +144,7 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 			self:LoseFocus()
 			control:UpdateValue(false, tonumber(self:GetText()))
 		end)
-
+
 	local range = maxValue - minValue
 	slider:SetValueStep(sliderData.step or 1)
 	slider:SetHandler("OnValueChanged", function(self, value, eventReason)
@@ -157,18 +156,18 @@ function LAMCreateControl.slider(parent, sliderData, controlName)
 			--sliderData.setFunc(value)
 			control:UpdateValue(false, value)	--does this work here instead?
 		end)
-
+
 	if sliderData.warning then
 		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
 		control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0)
 		--control.warning.tooltipText = sliderData.warning
 		control.warning.data = {tooltipText = sliderData.warning}
 	end
-
+
 	control.panel = parent.panel or parent	--if this is in a submenu, panel is the submenu's parent
 	control.data = sliderData
 	control.data.tooltipText = sliderData.tooltip
-
+
 	if sliderData.disabled then
 		control.UpdateDisabled = UpdateDisabled
 		control:UpdateDisabled()
diff --git a/libs/LibAddonMenu-2.0/controls/submenu.lua b/libs/LibAddonMenu-2.0/controls/submenu.lua
index ee2b777..c456d49 100644
--- a/libs/LibAddonMenu-2.0/controls/submenu.lua
+++ b/libs/LibAddonMenu-2.0/controls/submenu.lua
@@ -6,7 +6,7 @@
 	reference = "MyAddonSubmenu"	--(optional) unique global reference to control
 }	]]

-local widgetVersion = 7
+local widgetVersion = 8
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("submenu", widgetVersion) then return end

@@ -18,7 +18,6 @@ local tinsert = table.insert
 local function UpdateValue(control)
 	control.label:SetText(control.data.name)
 	if control.data.tooltip then
-		--control.label.tooltipText = control.data.tooltip
 		control.label.data = {tooltipText = control.data.tooltip}
 	end
 end
@@ -26,7 +25,7 @@ end
 local function AnimateSubmenu(clicked)
 	local control = clicked:GetParent()
 	control.open = not control.open
-
+
 	if control.open then
 		control.animation:PlayFromStart()
 	else
@@ -36,11 +35,10 @@ end


 function LAMCreateControl.submenu(parent, submenuData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or submenuData.reference)
-	control:SetParent(parent.scroll or parent)
+	local control = wm:CreateControl(controlName or submenuData.reference, parent.scroll or parent, CT_CONTROL)
 	control.panel = parent
 	control:SetDimensions(523, 40)
-
+
 	control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
 	local label = control.label
 	label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
@@ -49,12 +47,11 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
 	label:SetText(submenuData.name)
 	label:SetMouseEnabled(true)
 	if submenuData.tooltip then
-		--label.tooltipText = submenuData.tooltip
 		label.data = {tooltipText = submenuData.tooltip}
 		label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
 		label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
 	end
-
+
 	control.scroll = wm:CreateControl(nil, control, CT_SCROLL)
 	local scroll = control.scroll
 	scroll:SetParent(control)
@@ -68,23 +65,18 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
 	bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
 	bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
 	bg:SetInsets(16, 16, -16, -16)
-
+
 	control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE)
 	local arrow = control.arrow
 	arrow:SetDimensions(28, 28)
 	arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds")	--list_sortup for the other way
 	arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5)
-
+
 	--figure out the cool animation later...
 	control.animation = am:CreateTimeline()
 	local animation = control.animation
 	animation:SetPlaybackType(ANIMATION_SIZE, 0)	--2nd arg = loop count
-	--animation:SetDuration(1)
-	--animation:SetEasingFunction(ZO_LinearEase)	--is this needed?
-	--animation:SetHeightStartAndEnd(40, 80)	--SetStartAndEndHeight
-	--animation:SetStartAndEndHeight(40, 80)	--SetStartAndEndHeight
-	--animation:SetAnimatedControl(control)
-
+
 	control:SetResizeToFitDescendents(true)
 	control.open = false
 	label:SetHandler("OnMouseUp", AnimateSubmenu)
@@ -99,7 +91,7 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
 				scroll:SetHeight(0)
 			end
 		end)
-
+
 	--small strip at the bottom of the submenu that you can click to close it
 	control.btmToggle = wm:CreateControl(nil, control, CT_TEXTURE)
 	local btmToggle = control.btmToggle
@@ -109,15 +101,14 @@ function LAMCreateControl.submenu(parent, submenuData, controlName)
 	btmToggle:SetHeight(15)
 	btmToggle:SetAlpha(0)
 	btmToggle:SetHandler("OnMouseUp", AnimateSubmenu)
-
+
 	control.data = submenuData
-
+
 	control.UpdateValue = UpdateValue
-
+
 	if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then	--if our parent window wants to refresh controls, then add this to the list
 		tinsert(control.panel.controlsToRefresh, control)
 	end
-
+
 	return control
 end
-
diff --git a/libs/LibAddonMenu-2.0/controls/texture.lua b/libs/LibAddonMenu-2.0/controls/texture.lua
index efb29ec..d0e6905 100644
--- a/libs/LibAddonMenu-2.0/controls/texture.lua
+++ b/libs/LibAddonMenu-2.0/controls/texture.lua
@@ -10,17 +10,16 @@

 --add texture coords support?

-local widgetVersion = 5
+local widgetVersion = 6
 local LAM = LibStub("LibAddonMenu-2.0")
 if not LAM:RegisterWidget("texture", widgetVersion) then return end

 local wm = WINDOW_MANAGER

 function LAMCreateControl.texture(parent, textureData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or textureData.reference)
+	local control = wm:CreateControl(controlName or textureData.reference, parent.scroll or parent, CT_CONTROL)
 	control:SetResizeToFitDescendents(true)
-	control:SetParent(parent.scroll or parent)
-
+
 	local isHalfWidth = textureData.width == "half"
 	if isHalfWidth then
 		control:SetDimensionConstraints(250, 55, 250, 100)
@@ -29,13 +28,13 @@ function LAMCreateControl.texture(parent, textureData, controlName)
 		control:SetDimensionConstraints(510, 30, 510, 100)
 		control:SetDimensions(510, 30)
 	end
-
+
 	control.texture = wm:CreateControl(nil, control, CT_TEXTURE)
 	local texture = control.texture
 	texture:SetAnchor(CENTER)
 	texture:SetDimensions(textureData.imageWidth, textureData.imageHeight)
 	texture:SetTexture(textureData.image)
-
+
 	if textureData.tooltip then
 		texture:SetMouseEnabled(true)
 		--texture.tooltipText = textureData.tooltip
@@ -46,6 +45,6 @@ function LAMCreateControl.texture(parent, textureData, controlName)

 	control.panel = parent.panel or parent	--if this is in a submenu, panel is its parent
 	control.data = textureData
-
+
 	return control
 end
\ No newline at end of file