Moved to folder for Zip generator

Harry Semple [06-05-16 - 23:48]
Moved to folder for Zip generator
Filename
AIResearchGrid.lua
AIResearchGrid.txt
AIResearchGrid.xml
AIResearchGrid/AIResearchGrid.lua
AIResearchGrid/AIResearchGrid.txt
AIResearchGrid/AIResearchGrid.xml
AIResearchGrid/AIresearchGridConfig.lua
AIResearchGrid/Bindings.xml
AIResearchGrid/Language/de.lua
AIResearchGrid/Language/en.lua
AIResearchGrid/Language/fr.lua
AIResearchGrid/Language/ru.lua
AIResearchGrid/Libs/LAM2/LibAddonMenu-2.0.lua
AIResearchGrid/Libs/LAM2/controls/button.lua
AIResearchGrid/Libs/LAM2/controls/checkbox.lua
AIResearchGrid/Libs/LAM2/controls/colorpicker.lua
AIResearchGrid/Libs/LAM2/controls/custom.lua
AIResearchGrid/Libs/LAM2/controls/description.lua
AIResearchGrid/Libs/LAM2/controls/dropdown.lua
AIResearchGrid/Libs/LAM2/controls/editbox.lua
AIResearchGrid/Libs/LAM2/controls/header.lua
AIResearchGrid/Libs/LAM2/controls/panel.lua
AIResearchGrid/Libs/LAM2/controls/slider.lua
AIResearchGrid/Libs/LAM2/controls/submenu.lua
AIResearchGrid/Libs/LAM2/controls/texture.lua
AIResearchGrid/Libs/LibStub/LibStub.lua
AIResearchGrid/README
AIresearchGridConfig.lua
Bindings.xml
Language/de.lua
Language/en.lua
Language/fr.lua
Language/ru.lua
Libs/LAM2/LibAddonMenu-2.0.lua
Libs/LAM2/controls/button.lua
Libs/LAM2/controls/checkbox.lua
Libs/LAM2/controls/colorpicker.lua
Libs/LAM2/controls/custom.lua
Libs/LAM2/controls/description.lua
Libs/LAM2/controls/dropdown.lua
Libs/LAM2/controls/editbox.lua
Libs/LAM2/controls/header.lua
Libs/LAM2/controls/panel.lua
Libs/LAM2/controls/slider.lua
Libs/LAM2/controls/submenu.lua
Libs/LAM2/controls/texture.lua
Libs/LibStub/LibStub.lua
README
diff --git a/AIResearchGrid.lua b/AIResearchGrid.lua
deleted file mode 100644
index fc4e2a7..0000000
--- a/AIResearchGrid.lua
+++ /dev/null
@@ -1,682 +0,0 @@
--- AI Research Grid Addon for Elder Scrolls Online
--- Author: Stormknight/LCAmethyst/CrazyDutchGuy
-
-local _
-AIRG = {}
-
-AIRG.name = "AIResearchGrid"
-AIRG.version = "1.3.4"
-AIRG.initialised = false
-AIRG.processing = false
-
--- Set-up the defaults options for saved variables.
-AIRG.defaults = {
-    data        = {},
-    styles      = {},
-    showMotifs = true,
-}
-
-AIRG.gridAlignments = {
-	grid_base_height = 636,
-	grid_base_width = 760,
-	styleGrid = {
-		num_styles = 30,
-		height = 120,
-		width = 605,
-		icon_height = 30,
-		icon_width = 30,
-		left_align = 160,
-		top_align = 15,
-		row_length = 15,
-		icon_box_height = 37,
-		icon_box_width = 37,
-	},
-}
-
-function AIRG.Initialise(eventCode, addOnName)
-	-- Only initialize our own addon
-	if (AIRG.name ~= addOnName) then return end
-
-    -- Language text
-    AIRG.InitialiseLanguage()
-
-    -- Load the saved variables
-    AIRG.vars = ZO_SavedVars:NewAccountWide("AIRG_SavedVariables", 2, nil, AIRG.defaults)
-
-    -- Register Keybinding
-    ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_AIRG", "Toggle AI Research Grid")
-
-	-- Set-up some variables we'll want to refer to.
-    AIRG.craftNames = {}
-    AIRG.craftNames[CRAFTING_TYPE_BLACKSMITHING]    = "BLACKSMITHING"
-    AIRG.craftNames[CRAFTING_TYPE_CLOTHIER]         = "CLOTHING"
-    AIRG.craftNames[CRAFTING_TYPE_WOODWORKING]      = "WOODWORKING"
-    AIRG.playerName = GetUnitName("player")
-    AIRG.curCharacter = GetUnitName("player")       -- Default the display to the current character
-
-    AIRG.AssignGridTraits()
-    AIRG.AssignStyleLookups()
-
-    -- Query data for THIS character and populate the data matrix with fresh data.
-    --AIRG.PopulateMatrix()
-
-    -- Query data for THIS character for STYLES
-    --AIRG.PopulateStyleData()
-
-    -- UI set-up. Create frames, position labels & buttons etc.
-    AIRG.initUI()
-
-
-    -- REGISTER for events that aren't initialise.
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_STARTED, AIRG.ResearchStarted)
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED, AIRG.ResearchCompleted)
-
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_STYLE_LEARNED, AIRG.StyleLearned)
-
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_PLAYER_ACTIVATED, AIRG.PlayerActivated)
-
-    -- Create the configuration/settings menu.
-    AIRG.CreateConfigMenu()
-
-    AIRG.initialised = true
-end -- AIRG.Initialise
-
-EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_ADD_ON_LOADED, AIRG.Initialise)
-
-
--- SLASH COMMAND FUNCTIONALITY
-function AIRGslash(extra)
-    AIRG.ToggleMainWindow()
-end -- AIRGslash
-
-
-SLASH_COMMANDS["/airg"] = AIRGslash
-
-function AIRG.PlayerActivated()
-        -- somehow somewhere it sometimes happens that the data is not correct completely for whatever reason
-        -- so we force a reload of the current character data when we are actually loaded into the world.
-    	AIRG.PopulateMatrix()
-	AIRG.PopulateStyleData()
-end
-
-function AIRG.ToggleMainWindow()
-    if (AIResearchGrid:IsHidden()) then
-        AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-        SetGameCameraUIMode(true)	        -- Enable mouse pointer
-        AIResearchGrid:SetHidden(false)     -- Display the addon
-        AIRG.OnCharacterSelect()
-    else
-        SetGameCameraUIMode(false)	        -- Enable mouse pointer
-        AIResearchGrid:SetHidden(true)      -- Display the addon
-    end
-end -- AIRG.ToggleMainWindow
-
--- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_STARTED
--- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
-function AIRG.ResearchStarted(eventCode, craftingSkillType, researchLineIndex, traitIndex)
-    AIRG.PopulateMatrix()
-    -- TO DO: If it's visible, invoke a redisplay
-    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-end -- AIRG.ResearchStarted
-
--- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED
--- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
-function AIRG.ResearchCompleted()
-    AIRG.PopulateMatrix()
-    -- TO DO: If it's visible, invoke a redisplay
-    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-end -- AIRG.ResearchEnded
-
-function AIRG.StyleLearned(eventCode, styleIndex)
-    AIRG.PopulateStyleData()
-    AIRG.DisplayStyles()
-end -- AIRG.StyleLearned
-
--- Invoked from AIRG.Initialise but lengthy so in it's own function to not clutter Initialise
-function AIRG.initUI()
-    -- Some local variable declaration
-    local i, j      -- used in for loops
-    local thisTrait, tType, tDesc, rowNum, charName
-    -- Initialise a table to hold all the lua generated components
-    AIRG.UI = {}
-    -- Set the main window title
-    AIRG.UI.WindowTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowTitle", AIResearchGrid, CT_LABEL)
-    AIRG.UI.WindowTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 0)
-    AIRG.UI.WindowTitle:SetFont("ZoFontAnnounceMedium")
-    AIRG.UI.WindowTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-    AIRG.UI.WindowTitle:SetText("|c8080ffAI|r RESEARCH GRID")
-    -- Set the main window subtitle
-    AIRG.UI.WindowSubTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowSubTitle", AIResearchGrid, CT_LABEL)
-    AIRG.UI.WindowSubTitle:SetAnchor(LEFT, AIRG.UI.WindowTitle, RIGHT, 10, 0)
-    AIRG.UI.WindowSubTitle:SetFont("ZoFontAnnounceMedium")
-    AIRG.UI.WindowSubTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-    AIRG.UI.WindowSubTitle:SetColor(0, 1, 0, 1);    -- green
-    AIRG.UI.WindowSubTitle:SetText("")
-    -- Nice little line under the main title
-    AIRG.UI.TopDivider = WINDOW_MANAGER:CreateControl("AIResearchGridTopDivider", AIResearchGrid, CT_TEXTURE)
-    AIRG.UI.TopDivider:SetDimensions(760, 5)
-    AIRG.UI.TopDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 32)
-    AIRG.UI.TopDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
-    -- Nice little line under the grid
-    AIRG.UI.BottomDivider = WINDOW_MANAGER:CreateControl("AIResearchGridBottomDivider", AIResearchGrid, CT_TEXTURE)
-    AIRG.UI.BottomDivider:SetDimensions(760, 5)
-    AIRG.UI.BottomDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 636)
-    AIRG.UI.BottomDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
-    AIRG.UI.BottomDivider:SetHidden(not AIRG.vars.showMotifs)
-    -- CREATE BUTTON FOR CLOSE ADDON AT TOP_RIGHT
-    AIRG.UI.btnCloseAddonFrame = WINDOW_MANAGER:CreateControl("AIResearchGridButtonCloseAddon", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnCloseAddonFrame:SetDimensions(28, 28)
-    AIRG.UI.btnCloseAddonFrame:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, 0 , 0)
-    AIRG.UI.btnCloseAddonFrame:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnCloseAddonFrame:SetMouseOverBlendMode(0)
---    AIRG.UI.btnCloseAddonFrame:SetHidden(false)
-    AIRG.UI.btnCloseAddonFrame:SetEnabled(true)
---    AIRG.UI.btnCloseAddonFrame:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnCloseAddonFrame:SetNormalTexture("/esoui/art/buttons/clearslot_down.dds")
-    AIRG.UI.btnCloseAddonFrame:SetMouseOverTexture("/esoui/art/buttons/clearslot_up.dds")
-    AIRG.UI.btnCloseAddonFrame:SetHandler("OnClicked", function(self) AIRG.ToggleMainWindow() end)
-    -- CREATE the DROPDOWN BOX for CHARACTER SELECT
-    -- Uses code based on example from Seerah
-    AIRG.UI.charDropdown = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridDropdownCharacter", AIResearchGrid, "ZO_StatsDropdownRow")
-    AIRG.UI.charDropdown:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, -32, 0)
-    AIRG.UI.charDropdown:GetNamedChild("Dropdown"):SetWidth(200)
-    AIRG.UI.charDropdown.dropdown:SetSelectedItem(AIRG.curCharacter)  -- Set the current character as selected
-    local function OnItemSelect(_, choiceText, choice)  --this is the callback function for when an item gets selected in the dropdown
-        AIRG.OnCharacterSelect(choiceText)
-    end
-    for charName, _ in pairs(AIRG.vars.data) do
-        local entry = AIRG.UI.charDropdown.dropdown:CreateItemEntry(charName, OnItemSelect)
-        AIRG.UI.charDropdown.dropdown:AddItem(entry)
-    end
-    -- PEOPLE ICON NEXT TO THE DROPDOWN BOX
---    AIRG.UI.PeopleIcon = WINDOW_MANAGER:CreateControl("AIResearchGridPeopleIcon", AIResearchGrid, CT_TEXTURE)
---    AIRG.UI.PeopleIcon:SetDimensions(40, 32)
---    AIRG.UI.PeopleIcon:SetAnchor(TOPRIGHT, AIRG.UI.charDropdown, TOPLEFT, 0, 0)
---    AIRG.UI.PeopleIcon:SetTexture("/esoui/art/contacts/tabicon_friends_down.dds")
-    -- CREATE BUTTON FOR PROFESSION: BLACKSMITHING
-    AIRG.UI.btnBlacksmithing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonBlacksmithing", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnBlacksmithing:SetDimensions(48, 48)
-    AIRG.UI.btnBlacksmithing:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 8 , 44)
-    AIRG.UI.btnBlacksmithing:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnBlacksmithing:SetMouseOverBlendMode(0)
-    AIRG.UI.btnBlacksmithing:SetHidden(false)
-    AIRG.UI.btnBlacksmithing:SetEnabled(true)
-    AIRG.UI.btnBlacksmithing:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnBlacksmithing:SetNormalTexture("/esoui/art/icons/ability_smith_007.dds")
-    AIRG.UI.btnBlacksmithing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnBlacksmithing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_BLACKSMITHING) end)
-    -- CREATE BUTTON FOR PROFESSION: WOODWORKING
-    AIRG.UI.btnWoodworking = WINDOW_MANAGER:CreateControl("AIResearchGridButtonWoodworking", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnWoodworking:SetDimensions(48, 48)
-    AIRG.UI.btnWoodworking:SetAnchor(TOPLEFT, AIRG.UI.btnBlacksmithing, TOPRIGHT, 12 , 0)
-    AIRG.UI.btnWoodworking:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnWoodworking:SetMouseOverBlendMode(0)
-    AIRG.UI.btnWoodworking:SetHidden(false)
-    AIRG.UI.btnWoodworking:SetEnabled(true)
-    AIRG.UI.btnWoodworking:SetClickSound(SOUNDS.BLACKSMITH_EXTRACTED_BOOSTER)
-    AIRG.UI.btnWoodworking:SetNormalTexture("/esoui/art/icons/ability_tradecraft_009.dds")
-    AIRG.UI.btnWoodworking:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnWoodworking:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_WOODWORKING) end)
-    -- CREATE BUTTON FOR PROFESSION: CLOTHING
-    AIRG.UI.btnClothing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonClothing", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnClothing:SetDimensions(48, 48)
-    AIRG.UI.btnClothing:SetAnchor(TOPLEFT, AIRG.UI.btnWoodworking, TOPRIGHT, 12 , 0)
-    AIRG.UI.btnClothing:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnClothing:SetMouseOverBlendMode(0)
-    AIRG.UI.btnClothing:SetHidden(false)
-    AIRG.UI.btnClothing:SetEnabled(true)
-    AIRG.UI.btnClothing:SetClickSound(SOUNDS.CLOTHIER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnClothing:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
-    AIRG.UI.btnClothing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnClothing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_CLOTHIER) end)
-
-    -- BUILD THE TRAIT LABELS ON THE LEFT-SIDE using built-in language strings
-    AIRG.UI.rowLabels = {}
-    for thisTrait, j in pairs(AIRG.gridTraits) do
-        AIRG.UI.rowLabels[j] = WINDOW_MANAGER:CreateControl("AIResearchGridRowLabel" .. tostring(j), AIResearchGrid, CT_LABEL)
-        AIRG.UI.rowLabels[j]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 28*j + 70)
-        AIRG.UI.rowLabels[j]:SetText(GetString("SI_ITEMTRAITTYPE",thisTrait))       -- This is the text displayed on the screen as it's a label
-        AIRG.UI.rowLabels[j]:SetDimensions(180, 24)
-        AIRG.UI.rowLabels[j]:SetFont("ZoFontGame")
-        AIRG.UI.rowLabels[j]:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-        AIRG.UI.rowLabels[j]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.rowLabels[j]:SetMouseEnabled(true)
-        AIRG.UI.rowLabels[j]:SetHandler("OnMouseEnter", function (self)
-                            ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
-                        end)
-        AIRG.UI.rowLabels[j]:SetHandler("OnMouseExit", function (self)
-                            ZO_Tooltips_HideTextTooltip()
-                        end)
-    end
-    -- Now add tooltip text to the row labels.
-    -- The tooltip functionality is automatic as part of the label control.
-    for j = 1, 9 do
-        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,1,j) -- weapons
-        rowNum = AIRG.gridTraits[tType]
-        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
-        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,9,j) -- armour
-        rowNum = AIRG.gridTraits[tType]
-        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
-    end
-    -- BUILD THE COLUMNS & GRID
-    -- Determine the maximum number of item types across all three professions. This is currently always 14
-    AIRG.maxColumns= math.max(GetNumSmithingResearchLines(CRAFTING_TYPE_BLACKSMITHING),
-            GetNumSmithingResearchLines(CRAFTING_TYPE_CLOTHIER),
-            GetNumSmithingResearchLines(CRAFTING_TYPE_WOODWORKING))
-    AIRG.UI.columnButtons = {}
-    AIRG.UI.gridButtons = {}
-    AIRG.UI.columnFooters = {}
-    for i = 1, AIRG.maxColumns do
-        -- BUILD THE COLUMN BUTTONS
-        AIRG.UI.columnButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridHeaderButton" .. tostring(i), AIResearchGrid, CT_BUTTON)
-        AIRG.UI.columnButtons[i]:SetDimensions(36, 36)
-        AIRG.UI.columnButtons[i]:SetState(BSTATE_NORMAL)
-        AIRG.UI.columnButtons[i]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 40*i + 150, 55)
-        AIRG.UI.columnButtons[i]:SetHidden(true)
-        AIRG.UI.columnButtons[i]:SetEnabled(true)
-        AIRG.UI.columnButtons[i]:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-        AIRG.UI.columnButtons[i].text = i
-        AIRG.UI.columnButtons[i]:SetHandler("OnMouseEnter", function (self)
-                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.text)
-                                            end)
-        AIRG.UI.columnButtons[i]:SetHandler("OnMouseExit", function (self)
-                                                ZO_Tooltips_HideTextTooltip()
-                                            end)
-        -- BUILD THE GRID
-        -- There are a total of 18 traits possible. 9 armour and 9 weapon (Infused, Training and Nirnhoned on both)
-        AIRG.UI.gridButtons[i] = {}
-        for j = 1, 18 do
-            AIRG.UI.gridButtons[i][j] = WINDOW_MANAGER:CreateControl("AIResearchGridGridButton" .. tostring(i) .. "x" .. tostring(j), AIResearchGrid, CT_TEXTURE)
-            AIRG.UI.gridButtons[i][j]:SetDimensions(24, 24)
-            AIRG.UI.gridButtons[i][j]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 28*j -20)
-            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
-            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
-            AIRG.UI.gridButtons[i][j]:SetHidden(false)
-            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)
-            -- Following tooltip code uses ideas contributed by Krysstof
-            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseEnter", function (self)
-                        if (self.tooltipText > 0) then      -- Check the item is being researched and has a timestamp
-					        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
-                            local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
-					        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
-    						-- loop with "registerforupdate" once per second
-    						EVENT_MANAGER:RegisterForUpdate(self.name, 1000, function()
-    						        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
-                                    local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
-    						        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
-    						    end)
-    				    end
-					end)
-            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseExit", function (self)
-						-- unregister the update event or it keeps on displaying
-						EVENT_MANAGER:UnregisterForUpdate(self.name)
-						ZO_Tooltips_HideTextTooltip()
-					end)
-        end
-        -- BUILD THE COLUMN FOOTERS
-        AIRG.UI.columnFooters[i] = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterLabel" .. tostring(i), AIResearchGrid, CT_LABEL)
-        AIRG.UI.columnFooters[i]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 516)
-        AIRG.UI.columnFooters[i]:SetDimensions(36, 24)
-        AIRG.UI.columnFooters[i]:SetFont("ZoFontGame")
-        AIRG.UI.columnFooters[i]:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.columnFooters[i]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.columnFooters[i]:SetColor(1, 1, 0.4, 1);    -- faded yellow
-    end
-    -- BUILD LABEL FOR COLUMN FOOTER "TRAIT LINE"
-    AIRG.UI.columnFooterTitle = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterTitleLabel", AIResearchGrid, CT_LABEL)
-    AIRG.UI.columnFooterTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 606)
-    AIRG.UI.columnFooterTitle:SetDimensions(180, 24)
-    AIRG.UI.columnFooterTitle:SetFont("ZoFontGame")
-    AIRG.UI.columnFooterTitle:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-    AIRG.UI.columnFooterTitle:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-    AIRG.UI.columnFooterTitle:SetColor(1, 1, 0.4, 1);       -- faded yellow
---    AIRG.UI.columnFooterTitle:SetText(GetString(SI_SMITHING_RESEARCH_LINE_HEADER))
-    AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS))
-
-    -- BUILD THE MOTIF ICONS ACROSS THE BOTTOM
-    -- Note that for now, we're just setting up 15 icons and stuff is configured manually
-    -- but we can fix it later. It's not like it's going to have an overhead on processing. :)
-    -- It's set-up inside a container frame to make hiding or showing the whole lot simpler.
-    AIRG.UI.motifSection = WINDOW_MANAGER:CreateControl("AIResearchMotifSection", AIResearchGrid, CT_CONTROL)
-    AIRG.UI.motifSection:SetDimensions(AIRG.gridAlignments.grid_base_width, AIRG.gridAlignments.styleGrid.height)
-    AIRG.UI.motifSection:SetAnchor(BOTTOMLEFT, AIResearchGrid, BOTTOMLEFT, 0, 0)
-    AIRG.UI.motifSection:SetHidden(not AIRG.vars.showMotifs)
-    AIResearchGrid:SetHeight(AIRG.vars.showMotifs and AIRG.gridAlignments.grid_base_height + AIRG.gridAlignments.styleGrid.height or AIRG.gridAlignments.grid_base_height)
-    AIRG.UI.motifButtons = {}
-	local currentColumn = 0
-	local currentRow = 0
-    for i = 1, AIRG.gridAlignments.styleGrid.num_styles do
-		currentColumn = currentColumn + 1
-        AIRG.UI.motifButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridMotifButton" .. tostring(i), AIRG.UI.motifSection, CT_TEXTURE)
-        AIRG.UI.motifButtons[i]:SetDimensions(AIRG.gridAlignments.styleGrid.icon_width, AIRG.gridAlignments.styleGrid.icon_height)
-		if currentColumn > AIRG.gridAlignments.styleGrid.row_length then
-			currentRow = currentRow + 1
-			currentColumn = currentColumn - AIRG.gridAlignments.styleGrid.row_length
-		end
-		local yVal = AIRG.gridAlignments.styleGrid.top_align + (AIRG.gridAlignments.styleGrid.icon_box_height * currentRow)
-		local xVal = AIRG.gridAlignments.styleGrid.icon_box_width * currentColumn + AIRG.gridAlignments.styleGrid.left_align
-        AIRG.UI.motifButtons[i]:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, xVal, yVal)
-        AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-        AIRG.UI.motifButtons[i]:SetMouseEnabled(true)
-        j = AIRG.styleLookupValue[i]
-        tDesc ,_,_,_,_ = GetSmithingStyleItemInfo( AIRG.styleLookupItem[i] )
-        AIRG.UI.motifButtons[i].tooltipText = zo_strformat("<<t:1>>\n<<t:2>>", GetString("SI_ITEMSTYLE",j), tDesc)
-        AIRG.UI.motifButtons[i]:SetHandler("OnMouseEnter", function (self)
-                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
-                                            end)
-        AIRG.UI.motifButtons[i]:SetHandler("OnMouseExit", function (self)
-                                                ZO_Tooltips_HideTextTooltip()
-                                            end)
-    end
-    -- BUILD LABEL FOR STYLES
-    AIRG.UI.StyleLabel = WINDOW_MANAGER:CreateControl("AIResearchStylelabel", AIRG.UI.motifSection, CT_LABEL)
-    AIRG.UI.StyleLabel:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 5, 14)
-    AIRG.UI.StyleLabel:SetText(GetString(SI_SMITHING_HEADER_STYLE))
-    AIRG.UI.StyleLabel:SetDimensions(180, 24)
-    AIRG.UI.StyleLabel:SetFont("ZoFontGame")
-    AIRG.UI.StyleLabel:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-end -- AIRG.initUI
-
--- User has clicked on one of the profession buttons
--- or we just want to refresh the display with current data
-function AIRG.OnCraftSelected(_,thisCraft)
-    if (thisCraft == nil) then
-        if (AIRG.curCraft == nil) then
-            return
-        else
-            thisCraft = AIRG.curCraft
-        end
-    end
-    AIRG.UI.WindowSubTitle:SetText(AIRG.craftNames[thisCraft])
-    local i,j
-    local tType,tDesc,tKnown,tRemain,rowNum,traitCount
-    local maxLines = GetNumSmithingResearchLines(thisCraft) -- the number of columns for this profession
-    AIRG.curCraft = thisCraft
-    for i = 1, AIRG.maxColumns do
-        -- "blank" the grid
-        for j = 1, 18 do
-            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
-            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
-            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)    -- effectively disable tooltip for this grid item.
-        end
-        if (i > maxLines) then
-            AIRG.UI.columnButtons[i]:SetHidden(true)
-            AIRG.UI.columnFooters[i]:SetText("")
-        else
-            local name, icon, _, _ = GetSmithingResearchLineInfo(thisCraft, i)  -- Get info on that specific item
-            AIRG.UI.columnButtons[i]:SetNormalTexture(icon)
-            AIRG.UI.columnButtons[i]:SetHidden(false)
-            AIRG.UI.columnButtons[i].text = name
-
-            traitCount = 0
-            for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
-                AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
-                if (tKnown == -1) then       -- Trait is known
-                    AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
-                    traitCount = traitCount + 1
-                elseif (tKnown > 0) then   -- Trait is being researched
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/tutorial/timer_icon.dds")
-                    if (tKnown < GetTimeStamp()) then   -- This is on another character and the timer has completed.
-                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
-                        traitCount = traitCount + 1
-                    else
-                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.5, 0.5, 1, 1)   -- Blue
-                        AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
-                    end
-                else                        -- Trait is NOT known
-                    AIRG.UI.gridButtons[i][rowNum]:SetColor(1, 0.2, 0.2, 1)   -- Red
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/buttons/decline_up.dds")
-                end
-            end
-            if (traitCount > 0) then
-                AIRG.UI.columnFooters[i]:SetText(traitCount)
-            else
-                AIRG.UI.columnFooters[i]:SetText("")
-            end
-        end
-    end
-end -- AIRG:OnCraftSelected
-
--- Invoked when the user selected a character from the dropdown box
-function AIRG.OnCharacterSelect(charName)
-    if (charName == nil) then
-    else
-        AIRG.curCharacter = charName
-    end
-    AIRG.DisplayStyles()
-    AIRG.OnCraftSelected()
-end -- AIRG.OnCharacterSelect
-
--- Deletes data for the named character from the saved data and removes them from the dropdown box.
-function AIRG.DeleteCharacter(charName)
-    -- Can't delete the current character
-    if (charName == AIRG.playerName) then
-        d(AIRG.L["DeleteFalse"])
-    else
-        if (AIRG.vars.data[charName] ~= nil) then
-            AIRG.vars.data[charName] = nil
-            d(AIRG.L["DeleteTrue"] .. charName)
-        end
-        if (AIRG.vars.styles[charName] ~= nil) then
-            AIRG.vars.styles[charName] = nil
-        end
-    end
-end -- AIRG.DeleteCharacter
-
--- This function cycles through all three professions and populates the data matrix for THIS character.
--- This is carried out when the addon loasd to ensure the current character data is up-to-date.
--- The "if" logic in this function guesses at which profession should be default to display as the one with most research in.
-function AIRG.PopulateMatrix()
-    local curCount = 0
-    local thisCount
-    AIRG.vars.data[AIRG.playerName] = {}    -- create a table for this character's matrix
-    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_BLACKSMITHING)
-    if (thisCount > curCount) then
-        AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
-        curCount = thisCount
-    end
-    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_CLOTHIER)
-    if (thisCount > curCount) then
-        AIRG.curCraft = CRAFTING_TYPE_CLOTHIER
-        curCount = thisCount
-    end
-    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_WOODWORKING)
-    if (thisCount > curCount) then
-        AIRG.curCraft = CRAFTING_TYPE_WOODWORKING
-        curCount = thisCount
-    end
-
-	if (AIRG.curCraft == nil) then
-		AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
-	end
-end -- AIRG.PopulateMatrix
-
--- Lookup the style data for the current character and send it to saved vars.
-function AIRG.PopulateStyleData()
-    AIRG.vars.styles[AIRG.playerName] = {}    -- create a table for this character's matrix
-    local i, j
-    for i = 1, AIRG.gridAlignments.styleGrid.num_styles do
-        j = AIRG.styleLookupItem[i]
-        AIRG.vars.styles[AIRG.playerName][i] = IsSmithingStyleKnown(j, 1) --patternIndex set to 1, temporary workaround for changes introduced in Update 4
-    end
-end -- AIRG.PopulateStyleData
-
--- Set the icon highlights for the currently selected character
-function AIRG.DisplayStyles()
-    local i
-    if (AIRG.vars.styles[AIRG.curCharacter] == nil) then
-        for i = 1, 30 do
-            AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-            AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
-        end
-    else
-        for i = 1, 30 do
-            if (AIRG.vars.styles[AIRG.curCharacter][i]) then
-                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "down.dds")
-                AIRG.UI.motifButtons[i]:SetColor(0.7, 1, 0.7, 1)   -- Green
-            else
-                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-                AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
-            end
-        end
-    end
-end -- AIRG.DisplayStyles()
-
--- Look up all the data on this profession and commit to saved variables for this character.
--- TO DO: At some point, get clever with storing the timestamp for when research will be complete
-function AIRG.CreateDataMatrix(thisCraft)
-    local i, j
-    local tType, tKnown, tRemain, rowNum, tTargetStamp
-    local rCount = 0
-    local maxLines = GetNumSmithingResearchLines(thisCraft)     -- the number of columns for this profession
-    AIRG.vars.data[AIRG.playerName][thisCraft] = {}             -- create a table for this profession
-    -- Cycle through items for this profession
-    for i = 1, maxLines do
-        AIRG.vars.data[AIRG.playerName][thisCraft][i] = {}      -- create a table for this item
-        -- Cycle through the traits for this item
-        for j = 1, 9 do
-            tType,_,tKnown = GetSmithingResearchLineTraitInfo(thisCraft,i,j)
-            _,tRemain = GetSmithingResearchLineTraitTimes(thisCraft,i,j)
-            rowNum = AIRG.gridTraits[tType]
-
-            if (tKnown) then
-                AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = -1       -- this trait is known
-                rCount = rCount + 1
-            else
-                if (tRemain) then
-                    tTargetStamp = GetTimeStamp() + tRemain
-                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = tTargetStamp   -- this trait is being currently researched
-                    -- The value we are setting this to is the timestamp for when the research will be complete.
-                else
-                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = 0   -- this trait is NOT known
-                end
-            end
-        end
-    end
-    return rCount       -- the total number of traits already researched in this profession
-end -- AIRG.CreateDataMatrix
-
-function AIRG.AssignGridTraits()
-    -- Translates the traitType to the correct ROW of the grid
-    AIRG.gridTraits = {}
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_POWERED] = 1
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = 2
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = 3
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = 4
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = 5
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = 6
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = 7
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = 8
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = 9
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_STURDY] = 10
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = 11
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = 12
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = 13
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = 14
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = 15
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = 16
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = 17
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = 18
-end -- AIRG.AssignGridTraits
-
-function AIRG.AssignStyleLookups()
-    -- Lookup the correct icon for the style
-    AIRG.styleLookupIcons = {}
-    AIRG.styleLookupIcons[1] = "ESOUI/art/charactercreate/charactercreate_altmericon_"
-    AIRG.styleLookupIcons[2] = "ESOUI/art/charactercreate/charactercreate_argonianicon_"
-    AIRG.styleLookupIcons[3] = "ESOUI/art/charactercreate/charactercreate_bosmericon_"
-    AIRG.styleLookupIcons[4] = "ESOUI/art/charactercreate/charactercreate_bretonicon_"
-    AIRG.styleLookupIcons[5] = "ESOUI/art/charactercreate/charactercreate_dunmericon_"
-    AIRG.styleLookupIcons[6] = "ESOUI/art/charactercreate/charactercreate_khajiiticon_"
-    AIRG.styleLookupIcons[7] = "ESOUI/art/charactercreate/charactercreate_nordicon_"
-    AIRG.styleLookupIcons[8] = "ESOUI/art/charactercreate/charactercreate_orcicon_"
-    AIRG.styleLookupIcons[9] = "ESOUI/art/charactercreate/charactercreate_redguardicon_"
-    AIRG.styleLookupIcons[10] = "ESOUI/art/charactercreate/charactercreate_imperialicon_"
-    AIRG.styleLookupIcons[11] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[12] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[13] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[14] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[15] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[16] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[17] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[18] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[19] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[20] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[21] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[22] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[23] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[24] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[25] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[26] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[27] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[28] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[29] = "ESOUI/art/progression/progression_indexicon_weapons_"
-	AIRG.styleLookupIcons[30] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    -- Translate the icon position to the in-game type. Used for text look-up
-    AIRG.styleLookupValue = {}
-    AIRG.styleLookupValue[1] = ITEMSTYLE_RACIAL_HIGH_ELF
-    AIRG.styleLookupValue[2] = ITEMSTYLE_RACIAL_ARGONIAN
-    AIRG.styleLookupValue[3] = ITEMSTYLE_RACIAL_WOOD_ELF
-    AIRG.styleLookupValue[4] = ITEMSTYLE_RACIAL_BRETON
-    AIRG.styleLookupValue[5] = ITEMSTYLE_RACIAL_DARK_ELF
-    AIRG.styleLookupValue[6] = ITEMSTYLE_RACIAL_KHAJIIT
-    AIRG.styleLookupValue[7] = ITEMSTYLE_RACIAL_NORD
-    AIRG.styleLookupValue[8] = ITEMSTYLE_RACIAL_ORC
-    AIRG.styleLookupValue[9] = ITEMSTYLE_RACIAL_REDGUARD
-    AIRG.styleLookupValue[10] = ITEMSTYLE_RACIAL_IMPERIAL
-    AIRG.styleLookupValue[11] = ITEMSTYLE_AREA_ANCIENT_ELF
-    AIRG.styleLookupValue[12] = ITEMSTYLE_AREA_REACH
-    AIRG.styleLookupValue[13] = ITEMSTYLE_ENEMY_PRIMITIVE
-    AIRG.styleLookupValue[14] = ITEMSTYLE_ENEMY_DAEDRIC
-	AIRG.styleLookupValue[15] = ITEMSTYLE_AREA_DWEMER
-	AIRG.styleLookupValue[16] = ITEMSTYLE_GLASS
-	AIRG.styleLookupValue[17] = ITEMSTYLE_AREA_XIVKYN
-	AIRG.styleLookupValue[18] = ITEMSTYLE_AREA_AKAVIRI
-	AIRG.styleLookupValue[19] = ITEMSTYLE_UNDAUNTED
-	AIRG.styleLookupValue[20] = ITEMSTYLE_AREA_ANCIENT_ORC
-	AIRG.styleLookupValue[21] = ITEMSTYLE_DEITY_TRINIMAC
-	AIRG.styleLookupValue[22] = ITEMSTYLE_DEITY_MALACATH
-	AIRG.styleLookupValue[23] = ITEMSTYLE_ORG_OUTLAW
-	AIRG.styleLookupValue[24] = ITEMSTYLE_ALLIANCE_ALDMERI
-	AIRG.styleLookupValue[25] = ITEMSTYLE_ALLIANCE_DAGGERFALL
-	AIRG.styleLookupValue[26] = ITEMSTYLE_ALLIANCE_EBONHEART
-	AIRG.styleLookupValue[27] = ITEMSTYLE_AREA_SOUL_SHRIVEN
-	AIRG.styleLookupValue[28] = ITEMSTYLE_ORG_ABAHS_WATCH
-	AIRG.styleLookupValue[29] = ITEMSTYLE_ORG_THIEVES_GUILD
-	AIRG.styleLookupValue[30] = ITEMSTYLE_ORG_ASSASSINS
-    -- This is a bit of a hack, but only because of the way ESO uses Style Items with different index to styles.
-    AIRG.styleLookupItem = {}
-    AIRG.styleLookupItem[1] = 8     -- Altmer       		= Adamantite
-    AIRG.styleLookupItem[2] = 7     -- Argonian     		= Flint
-    AIRG.styleLookupItem[3] = 9     -- Bosmer       		= Bone
-    AIRG.styleLookupItem[4] = 2     -- Breton       		= Molybdenum
-    AIRG.styleLookupItem[5] = 5     -- Dunmer       		= Obsidian
-    AIRG.styleLookupItem[6] = 10    -- Khajit       		= Moonstone
-    AIRG.styleLookupItem[7] = 6     -- Nord         		= Corundum
-    AIRG.styleLookupItem[8] = 4     -- Orc          		= Manganese
-    AIRG.styleLookupItem[9] = 3     -- Redguard     		= Starmetal
-    AIRG.styleLookupItem[10] = 35   -- Imperial     		= Nickel
-    AIRG.styleLookupItem[11] = 16   -- Ancient Elf  		= Palladium
-    AIRG.styleLookupItem[12] = 18   -- Barbarian    		= Copper
-    AIRG.styleLookupItem[13] = 20   -- Primal       		= Argentum
-    AIRG.styleLookupItem[14] = 21   -- Daedric      		= Daedra Heart
-	AIRG.styleLookupItem[15] = 15   -- Dwemer       		= Dwemer Frame
-	AIRG.styleLookupItem[16] = 29   -- Glass     			= Malachite
-	AIRG.styleLookupItem[17] = 30   -- Xivkyn  				= Charcoal of Remorse
-	AIRG.styleLookupItem[18] = 34   -- Akaviri      		= Gold Scale
-	AIRG.styleLookupItem[19] = 27   -- Mercenary    		= Laurels
-	AIRG.styleLookupItem[20] = 23   -- Ancient Orc  		= Casserite
-	AIRG.styleLookupItem[21] = 22   -- Trinimac     		= Auric Tusk
-	AIRG.styleLookupItem[22] = 14   -- Malacath     		= Potash
-	AIRG.styleLookupItem[23] = 48   -- Outlaw      			= Rogue's Soot
-	AIRG.styleLookupItem[24] = 26   -- Aldmeri Dominion     = Eagle Feather
-	AIRG.styleLookupItem[25] = 24   -- Daggerfall Covenant  = Lion Fang
-	AIRG.styleLookupItem[26] = 25   -- Ebonheart Pact      	= Dragon Scute
-	AIRG.styleLookupItem[27] = 31   -- Soul Shriven      	= Azure Plasm
-	AIRG.styleLookupItem[28] = 42   -- Abah's Watch      	= Polished Shilling
-	AIRG.styleLookupItem[29] = 12   -- Thieves' Guild      	= Fine Chalk
-	AIRG.styleLookupItem[30] = 47   -- Assassin's League    = Tainted Blood
-end -- AIRG.AssignStyleLookups
-
--- EOF
diff --git a/AIResearchGrid.txt b/AIResearchGrid.txt
deleted file mode 100644
index 1e406d2..0000000
--- a/AIResearchGrid.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-## Title: |cFFFFB0Research Grid|r v2.3 by |c00C000CrazyDutchGuy|r
-## APIVersion: 100010
-## Version: 2.3
-## Author: Stormknight & CrazyDutchGuy
-## OptionalDependsOn: LibAddonMenu-2.0
-## SavedVariables: AIRG_SavedVariables
-## Description: Allows you to quickly and easily see which traits your characters have researched for Blacksmithing, Clothing & Woodworking, wherever you are in the world.
-
-Libs/LibStub/LibStub.lua
-Libs/LAM2/LibAddonMenu-2.0.lua
-Libs/LAM2/controls/panel.lua
-Libs\LAM2/controls/header.lua
-Libs\LAM2/controls/checkbox.lua
-Libs\LAM2/controls/dropdown.lua
-Libs\LAM2/controls/button.lua
-Libs\LAM2/controls/description.lua
-
-AIResearchGrid.lua
-AIResearchGridConfig.lua
-AIResearchGrid.xml
-Bindings.xml
-
-Language/$(language).lua
\ No newline at end of file
diff --git a/AIResearchGrid.xml b/AIResearchGrid.xml
deleted file mode 100644
index 520c0c5..0000000
--- a/AIResearchGrid.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<GuiXml>
-    <Controls>
-        <TopLevelControl name="AIResearchGrid" mouseEnabled="true" movable="true" clampedToScreen="true" hidden="true">
-            <Dimensions x="760" y="756" />
-            <Anchor point="CENTER" />
-            <Controls>
-
-                <Backdrop name="$(parent)BG" inherits="ZO_DefaultBackdrop" />
-
-            </Controls>
-        </TopLevelControl>
-    </Controls>
-</GuiXml>
\ No newline at end of file
diff --git a/AIResearchGrid/AIResearchGrid.lua b/AIResearchGrid/AIResearchGrid.lua
new file mode 100644
index 0000000..fc4e2a7
--- /dev/null
+++ b/AIResearchGrid/AIResearchGrid.lua
@@ -0,0 +1,682 @@
+-- AI Research Grid Addon for Elder Scrolls Online
+-- Author: Stormknight/LCAmethyst/CrazyDutchGuy
+
+local _
+AIRG = {}
+
+AIRG.name = "AIResearchGrid"
+AIRG.version = "1.3.4"
+AIRG.initialised = false
+AIRG.processing = false
+
+-- Set-up the defaults options for saved variables.
+AIRG.defaults = {
+    data        = {},
+    styles      = {},
+    showMotifs = true,
+}
+
+AIRG.gridAlignments = {
+	grid_base_height = 636,
+	grid_base_width = 760,
+	styleGrid = {
+		num_styles = 30,
+		height = 120,
+		width = 605,
+		icon_height = 30,
+		icon_width = 30,
+		left_align = 160,
+		top_align = 15,
+		row_length = 15,
+		icon_box_height = 37,
+		icon_box_width = 37,
+	},
+}
+
+function AIRG.Initialise(eventCode, addOnName)
+	-- Only initialize our own addon
+	if (AIRG.name ~= addOnName) then return end
+
+    -- Language text
+    AIRG.InitialiseLanguage()
+
+    -- Load the saved variables
+    AIRG.vars = ZO_SavedVars:NewAccountWide("AIRG_SavedVariables", 2, nil, AIRG.defaults)
+
+    -- Register Keybinding
+    ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_AIRG", "Toggle AI Research Grid")
+
+	-- Set-up some variables we'll want to refer to.
+    AIRG.craftNames = {}
+    AIRG.craftNames[CRAFTING_TYPE_BLACKSMITHING]    = "BLACKSMITHING"
+    AIRG.craftNames[CRAFTING_TYPE_CLOTHIER]         = "CLOTHING"
+    AIRG.craftNames[CRAFTING_TYPE_WOODWORKING]      = "WOODWORKING"
+    AIRG.playerName = GetUnitName("player")
+    AIRG.curCharacter = GetUnitName("player")       -- Default the display to the current character
+
+    AIRG.AssignGridTraits()
+    AIRG.AssignStyleLookups()
+
+    -- Query data for THIS character and populate the data matrix with fresh data.
+    --AIRG.PopulateMatrix()
+
+    -- Query data for THIS character for STYLES
+    --AIRG.PopulateStyleData()
+
+    -- UI set-up. Create frames, position labels & buttons etc.
+    AIRG.initUI()
+
+
+    -- REGISTER for events that aren't initialise.
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_STARTED, AIRG.ResearchStarted)
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED, AIRG.ResearchCompleted)
+
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_STYLE_LEARNED, AIRG.StyleLearned)
+
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_PLAYER_ACTIVATED, AIRG.PlayerActivated)
+
+    -- Create the configuration/settings menu.
+    AIRG.CreateConfigMenu()
+
+    AIRG.initialised = true
+end -- AIRG.Initialise
+
+EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_ADD_ON_LOADED, AIRG.Initialise)
+
+
+-- SLASH COMMAND FUNCTIONALITY
+function AIRGslash(extra)
+    AIRG.ToggleMainWindow()
+end -- AIRGslash
+
+
+SLASH_COMMANDS["/airg"] = AIRGslash
+
+function AIRG.PlayerActivated()
+        -- somehow somewhere it sometimes happens that the data is not correct completely for whatever reason
+        -- so we force a reload of the current character data when we are actually loaded into the world.
+    	AIRG.PopulateMatrix()
+	AIRG.PopulateStyleData()
+end
+
+function AIRG.ToggleMainWindow()
+    if (AIResearchGrid:IsHidden()) then
+        AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+        SetGameCameraUIMode(true)	        -- Enable mouse pointer
+        AIResearchGrid:SetHidden(false)     -- Display the addon
+        AIRG.OnCharacterSelect()
+    else
+        SetGameCameraUIMode(false)	        -- Enable mouse pointer
+        AIResearchGrid:SetHidden(true)      -- Display the addon
+    end
+end -- AIRG.ToggleMainWindow
+
+-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_STARTED
+-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
+function AIRG.ResearchStarted(eventCode, craftingSkillType, researchLineIndex, traitIndex)
+    AIRG.PopulateMatrix()
+    -- TO DO: If it's visible, invoke a redisplay
+    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+end -- AIRG.ResearchStarted
+
+-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED
+-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
+function AIRG.ResearchCompleted()
+    AIRG.PopulateMatrix()
+    -- TO DO: If it's visible, invoke a redisplay
+    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+end -- AIRG.ResearchEnded
+
+function AIRG.StyleLearned(eventCode, styleIndex)
+    AIRG.PopulateStyleData()
+    AIRG.DisplayStyles()
+end -- AIRG.StyleLearned
+
+-- Invoked from AIRG.Initialise but lengthy so in it's own function to not clutter Initialise
+function AIRG.initUI()
+    -- Some local variable declaration
+    local i, j      -- used in for loops
+    local thisTrait, tType, tDesc, rowNum, charName
+    -- Initialise a table to hold all the lua generated components
+    AIRG.UI = {}
+    -- Set the main window title
+    AIRG.UI.WindowTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowTitle", AIResearchGrid, CT_LABEL)
+    AIRG.UI.WindowTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 0)
+    AIRG.UI.WindowTitle:SetFont("ZoFontAnnounceMedium")
+    AIRG.UI.WindowTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+    AIRG.UI.WindowTitle:SetText("|c8080ffAI|r RESEARCH GRID")
+    -- Set the main window subtitle
+    AIRG.UI.WindowSubTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowSubTitle", AIResearchGrid, CT_LABEL)
+    AIRG.UI.WindowSubTitle:SetAnchor(LEFT, AIRG.UI.WindowTitle, RIGHT, 10, 0)
+    AIRG.UI.WindowSubTitle:SetFont("ZoFontAnnounceMedium")
+    AIRG.UI.WindowSubTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+    AIRG.UI.WindowSubTitle:SetColor(0, 1, 0, 1);    -- green
+    AIRG.UI.WindowSubTitle:SetText("")
+    -- Nice little line under the main title
+    AIRG.UI.TopDivider = WINDOW_MANAGER:CreateControl("AIResearchGridTopDivider", AIResearchGrid, CT_TEXTURE)
+    AIRG.UI.TopDivider:SetDimensions(760, 5)
+    AIRG.UI.TopDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 32)
+    AIRG.UI.TopDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
+    -- Nice little line under the grid
+    AIRG.UI.BottomDivider = WINDOW_MANAGER:CreateControl("AIResearchGridBottomDivider", AIResearchGrid, CT_TEXTURE)
+    AIRG.UI.BottomDivider:SetDimensions(760, 5)
+    AIRG.UI.BottomDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 636)
+    AIRG.UI.BottomDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
+    AIRG.UI.BottomDivider:SetHidden(not AIRG.vars.showMotifs)
+    -- CREATE BUTTON FOR CLOSE ADDON AT TOP_RIGHT
+    AIRG.UI.btnCloseAddonFrame = WINDOW_MANAGER:CreateControl("AIResearchGridButtonCloseAddon", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnCloseAddonFrame:SetDimensions(28, 28)
+    AIRG.UI.btnCloseAddonFrame:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, 0 , 0)
+    AIRG.UI.btnCloseAddonFrame:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnCloseAddonFrame:SetMouseOverBlendMode(0)
+--    AIRG.UI.btnCloseAddonFrame:SetHidden(false)
+    AIRG.UI.btnCloseAddonFrame:SetEnabled(true)
+--    AIRG.UI.btnCloseAddonFrame:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnCloseAddonFrame:SetNormalTexture("/esoui/art/buttons/clearslot_down.dds")
+    AIRG.UI.btnCloseAddonFrame:SetMouseOverTexture("/esoui/art/buttons/clearslot_up.dds")
+    AIRG.UI.btnCloseAddonFrame:SetHandler("OnClicked", function(self) AIRG.ToggleMainWindow() end)
+    -- CREATE the DROPDOWN BOX for CHARACTER SELECT
+    -- Uses code based on example from Seerah
+    AIRG.UI.charDropdown = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridDropdownCharacter", AIResearchGrid, "ZO_StatsDropdownRow")
+    AIRG.UI.charDropdown:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, -32, 0)
+    AIRG.UI.charDropdown:GetNamedChild("Dropdown"):SetWidth(200)
+    AIRG.UI.charDropdown.dropdown:SetSelectedItem(AIRG.curCharacter)  -- Set the current character as selected
+    local function OnItemSelect(_, choiceText, choice)  --this is the callback function for when an item gets selected in the dropdown
+        AIRG.OnCharacterSelect(choiceText)
+    end
+    for charName, _ in pairs(AIRG.vars.data) do
+        local entry = AIRG.UI.charDropdown.dropdown:CreateItemEntry(charName, OnItemSelect)
+        AIRG.UI.charDropdown.dropdown:AddItem(entry)
+    end
+    -- PEOPLE ICON NEXT TO THE DROPDOWN BOX
+--    AIRG.UI.PeopleIcon = WINDOW_MANAGER:CreateControl("AIResearchGridPeopleIcon", AIResearchGrid, CT_TEXTURE)
+--    AIRG.UI.PeopleIcon:SetDimensions(40, 32)
+--    AIRG.UI.PeopleIcon:SetAnchor(TOPRIGHT, AIRG.UI.charDropdown, TOPLEFT, 0, 0)
+--    AIRG.UI.PeopleIcon:SetTexture("/esoui/art/contacts/tabicon_friends_down.dds")
+    -- CREATE BUTTON FOR PROFESSION: BLACKSMITHING
+    AIRG.UI.btnBlacksmithing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonBlacksmithing", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnBlacksmithing:SetDimensions(48, 48)
+    AIRG.UI.btnBlacksmithing:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 8 , 44)
+    AIRG.UI.btnBlacksmithing:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnBlacksmithing:SetMouseOverBlendMode(0)
+    AIRG.UI.btnBlacksmithing:SetHidden(false)
+    AIRG.UI.btnBlacksmithing:SetEnabled(true)
+    AIRG.UI.btnBlacksmithing:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnBlacksmithing:SetNormalTexture("/esoui/art/icons/ability_smith_007.dds")
+    AIRG.UI.btnBlacksmithing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnBlacksmithing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_BLACKSMITHING) end)
+    -- CREATE BUTTON FOR PROFESSION: WOODWORKING
+    AIRG.UI.btnWoodworking = WINDOW_MANAGER:CreateControl("AIResearchGridButtonWoodworking", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnWoodworking:SetDimensions(48, 48)
+    AIRG.UI.btnWoodworking:SetAnchor(TOPLEFT, AIRG.UI.btnBlacksmithing, TOPRIGHT, 12 , 0)
+    AIRG.UI.btnWoodworking:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnWoodworking:SetMouseOverBlendMode(0)
+    AIRG.UI.btnWoodworking:SetHidden(false)
+    AIRG.UI.btnWoodworking:SetEnabled(true)
+    AIRG.UI.btnWoodworking:SetClickSound(SOUNDS.BLACKSMITH_EXTRACTED_BOOSTER)
+    AIRG.UI.btnWoodworking:SetNormalTexture("/esoui/art/icons/ability_tradecraft_009.dds")
+    AIRG.UI.btnWoodworking:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnWoodworking:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_WOODWORKING) end)
+    -- CREATE BUTTON FOR PROFESSION: CLOTHING
+    AIRG.UI.btnClothing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonClothing", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnClothing:SetDimensions(48, 48)
+    AIRG.UI.btnClothing:SetAnchor(TOPLEFT, AIRG.UI.btnWoodworking, TOPRIGHT, 12 , 0)
+    AIRG.UI.btnClothing:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnClothing:SetMouseOverBlendMode(0)
+    AIRG.UI.btnClothing:SetHidden(false)
+    AIRG.UI.btnClothing:SetEnabled(true)
+    AIRG.UI.btnClothing:SetClickSound(SOUNDS.CLOTHIER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnClothing:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
+    AIRG.UI.btnClothing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnClothing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_CLOTHIER) end)
+
+    -- BUILD THE TRAIT LABELS ON THE LEFT-SIDE using built-in language strings
+    AIRG.UI.rowLabels = {}
+    for thisTrait, j in pairs(AIRG.gridTraits) do
+        AIRG.UI.rowLabels[j] = WINDOW_MANAGER:CreateControl("AIResearchGridRowLabel" .. tostring(j), AIResearchGrid, CT_LABEL)
+        AIRG.UI.rowLabels[j]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 28*j + 70)
+        AIRG.UI.rowLabels[j]:SetText(GetString("SI_ITEMTRAITTYPE",thisTrait))       -- This is the text displayed on the screen as it's a label
+        AIRG.UI.rowLabels[j]:SetDimensions(180, 24)
+        AIRG.UI.rowLabels[j]:SetFont("ZoFontGame")
+        AIRG.UI.rowLabels[j]:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+        AIRG.UI.rowLabels[j]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.rowLabels[j]:SetMouseEnabled(true)
+        AIRG.UI.rowLabels[j]:SetHandler("OnMouseEnter", function (self)
+                            ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
+                        end)
+        AIRG.UI.rowLabels[j]:SetHandler("OnMouseExit", function (self)
+                            ZO_Tooltips_HideTextTooltip()
+                        end)
+    end
+    -- Now add tooltip text to the row labels.
+    -- The tooltip functionality is automatic as part of the label control.
+    for j = 1, 9 do
+        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,1,j) -- weapons
+        rowNum = AIRG.gridTraits[tType]
+        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
+        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,9,j) -- armour
+        rowNum = AIRG.gridTraits[tType]
+        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
+    end
+    -- BUILD THE COLUMNS & GRID
+    -- Determine the maximum number of item types across all three professions. This is currently always 14
+    AIRG.maxColumns= math.max(GetNumSmithingResearchLines(CRAFTING_TYPE_BLACKSMITHING),
+            GetNumSmithingResearchLines(CRAFTING_TYPE_CLOTHIER),
+            GetNumSmithingResearchLines(CRAFTING_TYPE_WOODWORKING))
+    AIRG.UI.columnButtons = {}
+    AIRG.UI.gridButtons = {}
+    AIRG.UI.columnFooters = {}
+    for i = 1, AIRG.maxColumns do
+        -- BUILD THE COLUMN BUTTONS
+        AIRG.UI.columnButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridHeaderButton" .. tostring(i), AIResearchGrid, CT_BUTTON)
+        AIRG.UI.columnButtons[i]:SetDimensions(36, 36)
+        AIRG.UI.columnButtons[i]:SetState(BSTATE_NORMAL)
+        AIRG.UI.columnButtons[i]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 40*i + 150, 55)
+        AIRG.UI.columnButtons[i]:SetHidden(true)
+        AIRG.UI.columnButtons[i]:SetEnabled(true)
+        AIRG.UI.columnButtons[i]:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+        AIRG.UI.columnButtons[i].text = i
+        AIRG.UI.columnButtons[i]:SetHandler("OnMouseEnter", function (self)
+                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.text)
+                                            end)
+        AIRG.UI.columnButtons[i]:SetHandler("OnMouseExit", function (self)
+                                                ZO_Tooltips_HideTextTooltip()
+                                            end)
+        -- BUILD THE GRID
+        -- There are a total of 18 traits possible. 9 armour and 9 weapon (Infused, Training and Nirnhoned on both)
+        AIRG.UI.gridButtons[i] = {}
+        for j = 1, 18 do
+            AIRG.UI.gridButtons[i][j] = WINDOW_MANAGER:CreateControl("AIResearchGridGridButton" .. tostring(i) .. "x" .. tostring(j), AIResearchGrid, CT_TEXTURE)
+            AIRG.UI.gridButtons[i][j]:SetDimensions(24, 24)
+            AIRG.UI.gridButtons[i][j]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 28*j -20)
+            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
+            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
+            AIRG.UI.gridButtons[i][j]:SetHidden(false)
+            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)
+            -- Following tooltip code uses ideas contributed by Krysstof
+            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseEnter", function (self)
+                        if (self.tooltipText > 0) then      -- Check the item is being researched and has a timestamp
+					        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
+                            local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
+					        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
+    						-- loop with "registerforupdate" once per second
+    						EVENT_MANAGER:RegisterForUpdate(self.name, 1000, function()
+    						        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
+                                    local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
+    						        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
+    						    end)
+    				    end
+					end)
+            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseExit", function (self)
+						-- unregister the update event or it keeps on displaying
+						EVENT_MANAGER:UnregisterForUpdate(self.name)
+						ZO_Tooltips_HideTextTooltip()
+					end)
+        end
+        -- BUILD THE COLUMN FOOTERS
+        AIRG.UI.columnFooters[i] = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterLabel" .. tostring(i), AIResearchGrid, CT_LABEL)
+        AIRG.UI.columnFooters[i]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 516)
+        AIRG.UI.columnFooters[i]:SetDimensions(36, 24)
+        AIRG.UI.columnFooters[i]:SetFont("ZoFontGame")
+        AIRG.UI.columnFooters[i]:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.columnFooters[i]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.columnFooters[i]:SetColor(1, 1, 0.4, 1);    -- faded yellow
+    end
+    -- BUILD LABEL FOR COLUMN FOOTER "TRAIT LINE"
+    AIRG.UI.columnFooterTitle = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterTitleLabel", AIResearchGrid, CT_LABEL)
+    AIRG.UI.columnFooterTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 606)
+    AIRG.UI.columnFooterTitle:SetDimensions(180, 24)
+    AIRG.UI.columnFooterTitle:SetFont("ZoFontGame")
+    AIRG.UI.columnFooterTitle:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+    AIRG.UI.columnFooterTitle:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+    AIRG.UI.columnFooterTitle:SetColor(1, 1, 0.4, 1);       -- faded yellow
+--    AIRG.UI.columnFooterTitle:SetText(GetString(SI_SMITHING_RESEARCH_LINE_HEADER))
+    AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS))
+
+    -- BUILD THE MOTIF ICONS ACROSS THE BOTTOM
+    -- Note that for now, we're just setting up 15 icons and stuff is configured manually
+    -- but we can fix it later. It's not like it's going to have an overhead on processing. :)
+    -- It's set-up inside a container frame to make hiding or showing the whole lot simpler.
+    AIRG.UI.motifSection = WINDOW_MANAGER:CreateControl("AIResearchMotifSection", AIResearchGrid, CT_CONTROL)
+    AIRG.UI.motifSection:SetDimensions(AIRG.gridAlignments.grid_base_width, AIRG.gridAlignments.styleGrid.height)
+    AIRG.UI.motifSection:SetAnchor(BOTTOMLEFT, AIResearchGrid, BOTTOMLEFT, 0, 0)
+    AIRG.UI.motifSection:SetHidden(not AIRG.vars.showMotifs)
+    AIResearchGrid:SetHeight(AIRG.vars.showMotifs and AIRG.gridAlignments.grid_base_height + AIRG.gridAlignments.styleGrid.height or AIRG.gridAlignments.grid_base_height)
+    AIRG.UI.motifButtons = {}
+	local currentColumn = 0
+	local currentRow = 0
+    for i = 1, AIRG.gridAlignments.styleGrid.num_styles do
+		currentColumn = currentColumn + 1
+        AIRG.UI.motifButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridMotifButton" .. tostring(i), AIRG.UI.motifSection, CT_TEXTURE)
+        AIRG.UI.motifButtons[i]:SetDimensions(AIRG.gridAlignments.styleGrid.icon_width, AIRG.gridAlignments.styleGrid.icon_height)
+		if currentColumn > AIRG.gridAlignments.styleGrid.row_length then
+			currentRow = currentRow + 1
+			currentColumn = currentColumn - AIRG.gridAlignments.styleGrid.row_length
+		end
+		local yVal = AIRG.gridAlignments.styleGrid.top_align + (AIRG.gridAlignments.styleGrid.icon_box_height * currentRow)
+		local xVal = AIRG.gridAlignments.styleGrid.icon_box_width * currentColumn + AIRG.gridAlignments.styleGrid.left_align
+        AIRG.UI.motifButtons[i]:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, xVal, yVal)
+        AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+        AIRG.UI.motifButtons[i]:SetMouseEnabled(true)
+        j = AIRG.styleLookupValue[i]
+        tDesc ,_,_,_,_ = GetSmithingStyleItemInfo( AIRG.styleLookupItem[i] )
+        AIRG.UI.motifButtons[i].tooltipText = zo_strformat("<<t:1>>\n<<t:2>>", GetString("SI_ITEMSTYLE",j), tDesc)
+        AIRG.UI.motifButtons[i]:SetHandler("OnMouseEnter", function (self)
+                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
+                                            end)
+        AIRG.UI.motifButtons[i]:SetHandler("OnMouseExit", function (self)
+                                                ZO_Tooltips_HideTextTooltip()
+                                            end)
+    end
+    -- BUILD LABEL FOR STYLES
+    AIRG.UI.StyleLabel = WINDOW_MANAGER:CreateControl("AIResearchStylelabel", AIRG.UI.motifSection, CT_LABEL)
+    AIRG.UI.StyleLabel:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 5, 14)
+    AIRG.UI.StyleLabel:SetText(GetString(SI_SMITHING_HEADER_STYLE))
+    AIRG.UI.StyleLabel:SetDimensions(180, 24)
+    AIRG.UI.StyleLabel:SetFont("ZoFontGame")
+    AIRG.UI.StyleLabel:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+end -- AIRG.initUI
+
+-- User has clicked on one of the profession buttons
+-- or we just want to refresh the display with current data
+function AIRG.OnCraftSelected(_,thisCraft)
+    if (thisCraft == nil) then
+        if (AIRG.curCraft == nil) then
+            return
+        else
+            thisCraft = AIRG.curCraft
+        end
+    end
+    AIRG.UI.WindowSubTitle:SetText(AIRG.craftNames[thisCraft])
+    local i,j
+    local tType,tDesc,tKnown,tRemain,rowNum,traitCount
+    local maxLines = GetNumSmithingResearchLines(thisCraft) -- the number of columns for this profession
+    AIRG.curCraft = thisCraft
+    for i = 1, AIRG.maxColumns do
+        -- "blank" the grid
+        for j = 1, 18 do
+            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
+            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
+            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)    -- effectively disable tooltip for this grid item.
+        end
+        if (i > maxLines) then
+            AIRG.UI.columnButtons[i]:SetHidden(true)
+            AIRG.UI.columnFooters[i]:SetText("")
+        else
+            local name, icon, _, _ = GetSmithingResearchLineInfo(thisCraft, i)  -- Get info on that specific item
+            AIRG.UI.columnButtons[i]:SetNormalTexture(icon)
+            AIRG.UI.columnButtons[i]:SetHidden(false)
+            AIRG.UI.columnButtons[i].text = name
+
+            traitCount = 0
+            for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
+                AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
+                if (tKnown == -1) then       -- Trait is known
+                    AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
+                    traitCount = traitCount + 1
+                elseif (tKnown > 0) then   -- Trait is being researched
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/tutorial/timer_icon.dds")
+                    if (tKnown < GetTimeStamp()) then   -- This is on another character and the timer has completed.
+                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
+                        traitCount = traitCount + 1
+                    else
+                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.5, 0.5, 1, 1)   -- Blue
+                        AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
+                    end
+                else                        -- Trait is NOT known
+                    AIRG.UI.gridButtons[i][rowNum]:SetColor(1, 0.2, 0.2, 1)   -- Red
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/buttons/decline_up.dds")
+                end
+            end
+            if (traitCount > 0) then
+                AIRG.UI.columnFooters[i]:SetText(traitCount)
+            else
+                AIRG.UI.columnFooters[i]:SetText("")
+            end
+        end
+    end
+end -- AIRG:OnCraftSelected
+
+-- Invoked when the user selected a character from the dropdown box
+function AIRG.OnCharacterSelect(charName)
+    if (charName == nil) then
+    else
+        AIRG.curCharacter = charName
+    end
+    AIRG.DisplayStyles()
+    AIRG.OnCraftSelected()
+end -- AIRG.OnCharacterSelect
+
+-- Deletes data for the named character from the saved data and removes them from the dropdown box.
+function AIRG.DeleteCharacter(charName)
+    -- Can't delete the current character
+    if (charName == AIRG.playerName) then
+        d(AIRG.L["DeleteFalse"])
+    else
+        if (AIRG.vars.data[charName] ~= nil) then
+            AIRG.vars.data[charName] = nil
+            d(AIRG.L["DeleteTrue"] .. charName)
+        end
+        if (AIRG.vars.styles[charName] ~= nil) then
+            AIRG.vars.styles[charName] = nil
+        end
+    end
+end -- AIRG.DeleteCharacter
+
+-- This function cycles through all three professions and populates the data matrix for THIS character.
+-- This is carried out when the addon loasd to ensure the current character data is up-to-date.
+-- The "if" logic in this function guesses at which profession should be default to display as the one with most research in.
+function AIRG.PopulateMatrix()
+    local curCount = 0
+    local thisCount
+    AIRG.vars.data[AIRG.playerName] = {}    -- create a table for this character's matrix
+    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_BLACKSMITHING)
+    if (thisCount > curCount) then
+        AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
+        curCount = thisCount
+    end
+    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_CLOTHIER)
+    if (thisCount > curCount) then
+        AIRG.curCraft = CRAFTING_TYPE_CLOTHIER
+        curCount = thisCount
+    end
+    thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_WOODWORKING)
+    if (thisCount > curCount) then
+        AIRG.curCraft = CRAFTING_TYPE_WOODWORKING
+        curCount = thisCount
+    end
+
+	if (AIRG.curCraft == nil) then
+		AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
+	end
+end -- AIRG.PopulateMatrix
+
+-- Lookup the style data for the current character and send it to saved vars.
+function AIRG.PopulateStyleData()
+    AIRG.vars.styles[AIRG.playerName] = {}    -- create a table for this character's matrix
+    local i, j
+    for i = 1, AIRG.gridAlignments.styleGrid.num_styles do
+        j = AIRG.styleLookupItem[i]
+        AIRG.vars.styles[AIRG.playerName][i] = IsSmithingStyleKnown(j, 1) --patternIndex set to 1, temporary workaround for changes introduced in Update 4
+    end
+end -- AIRG.PopulateStyleData
+
+-- Set the icon highlights for the currently selected character
+function AIRG.DisplayStyles()
+    local i
+    if (AIRG.vars.styles[AIRG.curCharacter] == nil) then
+        for i = 1, 30 do
+            AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+            AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
+        end
+    else
+        for i = 1, 30 do
+            if (AIRG.vars.styles[AIRG.curCharacter][i]) then
+                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "down.dds")
+                AIRG.UI.motifButtons[i]:SetColor(0.7, 1, 0.7, 1)   -- Green
+            else
+                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+                AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
+            end
+        end
+    end
+end -- AIRG.DisplayStyles()
+
+-- Look up all the data on this profession and commit to saved variables for this character.
+-- TO DO: At some point, get clever with storing the timestamp for when research will be complete
+function AIRG.CreateDataMatrix(thisCraft)
+    local i, j
+    local tType, tKnown, tRemain, rowNum, tTargetStamp
+    local rCount = 0
+    local maxLines = GetNumSmithingResearchLines(thisCraft)     -- the number of columns for this profession
+    AIRG.vars.data[AIRG.playerName][thisCraft] = {}             -- create a table for this profession
+    -- Cycle through items for this profession
+    for i = 1, maxLines do
+        AIRG.vars.data[AIRG.playerName][thisCraft][i] = {}      -- create a table for this item
+        -- Cycle through the traits for this item
+        for j = 1, 9 do
+            tType,_,tKnown = GetSmithingResearchLineTraitInfo(thisCraft,i,j)
+            _,tRemain = GetSmithingResearchLineTraitTimes(thisCraft,i,j)
+            rowNum = AIRG.gridTraits[tType]
+
+            if (tKnown) then
+                AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = -1       -- this trait is known
+                rCount = rCount + 1
+            else
+                if (tRemain) then
+                    tTargetStamp = GetTimeStamp() + tRemain
+                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = tTargetStamp   -- this trait is being currently researched
+                    -- The value we are setting this to is the timestamp for when the research will be complete.
+                else
+                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = 0   -- this trait is NOT known
+                end
+            end
+        end
+    end
+    return rCount       -- the total number of traits already researched in this profession
+end -- AIRG.CreateDataMatrix
+
+function AIRG.AssignGridTraits()
+    -- Translates the traitType to the correct ROW of the grid
+    AIRG.gridTraits = {}
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_POWERED] = 1
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = 2
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = 3
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = 4
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = 5
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = 6
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = 7
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = 8
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = 9
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_STURDY] = 10
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = 11
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = 12
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = 13
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = 14
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = 15
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = 16
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = 17
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = 18
+end -- AIRG.AssignGridTraits
+
+function AIRG.AssignStyleLookups()
+    -- Lookup the correct icon for the style
+    AIRG.styleLookupIcons = {}
+    AIRG.styleLookupIcons[1] = "ESOUI/art/charactercreate/charactercreate_altmericon_"
+    AIRG.styleLookupIcons[2] = "ESOUI/art/charactercreate/charactercreate_argonianicon_"
+    AIRG.styleLookupIcons[3] = "ESOUI/art/charactercreate/charactercreate_bosmericon_"
+    AIRG.styleLookupIcons[4] = "ESOUI/art/charactercreate/charactercreate_bretonicon_"
+    AIRG.styleLookupIcons[5] = "ESOUI/art/charactercreate/charactercreate_dunmericon_"
+    AIRG.styleLookupIcons[6] = "ESOUI/art/charactercreate/charactercreate_khajiiticon_"
+    AIRG.styleLookupIcons[7] = "ESOUI/art/charactercreate/charactercreate_nordicon_"
+    AIRG.styleLookupIcons[8] = "ESOUI/art/charactercreate/charactercreate_orcicon_"
+    AIRG.styleLookupIcons[9] = "ESOUI/art/charactercreate/charactercreate_redguardicon_"
+    AIRG.styleLookupIcons[10] = "ESOUI/art/charactercreate/charactercreate_imperialicon_"
+    AIRG.styleLookupIcons[11] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[12] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[13] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[14] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[15] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[16] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[17] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[18] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[19] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[20] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[21] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[22] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[23] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[24] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[25] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[26] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[27] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[28] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[29] = "ESOUI/art/progression/progression_indexicon_weapons_"
+	AIRG.styleLookupIcons[30] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    -- Translate the icon position to the in-game type. Used for text look-up
+    AIRG.styleLookupValue = {}
+    AIRG.styleLookupValue[1] = ITEMSTYLE_RACIAL_HIGH_ELF
+    AIRG.styleLookupValue[2] = ITEMSTYLE_RACIAL_ARGONIAN
+    AIRG.styleLookupValue[3] = ITEMSTYLE_RACIAL_WOOD_ELF
+    AIRG.styleLookupValue[4] = ITEMSTYLE_RACIAL_BRETON
+    AIRG.styleLookupValue[5] = ITEMSTYLE_RACIAL_DARK_ELF
+    AIRG.styleLookupValue[6] = ITEMSTYLE_RACIAL_KHAJIIT
+    AIRG.styleLookupValue[7] = ITEMSTYLE_RACIAL_NORD
+    AIRG.styleLookupValue[8] = ITEMSTYLE_RACIAL_ORC
+    AIRG.styleLookupValue[9] = ITEMSTYLE_RACIAL_REDGUARD
+    AIRG.styleLookupValue[10] = ITEMSTYLE_RACIAL_IMPERIAL
+    AIRG.styleLookupValue[11] = ITEMSTYLE_AREA_ANCIENT_ELF
+    AIRG.styleLookupValue[12] = ITEMSTYLE_AREA_REACH
+    AIRG.styleLookupValue[13] = ITEMSTYLE_ENEMY_PRIMITIVE
+    AIRG.styleLookupValue[14] = ITEMSTYLE_ENEMY_DAEDRIC
+	AIRG.styleLookupValue[15] = ITEMSTYLE_AREA_DWEMER
+	AIRG.styleLookupValue[16] = ITEMSTYLE_GLASS
+	AIRG.styleLookupValue[17] = ITEMSTYLE_AREA_XIVKYN
+	AIRG.styleLookupValue[18] = ITEMSTYLE_AREA_AKAVIRI
+	AIRG.styleLookupValue[19] = ITEMSTYLE_UNDAUNTED
+	AIRG.styleLookupValue[20] = ITEMSTYLE_AREA_ANCIENT_ORC
+	AIRG.styleLookupValue[21] = ITEMSTYLE_DEITY_TRINIMAC
+	AIRG.styleLookupValue[22] = ITEMSTYLE_DEITY_MALACATH
+	AIRG.styleLookupValue[23] = ITEMSTYLE_ORG_OUTLAW
+	AIRG.styleLookupValue[24] = ITEMSTYLE_ALLIANCE_ALDMERI
+	AIRG.styleLookupValue[25] = ITEMSTYLE_ALLIANCE_DAGGERFALL
+	AIRG.styleLookupValue[26] = ITEMSTYLE_ALLIANCE_EBONHEART
+	AIRG.styleLookupValue[27] = ITEMSTYLE_AREA_SOUL_SHRIVEN
+	AIRG.styleLookupValue[28] = ITEMSTYLE_ORG_ABAHS_WATCH
+	AIRG.styleLookupValue[29] = ITEMSTYLE_ORG_THIEVES_GUILD
+	AIRG.styleLookupValue[30] = ITEMSTYLE_ORG_ASSASSINS
+    -- This is a bit of a hack, but only because of the way ESO uses Style Items with different index to styles.
+    AIRG.styleLookupItem = {}
+    AIRG.styleLookupItem[1] = 8     -- Altmer       		= Adamantite
+    AIRG.styleLookupItem[2] = 7     -- Argonian     		= Flint
+    AIRG.styleLookupItem[3] = 9     -- Bosmer       		= Bone
+    AIRG.styleLookupItem[4] = 2     -- Breton       		= Molybdenum
+    AIRG.styleLookupItem[5] = 5     -- Dunmer       		= Obsidian
+    AIRG.styleLookupItem[6] = 10    -- Khajit       		= Moonstone
+    AIRG.styleLookupItem[7] = 6     -- Nord         		= Corundum
+    AIRG.styleLookupItem[8] = 4     -- Orc          		= Manganese
+    AIRG.styleLookupItem[9] = 3     -- Redguard     		= Starmetal
+    AIRG.styleLookupItem[10] = 35   -- Imperial     		= Nickel
+    AIRG.styleLookupItem[11] = 16   -- Ancient Elf  		= Palladium
+    AIRG.styleLookupItem[12] = 18   -- Barbarian    		= Copper
+    AIRG.styleLookupItem[13] = 20   -- Primal       		= Argentum
+    AIRG.styleLookupItem[14] = 21   -- Daedric      		= Daedra Heart
+	AIRG.styleLookupItem[15] = 15   -- Dwemer       		= Dwemer Frame
+	AIRG.styleLookupItem[16] = 29   -- Glass     			= Malachite
+	AIRG.styleLookupItem[17] = 30   -- Xivkyn  				= Charcoal of Remorse
+	AIRG.styleLookupItem[18] = 34   -- Akaviri      		= Gold Scale
+	AIRG.styleLookupItem[19] = 27   -- Mercenary    		= Laurels
+	AIRG.styleLookupItem[20] = 23   -- Ancient Orc  		= Casserite
+	AIRG.styleLookupItem[21] = 22   -- Trinimac     		= Auric Tusk
+	AIRG.styleLookupItem[22] = 14   -- Malacath     		= Potash
+	AIRG.styleLookupItem[23] = 48   -- Outlaw      			= Rogue's Soot
+	AIRG.styleLookupItem[24] = 26   -- Aldmeri Dominion     = Eagle Feather
+	AIRG.styleLookupItem[25] = 24   -- Daggerfall Covenant  = Lion Fang
+	AIRG.styleLookupItem[26] = 25   -- Ebonheart Pact      	= Dragon Scute
+	AIRG.styleLookupItem[27] = 31   -- Soul Shriven      	= Azure Plasm
+	AIRG.styleLookupItem[28] = 42   -- Abah's Watch      	= Polished Shilling
+	AIRG.styleLookupItem[29] = 12   -- Thieves' Guild      	= Fine Chalk
+	AIRG.styleLookupItem[30] = 47   -- Assassin's League    = Tainted Blood
+end -- AIRG.AssignStyleLookups
+
+-- EOF
diff --git a/AIResearchGrid/AIResearchGrid.txt b/AIResearchGrid/AIResearchGrid.txt
new file mode 100644
index 0000000..1e406d2
--- /dev/null
+++ b/AIResearchGrid/AIResearchGrid.txt
@@ -0,0 +1,23 @@
+## Title: |cFFFFB0Research Grid|r v2.3 by |c00C000CrazyDutchGuy|r
+## APIVersion: 100010
+## Version: 2.3
+## Author: Stormknight & CrazyDutchGuy
+## OptionalDependsOn: LibAddonMenu-2.0
+## SavedVariables: AIRG_SavedVariables
+## Description: Allows you to quickly and easily see which traits your characters have researched for Blacksmithing, Clothing & Woodworking, wherever you are in the world.
+
+Libs/LibStub/LibStub.lua
+Libs/LAM2/LibAddonMenu-2.0.lua
+Libs/LAM2/controls/panel.lua
+Libs\LAM2/controls/header.lua
+Libs\LAM2/controls/checkbox.lua
+Libs\LAM2/controls/dropdown.lua
+Libs\LAM2/controls/button.lua
+Libs\LAM2/controls/description.lua
+
+AIResearchGrid.lua
+AIResearchGridConfig.lua
+AIResearchGrid.xml
+Bindings.xml
+
+Language/$(language).lua
\ No newline at end of file
diff --git a/AIResearchGrid/AIResearchGrid.xml b/AIResearchGrid/AIResearchGrid.xml
new file mode 100644
index 0000000..520c0c5
--- /dev/null
+++ b/AIResearchGrid/AIResearchGrid.xml
@@ -0,0 +1,13 @@
+<GuiXml>
+    <Controls>
+        <TopLevelControl name="AIResearchGrid" mouseEnabled="true" movable="true" clampedToScreen="true" hidden="true">
+            <Dimensions x="760" y="756" />
+            <Anchor point="CENTER" />
+            <Controls>
+
+                <Backdrop name="$(parent)BG" inherits="ZO_DefaultBackdrop" />
+
+            </Controls>
+        </TopLevelControl>
+    </Controls>
+</GuiXml>
\ No newline at end of file
diff --git a/AIResearchGrid/AIresearchGridConfig.lua b/AIResearchGrid/AIresearchGridConfig.lua
new file mode 100644
index 0000000..97a239d
--- /dev/null
+++ b/AIResearchGrid/AIresearchGridConfig.lua
@@ -0,0 +1,67 @@
+function AIRG.CreateConfigMenu()
+    local charList = {}
+    table.insert(charList,"")
+    for charName, _ in pairs(AIRG.vars.data) do
+        table.insert(charList, charName)
+    end
+
+    local panelData = {
+        type = "panel",
+        name = "AI Research Grid",
+        displayName = "|c8080FFAI Research Grid|r",
+        author = "Stormknight & CrazyDutchGuy",
+        version = tostring(AIRG.version),
+    }
+
+    local optionsData = {
+    -- GENERAL SECTION
+        {
+            type = "header",
+            name = AIRG.L["General Options"],
+        },
+        {
+            type = "checkbox",
+            name = AIRG.L["Show Motifs"],
+            tooltip = AIRG.L["Show Motifs Long"],
+            getFunc = function() return AIRG.vars.showMotifs end,
+            setFunc = function(newValue)
+                    AIRG.vars.showMotifs = newValue
+                    AIRG.UI.motifSection:SetHidden(not newValue)
+                    AIRG.UI.BottomDivider:SetHidden(not newValue)
+                    AIResearchGrid:SetHeight(newValue and 756 or 636)
+                end,
+        },
+        -- CHARACTER DELETION SECTION
+        {
+            type = "header",
+            name = AIRG.L["Characters"],
+        },
+        {
+            type = "dropdown",
+            name = AIRG.L["CharacterSelect"],
+            choices = charList,
+            getFunc = function() return "" end,
+            setFunc = function(newValue) AIRG.charToDelete = newValue	end,
+        },
+        {
+            type = "button",
+            name = AIRG.L["Delete"],
+            tooltip = AIRG.L["DeleteDesc"],
+            func = function() AIRG.DeleteCharacter(AIRG.charToDelete) end,
+        },
+        -- KEYBINDS SECTION
+        {
+            type = "header",
+            name = AIRG.L["Keybinds"],
+        },
+        {
+            type = "description",
+            text = AIRG.L["Keybind Text"],
+        },
+    }
+
+    local LAM2 = LibStub("LibAddonMenu-2.0")
+    LAM2:RegisterAddonPanel(AIRG.name.."Config", panelData)
+    LAM2:RegisterOptionControls(AIRG.name.."Config", optionsData)
+
+end -- AIRG.CreateConfigMenu
diff --git a/AIResearchGrid/Bindings.xml b/AIResearchGrid/Bindings.xml
new file mode 100644
index 0000000..ddd3193
--- /dev/null
+++ b/AIResearchGrid/Bindings.xml
@@ -0,0 +1,9 @@
+<Bindings>
+  <Layer name="SI_KEYBINDINGS_LAYER_GENERAL">
+    <Category name="|c8080FFAI Research Grid|r">
+      <Action name="TOGGLE_AIRG">
+        <Down>AIRG.ToggleMainWindow()</Down>
+      </Action>
+    </Category>
+  </Layer>
+</Bindings>
\ No newline at end of file
diff --git a/AIResearchGrid/Language/de.lua b/AIResearchGrid/Language/de.lua
new file mode 100644
index 0000000..7aeffd1
--- /dev/null
+++ b/AIResearchGrid/Language/de.lua
@@ -0,0 +1,21 @@
+-- Language file: GERMAN
+
+function AIRG.InitialiseLanguage()
+    AIRG.L = {}
+
+    -- Settings / Config menu stuff
+    AIRG.L["General Options"]                       = "|c45D7F7Generelle Einstellungen|r"
+    AIRG.L["Keybinds"]                              = "|c45D7F7Tastenbelegung|r"
+    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
+
+    AIRG.L["Show Motifs"]                           = "Zeige Motive?"
+    AIRG.L["Show Motifs Long"]                      = "Zeige Motive in der Fuzeile vom Research Grid Addon."
+
+    AIRG.L["Characters"]                            = "|c45D7F7Charakter Lschen|r"
+    AIRG.L["CharacterSelect"]                       = "Whle Charakter"
+    AIRG.L["Delete"]                                = "Lschen"
+    AIRG.L["DeleteDesc"]                            = "Klicke diesen Button um die Daten des selektierten Charakters zu lschen."
+
+    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Daten des aktuellen Charakters lschen nicht mglich."
+    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Lsche Charakterdaten fr "
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Language/en.lua b/AIResearchGrid/Language/en.lua
new file mode 100644
index 0000000..fcf2616
--- /dev/null
+++ b/AIResearchGrid/Language/en.lua
@@ -0,0 +1,21 @@
+-- Language file: ENGLISH
+
+function AIRG.InitialiseLanguage()
+    AIRG.L = {}
+
+    -- Settings / Config menu stuff
+    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
+    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
+    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
+
+    AIRG.L["Show Motifs"]                           = "Show Motifs?"
+    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
+
+    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
+    AIRG.L["CharacterSelect"]                       = "Select Character"
+    AIRG.L["Delete"]                                = "Delete"
+    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
+
+    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
+    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Language/fr.lua b/AIResearchGrid/Language/fr.lua
new file mode 100644
index 0000000..fcf2616
--- /dev/null
+++ b/AIResearchGrid/Language/fr.lua
@@ -0,0 +1,21 @@
+-- Language file: ENGLISH
+
+function AIRG.InitialiseLanguage()
+    AIRG.L = {}
+
+    -- Settings / Config menu stuff
+    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
+    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
+    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
+
+    AIRG.L["Show Motifs"]                           = "Show Motifs?"
+    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
+
+    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
+    AIRG.L["CharacterSelect"]                       = "Select Character"
+    AIRG.L["Delete"]                                = "Delete"
+    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
+
+    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
+    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Language/ru.lua b/AIResearchGrid/Language/ru.lua
new file mode 100644
index 0000000..fcf2616
--- /dev/null
+++ b/AIResearchGrid/Language/ru.lua
@@ -0,0 +1,21 @@
+-- Language file: ENGLISH
+
+function AIRG.InitialiseLanguage()
+    AIRG.L = {}
+
+    -- Settings / Config menu stuff
+    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
+    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
+    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
+
+    AIRG.L["Show Motifs"]                           = "Show Motifs?"
+    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
+
+    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
+    AIRG.L["CharacterSelect"]                       = "Select Character"
+    AIRG.L["Delete"]                                = "Delete"
+    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
+
+    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
+    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/LibAddonMenu-2.0.lua b/AIResearchGrid/Libs/LAM2/LibAddonMenu-2.0.lua
new file mode 100644
index 0000000..1ab94cf
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/LibAddonMenu-2.0.lua
@@ -0,0 +1,322 @@
+--	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.								--
+--------------------------------------------------------------
+
+
+--Register LAM with LibStub
+local MAJOR, MINOR = "LibAddonMenu-2.0", 16
+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
+
+
+--UPVALUES--
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+local optionsWindow = ZO_OptionsWindowSettingsScrollChild
+local _
+
+local addonsForList = {}
+local addonToOptionsMap = {}
+local optionsCreated = {}
+lam.widgets = lam.widgets or {}
+local widgets = lam.widgets
+
+
+--METHOD: REGISTER WIDGET--
+--each widget has its version checked before loading,
+--so we only have the most recent one in memory
+--Usage:
+--	widgetType = "string"; the type of widget being registered
+--	widgetVersion = integer; the widget's version number
+LAMCreateControl = LAMCreateControl or {}
+local lamcc = LAMCreateControl
+
+function lam:RegisterWidget(widgetType, widgetVersion)
+	if widgets[widgetType] and widgets[widgetType] >= widgetVersion then
+		return false
+	else
+		widgets[widgetType] = widgetVersion
+		return true
+	end
+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")]
+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)
+end
+
+
+--INTERNAL FUNCTION
+--creates controls when options panel is first shown
+--controls anchoring of these controls in the panel
+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
+			if widgetType == "submenu" then
+				local submenu = LAMCreateControl[widgetType](panel, widgetData)
+				if lastAddedControl then
+					submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
+				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"
+					if lastAddedControlSub then
+						if lacAtHalfRowSub and isHalf then
+							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, TOPRIGHT, 5, 0)
+							lacAtHalfRowSub = false
+						else
+							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15)
+							lacAtHalfRowSub = isHalf and true or false
+							lastAddedControlSub = subWidget
+						end
+					else
+						subWidget:SetAnchor(TOPLEFT)
+						lacAtHalfRowSub = isHalf and true or false
+						lastAddedControlSub = subWidget
+					end
+				end
+			else
+				local widget = LAMCreateControl[widgetType](panel, widgetData)
+				local isHalf = widgetData.width == "half"
+				if lastAddedControl then
+					if lacAtHalfRow and isHalf then
+						widget:SetAnchor(TOPLEFT, lastAddedControl, TOPRIGHT, 10, 0)
+						lacAtHalfRow = false
+					else
+						widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
+						lacAtHalfRow = isHalf and true or false
+						lastAddedControl = widget
+					end
+				else
+					widget:SetAnchor(TOPLEFT)
+					lacAtHalfRow = isHalf and true or false
+					lastAddedControl = widget
+				end
+			end
+		end
+	end
+
+	optionsCreated[addonID] = true
+	cm:FireCallbacks("LAM-PanelControlsCreated", panel)
+end
+
+
+--INTERNAL FUNCTION
+--handles switching between panels
+local function ToggleAddonPanels(panel)	--called in OnShow of newly shown panel
+	local currentlySelected = LAMAddonPanelsMenu.currentlySelected
+	if currentlySelected and currentlySelected ~= panel then
+		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
+
+
+--METHOD: REGISTER ADDON PANEL
+--registers your addon with LibAddonMenu and creates a panel
+--Usage:
+--	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)
+	local panel = lamcc.panel(nil, panelData, addonID)	--addonID==global name of panel
+	panel:SetHidden(true)
+	panel:SetAnchor(TOPLEFT, LAMAddonPanelsMenu, TOPRIGHT, 10, 0)
+	panel:SetAnchor(BOTTOMLEFT, LAMAddonPanelsMenu, BOTTOMRIGHT, 10, 0)
+	panel:SetWidth(549)
+	panel:SetDrawLayer(DL_OVERLAY)
+	tinsert(addonsForList, {panel = addonID, name = panelData.name})
+	panel:SetHandler("OnShow", ToggleAddonPanels)
+	if panelData.slashCommand then
+		SLASH_COMMANDS[panelData.slashCommand] = function()
+			lam:OpenToPanel(panel)
+		end
+	end
+
+	return panel	--return for authors creating options manually
+end
+
+
+--METHOD: REGISTER OPTION CONTROLS
+--registers the options you want shown for your addon
+--these are stored in a table where each key-value pair is the order
+--of the options in the panel and the data for that control, respectively
+--see exampleoptions.lua for an example
+--see controls\<widget>.lua for each widget type
+--Usage:
+--	addonID = "string"; the same string passed to :RegisterAddonPanel
+--	optionsTable = table; the table containing all of the options controls and their data
+function lam:RegisterOptionControls(addonID, optionsTable)	--optionsTable = {sliderData, buttonData, etc}
+	addonToOptionsMap[addonID] = optionsTable
+end
+
+
+--INTERNAL FUNCTION
+--handles switching between LAM's Addon Settings panel and other panels in the Settings menu
+local oldDefaultButton = ZO_OptionsWindowResetToDefaultButton
+local oldCallback = oldDefaultButton.callback
+local dummyFunc = function() end
+local panelWindow = ZO_OptionsWindow
+local bgL = ZO_OptionsWindowBGLeft
+local bgR = ZO_OptionsWindowBGLeftBGRight
+local function HandlePanelSwitching(self, panel)
+	if panel == lam.panelID then	--our addon settings panel
+		oldDefaultButton:SetCallback(dummyFunc)
+		oldDefaultButton:SetHidden(true)
+		oldDefaultButton:SetAlpha(0)	--just because it still bugs out
+		panelWindow:SetDimensions(999, 960)
+		bgL:SetWidth(666)
+		bgR:SetWidth(333)
+	else
+		local shown = LAMAddonPanelsMenu.currentlySelected
+		if shown then shown:SetHidden(true) end
+		oldDefaultButton:SetCallback(oldCallback)
+		oldDefaultButton:SetHidden(false)
+		oldDefaultButton:SetAlpha(1)
+		panelWindow:SetDimensions(768, 914)
+		bgL:SetWidth(512)
+		bgR:SetWidth(256)
+	end
+end
+
+
+--INTERNAL FUNCTION
+--creates LAM's Addon Settings panel
+local function CreateAddonSettingsPanel()
+	if not LAMSettingsPanelCreated then
+		local controlPanelID = "LAM_ADDON_SETTINGS_PANEL"
+		--Russian for TERAB1T's RuESO addon, which creates an "ru" locale
+		--game font does not support Cyrillic, so they are using custom fonts + extended latin charset
+		--Spanish provided by Luisen75 for their translation project
+		local controlPanelNames = {
+			en = "Addon Settings",
+			fr = "Extensions",
+			de = "Erweiterungen",
+			ru = "Îacòpoéêè äoïoìîeîèé",
+			es = "Configura Addons",
+		}
+
+		ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")] or controlPanelName["en"])
+
+		lam.panelID = _G[controlPanelID]
+
+		--ZO_PreHook("ZO_OptionsWindow_ChangePanels", HandlePanelSwitching)
+		ZO_PreHook(ZO_SharedOptions, "ChangePanels", HandlePanelSwitching)
+
+		LAMSettingsPanelCreated = true
+	end
+end
+
+
+--INTERNAL FUNCTION
+--adds each registered addon to the menu in LAM's panel
+local function CreateAddonButtons(list, addons)
+	for i = 1, #addons do
+		local button = wm:CreateControlFromVirtual("LAMAddonMenuButton"..i, list.scrollChild, "ZO_DefaultTextButton")
+		button.name = addons[i].name
+		button.panel = _G[addons[i].panel]
+		button:SetText(button.name)
+		button:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+		button:SetWidth(190)
+		if i == 1 then
+			button:SetAnchor(TOPLEFT, list.scrollChild, TOPLEFT, 5, 5)
+		else
+			button:SetAnchor(TOPLEFT, _G["LAMAddonMenuButton"..i-1], BOTTOMLEFT)
+		end
+		button:SetHandler("OnClicked", function(self) self.panel:SetHidden(false) end)
+	end
+end
+
+
+--INTERNAL FUNCTION
+--creates the left-hand menu in LAM's panel
+local function CreateAddonList()
+	local list
+	--check if an earlier loaded copy of LAM created it already
+	list = LAMAddonPanelsMenu or wm:CreateControlFromVirtual("LAMAddonPanelsMenu", optionsWindow, "ZO_ScrollContainer")
+	list:ClearAnchors()
+	list:SetAnchor(TOPLEFT)
+	list:SetHeight(675)
+	list:SetWidth(200)
+
+	list.bg = list.bg or wm:CreateControl(nil, list, CT_BACKDROP)
+	local bg = list.bg
+	bg:SetAnchorFill()	--offsets of 8?
+	bg:SetEdgeTexture("EsoUI\\Art\\miscellaneous\\borderedinsettransparent_edgefile.dds", 128, 16)
+	bg:SetCenterColor(0, 0, 0, 0)
+
+	list.scrollChild = LAMAddonPanelsMenuScrollChild
+	list.scrollChild:SetResizeToFitPadding(0, 15)
+
+	local generatedButtons
+	list:SetHandler("OnShow", function(self)
+			if not generatedButtons and #addonsForList > 0 then
+				--we're about to show our list for the first time - let's sort the buttons before creating them
+				table.sort(addonsForList, function(a, b)
+						return a.name < b.name
+					end)
+				CreateAddonButtons(list, addonsForList)
+				self.currentlySelected = LAMAddonMenuButton1 and LAMAddonMenuButton1.panel
+				--since our addon panels don't have a parent, let's make sure they hide when we're done with them
+				ZO_PreHookHandler(ZO_OptionsWindow, "OnHide", function() self.currentlySelected:SetHidden(true) end)
+				generatedButtons = true
+			end
+			if self.currentlySelected then self.currentlySelected:SetHidden(false) end
+		end)
+
+	--list.controlType = OPTIONS_CUSTOM
+	--list.panel = lam.panelID
+	list.data = {
+		controlType = OPTIONS_CUSTOM,
+		panel = lam.panelID,
+	}
+
+	ZO_OptionsWindow_InitializeControl(list)
+
+	return list
+end
+
+
+--INITIALIZING
+CreateAddonSettingsPanel()
+CreateAddonList()
+
diff --git a/AIResearchGrid/Libs/LAM2/controls/button.lua b/AIResearchGrid/Libs/LAM2/controls/button.lua
new file mode 100644
index 0000000..187e901
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/button.lua
@@ -0,0 +1,89 @@
+--[[buttonData = {
+	type = "button",
+	name = "My Button",
+	tooltip = "Button's tooltip text.",
+	func = function() end,
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	icon = "icon\\path.dds",	--(optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	reference = "MyAddonButton"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 5
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("button", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	else
+		disable = control.data.disabled
+	end
+
+	control.button:SetEnabled(not disable)
+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 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)
+		control.button:SetNormalTexture(buttonData.icon)
+		control.button:SetPressedOffset(2, 2)
+	else
+		--control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton")
+		control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton")
+		control.button:SetWidth(isHalfWidth and 180 or 200)
+		control.button:SetText(buttonData.name)
+	end
+	local button = control.button
+	button:SetAnchor(isHalfWidth and CENTER or RIGHT)
+	button:SetClickSound("Click")
+	--button.tooltipText = buttonData.tooltip
+	button.data = {tooltipText = buttonData.tooltip}
+	button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+	button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+	button:SetHandler("OnClicked", function(self, ...)
+			buttonData.func(self, ...)
+			if control.panel.data.registerForRefresh then
+				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/AIResearchGrid/Libs/LAM2/controls/checkbox.lua b/AIResearchGrid/Libs/LAM2/controls/checkbox.lua
new file mode 100644
index 0000000..a777c7d
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/checkbox.lua
@@ -0,0 +1,172 @@
+--[[checkboxData = {
+	type = "checkbox",
+	name = "My Checkbox",
+	tooltip = "Checkbox's tooltip text.",
+	getFunc = function() return db.var end,
+	setFunc = function(value) db.var = value doStuff() end,
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	default = defaults.var,	--(optional)
+	reference = "MyAddonCheckbox"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 7
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("checkbox", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+--label
+local enabledColor = ZO_DEFAULT_ENABLED_COLOR
+local enabledHLcolor = ZO_HIGHLIGHT_TEXT
+local disabledColor = ZO_DEFAULT_DISABLED_COLOR
+local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR
+--checkbox
+local checkboxColor = ZO_NORMAL_TEXT
+local checkboxHLcolor = ZO_HIGHLIGHT_TEXT
+
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	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)
+	if control.value then
+		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+		control.checkbox:SetText(control.checkedText)
+	else
+		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+		control.checkbox:SetText(control.uncheckedText)
+	end
+end
+
+local function UpdateValue(control, forceDefault, value)
+	if forceDefault then	--if we are forcing defaults
+		value = control.data.default
+		control.data.setFunc(value)
+	elseif value ~= nil then	--our value could be false
+		control.data.setFunc(value)
+		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
+		if control.panel.data.registerForRefresh then
+			cm:FireCallbacks("LAM-RefreshPanel", control)
+		end
+	else
+		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
+	if control.value then
+		label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
+	else
+		label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
+	end
+	control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
+end
+
+local function OnMouseExit(control)
+    ZO_Options_OnMouseExit(control)
+
+	if control.isDisabled then return end
+
+	local label = control.label
+	if control.value then
+		label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+	else
+		label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+	end
+	control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
+end
+
+
+--controlName is optional
+function LAMCreateControl.checkbox(parent, checkboxData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or checkboxData.reference)
+	control:SetParent(parent.scroll or parent)
+	control:SetMouseEnabled(true)
+	--control.tooltipText = checkboxData.tooltip
+	control:SetHandler("OnMouseEnter", OnMouseEnter)
+	control:SetHandler("OnMouseExit", OnMouseExit)
+	control:SetHandler("OnMouseUp", function(control)
+			if control.isDisabled then return end
+			PlaySound(SOUNDS.DEFAULT_CLICK)
+			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")
+	label:SetText(checkboxData.name)
+	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+	label:SetHeight(26)
+
+	control.checkbox = wm:CreateControl(nil, control, CT_LABEL)
+	local checkbox = control.checkbox
+	checkbox:SetFont("ZoFontGameBold")
+	checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
+	control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper()
+	control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper()
+
+	local isHalfWidth = checkboxData.width == "half"
+	if isHalfWidth then
+		control:SetDimensions(250, 55)
+		checkbox:SetDimensions(100, 26)
+		checkbox:SetAnchor(BOTTOMRIGHT)
+		label:SetAnchor(TOPLEFT)
+		label:SetAnchor(TOPRIGHT)
+	else
+		control:SetDimensions(510, 30)
+		checkbox:SetDimensions(200, 26)
+		checkbox:SetAnchor(RIGHT)
+		label:SetAnchor(LEFT)
+		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
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/colorpicker.lua b/AIResearchGrid/Libs/LAM2/controls/colorpicker.lua
new file mode 100644
index 0000000..abd9ba4
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/colorpicker.lua
@@ -0,0 +1,140 @@
+--[[colorpickerData = {
+	type = "colorpicker",
+	name = "My Color Picker",
+	tooltip = "Color Picker's tooltip text.",
+	getFunc = function() return db.r, db.g, db.b, db.a end,	--(alpha is optional)
+	setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end,	--(alpha is optional)
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a},	--(optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a])
+	reference = "MyAddonColorpicker"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 5
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	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
+
+local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA)
+	if forceDefault then	--if we are forcing defaults
+		local color = control.data.default
+		valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a
+		control.data.setFunc(valueR, valueG, valueB, valueA)
+	elseif valueR and valueG and valueB then
+		control.data.setFunc(valueR, valueG, valueB, valueA or 1)
+		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
+		if control.panel.data.registerForRefresh then
+			cm:FireCallbacks("LAM-RefreshPanel", control)
+		end
+	else
+		valueR, valueG, valueB, valueA = control.data.getFunc()
+	end
+
+	control.thumb:SetColor(valueR, valueG, valueB, valueA or 1)
+end
+
+
+function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or colorpickerData.reference)
+	control:SetParent(parent.scroll or parent)
+	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)
+	label:SetAnchor(TOPLEFT)
+	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)
+		label:SetDimensions(250, 26)
+		color:SetDimensions(100, 24)
+		color:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
+	else
+		control:SetDimensions(510, 30)
+		label:SetDimensions(300, 26)
+		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")
+	border:SetTextureCoords(0, .625, 0, .8125)
+	border:SetDimensions(40, 22)
+	border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
+
+	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)
+			end
+		end)
+
+	if colorpickerData.warning then
+		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
+		control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0)
+		--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()
+	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
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/custom.lua b/AIResearchGrid/Libs/LAM2/controls/custom.lua
new file mode 100644
index 0000000..54c9775
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/custom.lua
@@ -0,0 +1,45 @@
+--[[customData = {
+	type = "custom",
+	reference = "MyAddonCustomControl",	--(optional) unique name for your control to use as reference
+	refreshFunc = function(customControl) end,	--(optional) function to call when panel/controls refresh
+	width = "full",	--or "half" (optional)
+}	]]
+
+local widgetVersion = 4
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("custom", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local tinsert = table.insert
+
+local function UpdateValue(control)
+	if control.data.refreshFunc then
+		control.data.refreshFunc(control)
+	end
+end
+
+function LAMCreateControl.custom(parent, customData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or customData.reference)
+	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)
+		control:SetDimensions(250, 55)
+	else
+		control:SetDimensionConstraints(510, 30, 510, 100)
+		control:SetDimensions(510, 30)
+	end
+
+	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/AIResearchGrid/Libs/LAM2/controls/description.lua b/AIResearchGrid/Libs/LAM2/controls/description.lua
new file mode 100644
index 0000000..5d7219d
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/description.lua
@@ -0,0 +1,67 @@
+--[[descriptionData = {
+	type = "description",
+	title = "My Title",	--(optional)
+	text = "My description text to display.",
+	width = "full",	--or "half" (optional)
+	reference = "MyAddonDescription"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 4
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("description", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local tinsert = table.insert
+
+local function UpdateValue(control)
+	if control.title then
+		control.title:SetText(control.data.title)
+	end
+	control.desc:SetText(control.data.text)
+end
+
+function LAMCreateControl.description(parent, descriptionData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or descriptionData.reference)
+	control:SetResizeToFitDescendents(true)
+	control:SetParent(parent.scroll or parent)
+	local isHalfWidth = descriptionData.width == "half"
+	if isHalfWidth then
+		control:SetDimensionConstraints(250, 55, 250, 100)
+		control:SetDimensions(250, 55)
+	else
+		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)
+	desc:SetFont("ZoFontGame")
+	desc:SetText(descriptionData.text)
+	desc:SetWidth(isHalfWidth and 250 or 510)
+
+	if descriptionData.title then
+		control.title = wm:CreateControl(nil, control, CT_LABEL)
+		local title = control.title
+		title:SetWidth(isHalfWidth and 250 or 510)
+		title:SetAnchor(TOPLEFT, control, TOPLEFT)
+		title:SetFont("ZoFontWinH4")
+		title:SetText(descriptionData.title)
+		desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT)
+	else
+		desc:SetAnchor(TOPLEFT)
+	end
+
+	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/AIResearchGrid/Libs/LAM2/controls/dropdown.lua b/AIResearchGrid/Libs/LAM2/controls/dropdown.lua
new file mode 100644
index 0000000..94cd820
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/dropdown.lua
@@ -0,0 +1,153 @@
+--[[dropdownData = {
+	type = "dropdown",
+	name = "My Dropdown",
+	tooltip = "Dropdown's tooltip text.",
+	choices = {"table", "of", "choices"},
+	sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted
+	getFunc = function() return db.var end,
+	setFunc = function(var) db.var = var doStuff() end,
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	default = defaults.var,	--(optional)
+	reference = "MyAddonDropdown"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 7
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	else
+		disable = control.data.disabled
+	end
+
+	control.dropdown:SetEnabled(not disable)
+	if disable then
+		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+	else
+		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+	end
+end
+
+local function UpdateValue(control, forceDefault, value)
+	if forceDefault then	--if we are forcing defaults
+		value = control.data.default
+		control.data.setFunc(value)
+		control.dropdown:SetSelectedItem(value)
+	elseif value then
+		control.data.setFunc(value)
+		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
+		if control.panel.data.registerForRefresh then
+			cm:FireCallbacks("LAM-RefreshPanel", control)
+		end
+	else
+		value = control.data.getFunc()
+		control.dropdown:SetSelectedItem(value)
+	end
+end
+
+local function DropdownCallback(choice, 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
+		local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
+		entry.control = control
+		control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE)	--if sort type/order isn't specified, then don't sort
+	end
+end
+
+local function GrabSortingInfo(sortInfo)
+	local t, i = {}, 1
+	for info in string.gmatch(sortInfo, "([^%-]+)") do
+		t[i] = info
+		i = i + 1
+	end
+
+	return t
+end
+
+
+local comboboxCount = 1
+function LAMCreateControl.dropdown(parent, dropdownData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or dropdownData.reference)
+	control:SetParent(parent.scroll or parent)
+	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)
+	label:SetFont("ZoFontWinH4")
+	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 combobox = control.combobox
+	combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
+	combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
+	control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
+	local dropdown = control.dropdown
+	if dropdownData.sort then
+		local sortInfo = GrabSortingInfo(dropdownData.sort)
+		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)
+		label:SetDimensions(250, 26)
+		combobox:SetDimensions(225, 26)
+		combobox:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
+	else
+		control:SetDimensions(510, 30)
+		label:SetDimensions(300, 26)
+		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()
+	end
+	control.UpdateChoices = UpdateChoices
+	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
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/editbox.lua b/AIResearchGrid/Libs/LAM2/controls/editbox.lua
new file mode 100644
index 0000000..0d273d3
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/editbox.lua
@@ -0,0 +1,155 @@
+--[[editboxData = {
+	type = "editbox",
+	name = "My Editbox",
+	tooltip = "Editbox's tooltip text.",
+	getFunc = function() return db.text end,
+	setFunc = function(text) db.text = text doStuff() end,
+	isMultiline = true,	--boolean
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	default = defaults.text,	--(optional)
+	reference = "MyAddonEditbox"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 6
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("editbox", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local tinsert = table.insert
+
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	else
+		disable = control.data.disabled
+	end
+
+	if disable then
+		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+		control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
+	else
+		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+		control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+	end
+	--control.editbox:SetEditEnabled(not disable)
+	control.editbox:SetMouseEnabled(not disable)
+end
+
+local function UpdateValue(control, forceDefault, value)
+	if forceDefault then	--if we are forcing defaults
+		value = control.data.default
+		control.data.setFunc(value)
+		control.editbox:SetText(value)
+	elseif value then
+		control.data.setFunc(value)
+		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
+		if control.panel.data.registerForRefresh then
+			cm:FireCallbacks("LAM-RefreshPanel", control)
+		end
+	else
+		value = control.data.getFunc()
+		control.editbox:SetText(value)
+	end
+end
+
+
+function LAMCreateControl.editbox(parent, editboxData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or editboxData.reference)
+	control:SetParent(parent.scroll or parent)
+	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)
+				if self:HasFocus() then	--only set focus to new spots if the editbox is currently in use
+					local cursorPos = self:GetCursorPosition()
+					local text = self:GetText()
+					local textLen = text:len()
+					local newPos
+					if delta > 0 then	--scrolling up
+						local reverseText = text:reverse()
+						local revCursorPos = textLen - cursorPos
+						local revPos = reverseText:find("\n", revCursorPos+1)
+						newPos = revPos and textLen - revPos
+					else	--scrolling down
+						newPos = text:find("\n", cursorPos+1)
+					end
+					if newPos then	--if we found a new line, then scroll, otherwise don't
+						self:SetCursorPosition(newPos)
+					end
+				end
+			end)
+	else
+		control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop")
+	end
+	local editbox = control.editbox
+	editbox:SetText(editboxData.getFunc())
+	editbox:SetMaxInputChars(3000)
+	editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end)
+	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)
+		label:SetDimensions(250, 26)
+		bg:SetDimensions(225, editboxData.isMultiline and 74 or 24)
+		bg:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
+		if editboxData.isMultiline then
+			editbox:SetDimensionConstraints(210, 74, 210, 500)
+		end
+	else
+		control:SetDimensions(510, 30)
+		label:SetDimensions(300, 26)
+		bg:SetDimensions(200, editboxData.isMultiline and 100 or 24)
+		bg:SetAnchor(TOPRIGHT)
+		if editboxData.isMultiline then
+			editbox:SetDimensionConstraints(185, 100, 185, 500)
+		end
+	end
+
+	if editboxData.warning then
+		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
+		control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0)
+		--control.warning.tooltipText = editboxData.warning
+		control.warning.data = {tooltipText = editboxData.warning}
+	end
+
+	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()
+	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
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/header.lua b/AIResearchGrid/Libs/LAM2/controls/header.lua
new file mode 100644
index 0000000..bbf2c60
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/header.lua
@@ -0,0 +1,47 @@
+--[[headerData = {
+	type = "header",
+	name = "My Header",
+	width = "full",	--or "half" (optional)
+	reference = "MyAddonHeader"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 4
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("header", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local tinsert = table.insert
+
+local function UpdateValue(control)
+	control.header:SetText(control.data.name)
+end
+
+function LAMCreateControl.header(parent, headerData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or headerData.reference)
+	control:SetParent(parent.scroll or parent)
+	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)
+	divider:SetAnchor(TOPLEFT)
+
+	control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
+	local header = control.header
+	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/AIResearchGrid/Libs/LAM2/controls/panel.lua b/AIResearchGrid/Libs/LAM2/controls/panel.lua
new file mode 100644
index 0000000..5f9f41b
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/panel.lua
@@ -0,0 +1,138 @@
+--[[panelData = {
+	type = "panel",
+	name = "Window Title",
+	displayName = "My Longer Window Title",	--(optional) (can be useful for long addon names or if you want to colorize it)
+	author = "Seerah",	--(optional)
+	version = "2.0",	--(optional)
+	slashCommand = "/myaddon",	--(optional) will register a keybind to open to this panel (don't forget to include the slash!)
+	registerForRefresh = true,	--boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown)
+	registerForDefaults = true,	--boolean (optional) (will set all options controls back to default values)
+	resetFunc = function() print("defaults reset") end,	--(optional) custom function to run after settings are reset to defaults
+}	]]
+
+
+local widgetVersion = 8
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("panel", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+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.UpdateValue then
+				updateControl:UpdateValue()
+			end
+			if updateControl.UpdateDisabled then
+				updateControl:UpdateDisabled()
+			end
+		end
+	end
+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"] = {
+	title = {
+		text = SI_OPTIONS_RESET_TITLE,
+	},
+	mainText = {
+		text = SI_OPTIONS_RESET_PROMPT,
+		align = TEXT_ALIGN_CENTER,
+	},
+	buttons = {
+		[1] = {
+			text = SI_OPTIONS_RESET,
+			callback = function(dialog) ForceDefaults(dialog.data[1]) end,
+		},
+		[2] = {
+			text = SI_DIALOG_CANCEL,
+		},
+	},
+}
+
+local callbackRegistered = false
+LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1
+function LAMCreateControl.panel(parent, panelData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName)
+	control:SetParent(parent)
+
+	control.bg = wm:CreateControl(nil, control, CT_BACKDROP)
+	local bg = control.bg
+	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
+		info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin")
+		info:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
+		info:SetHeight(13)
+		info:SetAnchor(TOPRIGHT, control, BOTTOMRIGHT, -5, 2)
+		if panelData.author and panelData.version then
+			--info:SetText("Version: "..panelData.version.."  -  "..GetString(SI_ADDON_MANAGER_AUTHOR)..": "..panelData.author)
+			info:SetText(string.format("Version: %s  -  %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
+		elseif panelData.author then
+			info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
+		else
+			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
+	container:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 20)
+	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
+		defaultButton:SetFont("ZoFontDialogKeybindDescription")
+		defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+		--defaultButton:SetText("Reset To Defaults")
+		defaultButton:SetText(GetString(SI_OPTIONS_RESET_TITLE))
+		defaultButton:SetDimensions(200, 30)
+		defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2)
+		defaultButton:SetHandler("OnClicked", function()
+				ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control})
+			end)
+	end
+
+	if panelData.registerForRefresh and not callbackRegistered then	--don't want to register our callback more than once
+		cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel)
+		callbackRegistered = true
+	end
+
+	control.data = panelData
+	control.controlsToRefresh = {}
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/slider.lua b/AIResearchGrid/Libs/LAM2/controls/slider.lua
new file mode 100644
index 0000000..f7ab0a3
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/slider.lua
@@ -0,0 +1,184 @@
+--[[sliderData = {
+	type = "slider",
+	name = "My Slider",
+	tooltip = "Slider's tooltip text.",
+	min = 0,
+	max = 20,
+	step = 1,	--(optional)
+	getFunc = function() return db.var end,
+	setFunc = function(value) db.var = value doStuff() end,
+	width = "full",	--or "half" (optional)
+	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
+	warning = "Will need to reload the UI.",	--(optional)
+	default = defaults.var,	--(optional)
+	reference = "MyAddonSlider"	--(optional) unique global reference to control
+}	]]
+
+
+local widgetVersion = 5
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("slider", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local cm = CALLBACK_MANAGER
+local round = zo_round
+local strformat = string.format
+local tinsert = table.insert
+
+local function UpdateDisabled(control)
+	local disable
+	if type(control.data.disabled) == "function" then
+		disable = control.data.disabled()
+	else
+		disable = control.data.disabled
+	end
+
+	control.slider:SetEnabled(not disable)
+	control.slidervalue:SetEditEnabled(not disable)
+	if disable then
+		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+		control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+		control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+		control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
+	else
+		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+		control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+		control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+		control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
+	end
+end
+
+local function UpdateValue(control, forceDefault, value)
+	if forceDefault then	--if we are forcing defaults
+		value = control.data.default
+		control.data.setFunc(value)
+	elseif value and value >= control.data.min and value <= control.data.max then
+		control.data.setFunc(value)
+		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
+		if control.panel.data.registerForRefresh then
+			cm:FireCallbacks("LAM-RefreshPanel", control)
+		end
+	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 isHalfWidth = sliderData.width == "half"
+	if isHalfWidth then
+		control:SetDimensions(250, 55)
+	else
+		control:SetDimensions(510, 40)
+	end
+	control:SetMouseEnabled(true)
+	--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")
+	label:SetDimensions(isHalfWidth and 250 or 300, 26)
+	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
+	slider:SetDimensions(190, 14)
+	if isHalfWidth then
+		slider:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT, -5, 2)
+	else
+		slider:SetAnchor(RIGHT, control, RIGHT, -5, -5)
+	end
+	slider:SetMouseEnabled(true)
+	slider:SetOrientation(ORIENTATION_HORIZONTAL)
+	--put nil for highlighted texture file path, and what look to be texture coords
+	slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16)
+	local minValue = sliderData.min
+	local maxValue = sliderData.max
+	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")
+	minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT)
+	minText:SetText(sliderData.min)
+
+	control.maxText = wm:CreateControl(nil, slider, CT_LABEL)
+	local maxText = control.maxText
+	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)
+	control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop")
+	local slidervalue = control.slidervalue
+	slidervalue:ClearAnchors()
+	slidervalue:SetAnchor(TOPLEFT, slidervaluebg, TOPLEFT, 3, 1)
+	slidervalue:SetAnchor(BOTTOMRIGHT, slidervaluebg, BOTTOMRIGHT, -3, -1)
+	slidervalue:SetTextType(TEXT_TYPE_NUMERIC)
+	slidervalue:SetFont("ZoFontGameSmall")
+	slidervalue:SetHandler("OnEscape", function(self)
+			self:LoseFocus()
+			control:UpdateValue()
+		end)
+	slidervalue:SetHandler("OnEnter", function(self)
+			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)
+			if eventReason == EVENT_REASON_SOFTWARE then return end
+			self:SetValue(value)	--do we actually need this line?
+			slidervalue:SetText(value)
+		end)
+	slider:SetHandler("OnSliderReleased", function(self, value)
+			--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()
+	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
+
+	return control
+end
\ No newline at end of file
diff --git a/AIResearchGrid/Libs/LAM2/controls/submenu.lua b/AIResearchGrid/Libs/LAM2/controls/submenu.lua
new file mode 100644
index 0000000..761dda5
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/submenu.lua
@@ -0,0 +1,123 @@
+--[[submenuData = {
+	type = "submenu",
+	name = "Submenu Title",
+	tooltip = "My submenu tooltip",	--(optional)
+	controls = {sliderData, buttonData}	--(optional) used by LAM
+	reference = "MyAddonSubmenu"	--(optional) unique global reference to control
+}	]]
+
+local widgetVersion = 7
+local LAM = LibStub("LibAddonMenu-2.0")
+if not LAM:RegisterWidget("submenu", widgetVersion) then return end
+
+local wm = WINDOW_MANAGER
+local am = ANIMATION_MANAGER
+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
+
+local function AnimateSubmenu(clicked)
+	local control = clicked:GetParent()
+	control.open = not control.open
+
+	if control.open then
+		control.animation:PlayFromStart()
+	else
+		control.animation:PlayFromEnd()
+	end
+end
+
+
+function LAMCreateControl.submenu(parent, submenuData, controlName)
+	local control = wm:CreateTopLevelWindow(controlName or submenuData.reference)
+	control:SetParent(parent.scroll or parent)
+	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)
+	label:SetDimensions(520, 30)
+	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+	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)
+	scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10)
+	scroll:SetDimensionConstraints(525, 0, 525, 2500)
+
+	control.bg = wm:CreateControl(nil, label, CT_BACKDROP)
+	local bg = control.bg
+	bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5)
+	bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0)
+	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)
+	animation:SetHandler("OnStop", function(self, completedPlaying)
+			scroll:SetResizeToFitDescendents(control.open)
+			if control.open then
+				control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds")
+				scroll:SetResizeToFitPadding(5, 20)
+			else
+				control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds")
+				scroll:SetResizeToFitPadding(5, 0)
+				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
+	btmToggle:SetMouseEnabled(true)
+	btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT)
+	btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT)
+	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/AIResearchGrid/Libs/LAM2/controls/texture.lua b/AIResearchGrid/Libs/LAM2/controls/texture.lua
new file mode 100644
index 0000000..928ab82
--- /dev/null
+++ b/AIResearchGrid/Libs/LAM2/controls/texture.lua
@@ -0,0 +1,51 @@
+--[[textureData = {
+	type = "texture",
+	image = "file/path.dds",
+	imageWidth = 64,	--max of 250 for half width, 510 for full
+	imageHeight = 32,	--max of 100
+	tooltip = "Image's tooltip text.",	--(optional)
+	width = "full",	--or "half" (optional)
+	reference = "MyAddonTexture"	--(optional) unique global reference to control
+}	]]
+
+--add texture coords support?
+
+local widgetVersion = 5
+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)
+	control:SetResizeToFitDescendents(true)
+	control:SetParent(parent.scroll or parent)
+
+	local isHalfWidth = textureData.width == "half"
+	if isHalfWidth then
+		control:SetDimensionConstraints(250, 55, 250, 100)
+		control:SetDimensions(250, 55)
+	else
+		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
+		texture.data = {tooltipText = textureData.tooltip}
+		texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+		texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit)
+	end
+
+	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
diff --git a/AIResearchGrid/Libs/LibStub/LibStub.lua b/AIResearchGrid/Libs/LibStub/LibStub.lua
new file mode 100644
index 0000000..879d132
--- /dev/null
+++ b/AIResearchGrid/Libs/LibStub/LibStub.lua
@@ -0,0 +1,34 @@
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+-- LibStub developed for World of Warcraft by above members of the WowAce community.
+-- Ported to Elder Scrolls Online by Seerah
+
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+local strformat = string.format
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(strformat("Cannot find a library instance of %q.", tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	function LibStub:IterateLibraries() return pairs(self.libs) end
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/AIResearchGrid/README b/AIResearchGrid/README
new file mode 100644
index 0000000..37685a4
--- /dev/null
+++ b/AIResearchGrid/README
@@ -0,0 +1 @@
+This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates. The Elder Scrolls® and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries. All rights reserved.
\ No newline at end of file
diff --git a/AIresearchGridConfig.lua b/AIresearchGridConfig.lua
deleted file mode 100644
index 97a239d..0000000
--- a/AIresearchGridConfig.lua
+++ /dev/null
@@ -1,67 +0,0 @@
-function AIRG.CreateConfigMenu()
-    local charList = {}
-    table.insert(charList,"")
-    for charName, _ in pairs(AIRG.vars.data) do
-        table.insert(charList, charName)
-    end
-
-    local panelData = {
-        type = "panel",
-        name = "AI Research Grid",
-        displayName = "|c8080FFAI Research Grid|r",
-        author = "Stormknight & CrazyDutchGuy",
-        version = tostring(AIRG.version),
-    }
-
-    local optionsData = {
-    -- GENERAL SECTION
-        {
-            type = "header",
-            name = AIRG.L["General Options"],
-        },
-        {
-            type = "checkbox",
-            name = AIRG.L["Show Motifs"],
-            tooltip = AIRG.L["Show Motifs Long"],
-            getFunc = function() return AIRG.vars.showMotifs end,
-            setFunc = function(newValue)
-                    AIRG.vars.showMotifs = newValue
-                    AIRG.UI.motifSection:SetHidden(not newValue)
-                    AIRG.UI.BottomDivider:SetHidden(not newValue)
-                    AIResearchGrid:SetHeight(newValue and 756 or 636)
-                end,
-        },
-        -- CHARACTER DELETION SECTION
-        {
-            type = "header",
-            name = AIRG.L["Characters"],
-        },
-        {
-            type = "dropdown",
-            name = AIRG.L["CharacterSelect"],
-            choices = charList,
-            getFunc = function() return "" end,
-            setFunc = function(newValue) AIRG.charToDelete = newValue	end,
-        },
-        {
-            type = "button",
-            name = AIRG.L["Delete"],
-            tooltip = AIRG.L["DeleteDesc"],
-            func = function() AIRG.DeleteCharacter(AIRG.charToDelete) end,
-        },
-        -- KEYBINDS SECTION
-        {
-            type = "header",
-            name = AIRG.L["Keybinds"],
-        },
-        {
-            type = "description",
-            text = AIRG.L["Keybind Text"],
-        },
-    }
-
-    local LAM2 = LibStub("LibAddonMenu-2.0")
-    LAM2:RegisterAddonPanel(AIRG.name.."Config", panelData)
-    LAM2:RegisterOptionControls(AIRG.name.."Config", optionsData)
-
-end -- AIRG.CreateConfigMenu
diff --git a/Bindings.xml b/Bindings.xml
deleted file mode 100644
index ddd3193..0000000
--- a/Bindings.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<Bindings>
-  <Layer name="SI_KEYBINDINGS_LAYER_GENERAL">
-    <Category name="|c8080FFAI Research Grid|r">
-      <Action name="TOGGLE_AIRG">
-        <Down>AIRG.ToggleMainWindow()</Down>
-      </Action>
-    </Category>
-  </Layer>
-</Bindings>
\ No newline at end of file
diff --git a/Language/de.lua b/Language/de.lua
deleted file mode 100644
index 7aeffd1..0000000
--- a/Language/de.lua
+++ /dev/null
@@ -1,21 +0,0 @@
--- Language file: GERMAN
-
-function AIRG.InitialiseLanguage()
-    AIRG.L = {}
-
-    -- Settings / Config menu stuff
-    AIRG.L["General Options"]                       = "|c45D7F7Generelle Einstellungen|r"
-    AIRG.L["Keybinds"]                              = "|c45D7F7Tastenbelegung|r"
-    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
-
-    AIRG.L["Show Motifs"]                           = "Zeige Motive?"
-    AIRG.L["Show Motifs Long"]                      = "Zeige Motive in der Fuzeile vom Research Grid Addon."
-
-    AIRG.L["Characters"]                            = "|c45D7F7Charakter Lschen|r"
-    AIRG.L["CharacterSelect"]                       = "Whle Charakter"
-    AIRG.L["Delete"]                                = "Lschen"
-    AIRG.L["DeleteDesc"]                            = "Klicke diesen Button um die Daten des selektierten Charakters zu lschen."
-
-    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Daten des aktuellen Charakters lschen nicht mglich."
-    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Lsche Charakterdaten fr "
-end
\ No newline at end of file
diff --git a/Language/en.lua b/Language/en.lua
deleted file mode 100644
index fcf2616..0000000
--- a/Language/en.lua
+++ /dev/null
@@ -1,21 +0,0 @@
--- Language file: ENGLISH
-
-function AIRG.InitialiseLanguage()
-    AIRG.L = {}
-
-    -- Settings / Config menu stuff
-    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
-    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
-    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
-
-    AIRG.L["Show Motifs"]                           = "Show Motifs?"
-    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
-
-    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
-    AIRG.L["CharacterSelect"]                       = "Select Character"
-    AIRG.L["Delete"]                                = "Delete"
-    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
-
-    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
-    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
-end
\ No newline at end of file
diff --git a/Language/fr.lua b/Language/fr.lua
deleted file mode 100644
index fcf2616..0000000
--- a/Language/fr.lua
+++ /dev/null
@@ -1,21 +0,0 @@
--- Language file: ENGLISH
-
-function AIRG.InitialiseLanguage()
-    AIRG.L = {}
-
-    -- Settings / Config menu stuff
-    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
-    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
-    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
-
-    AIRG.L["Show Motifs"]                           = "Show Motifs?"
-    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
-
-    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
-    AIRG.L["CharacterSelect"]                       = "Select Character"
-    AIRG.L["Delete"]                                = "Delete"
-    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
-
-    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
-    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
-end
\ No newline at end of file
diff --git a/Language/ru.lua b/Language/ru.lua
deleted file mode 100644
index fcf2616..0000000
--- a/Language/ru.lua
+++ /dev/null
@@ -1,21 +0,0 @@
--- Language file: ENGLISH
-
-function AIRG.InitialiseLanguage()
-    AIRG.L = {}
-
-    -- Settings / Config menu stuff
-    AIRG.L["General Options"]                       = "|c45D7F7General Options|r"
-    AIRG.L["Keybinds"]                              = "|c45D7F7Keybinds|r"
-    AIRG.L["Keybind Text"]                          = "Use ESC -> CONTROLS -> Keybindings to create a hotkey to open and close AI Research Grid."
-
-    AIRG.L["Show Motifs"]                           = "Show Motifs?"
-    AIRG.L["Show Motifs Long"]                      = "Show motifs along the bottom of the Research Grid addon."
-
-    AIRG.L["Characters"]                            = "|c45D7F7Character Deletion|r"
-    AIRG.L["CharacterSelect"]                       = "Select Character"
-    AIRG.L["Delete"]                                = "Delete"
-    AIRG.L["DeleteDesc"]                            = "Click this button to delete data for the selected character."
-
-    AIRG.L["DeleteFalse"]                           = "|c8080ffAI Research Grid|r: Can't delete data for the current character."
-    AIRG.L["DeleteTrue"]                            = "|c8080ffAI Research Grid|r: Deleted character data for "
-end
\ No newline at end of file
diff --git a/Libs/LAM2/LibAddonMenu-2.0.lua b/Libs/LAM2/LibAddonMenu-2.0.lua
deleted file mode 100644
index 1ab94cf..0000000
--- a/Libs/LAM2/LibAddonMenu-2.0.lua
+++ /dev/null
@@ -1,322 +0,0 @@
---	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.								--
---------------------------------------------------------------
-
-
---Register LAM with LibStub
-local MAJOR, MINOR = "LibAddonMenu-2.0", 16
-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
-
-
---UPVALUES--
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-local optionsWindow = ZO_OptionsWindowSettingsScrollChild
-local _
-
-local addonsForList = {}
-local addonToOptionsMap = {}
-local optionsCreated = {}
-lam.widgets = lam.widgets or {}
-local widgets = lam.widgets
-
-
---METHOD: REGISTER WIDGET--
---each widget has its version checked before loading,
---so we only have the most recent one in memory
---Usage:
---	widgetType = "string"; the type of widget being registered
---	widgetVersion = integer; the widget's version number
-LAMCreateControl = LAMCreateControl or {}
-local lamcc = LAMCreateControl
-
-function lam:RegisterWidget(widgetType, widgetVersion)
-	if widgets[widgetType] and widgets[widgetType] >= widgetVersion then
-		return false
-	else
-		widgets[widgetType] = widgetVersion
-		return true
-	end
-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")]
-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)
-end
-
-
---INTERNAL FUNCTION
---creates controls when options panel is first shown
---controls anchoring of these controls in the panel
-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
-			if widgetType == "submenu" then
-				local submenu = LAMCreateControl[widgetType](panel, widgetData)
-				if lastAddedControl then
-					submenu:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
-				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"
-					if lastAddedControlSub then
-						if lacAtHalfRowSub and isHalf then
-							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, TOPRIGHT, 5, 0)
-							lacAtHalfRowSub = false
-						else
-							subWidget:SetAnchor(TOPLEFT, lastAddedControlSub, BOTTOMLEFT, 0, 15)
-							lacAtHalfRowSub = isHalf and true or false
-							lastAddedControlSub = subWidget
-						end
-					else
-						subWidget:SetAnchor(TOPLEFT)
-						lacAtHalfRowSub = isHalf and true or false
-						lastAddedControlSub = subWidget
-					end
-				end
-			else
-				local widget = LAMCreateControl[widgetType](panel, widgetData)
-				local isHalf = widgetData.width == "half"
-				if lastAddedControl then
-					if lacAtHalfRow and isHalf then
-						widget:SetAnchor(TOPLEFT, lastAddedControl, TOPRIGHT, 10, 0)
-						lacAtHalfRow = false
-					else
-						widget:SetAnchor(TOPLEFT, lastAddedControl, BOTTOMLEFT, 0, 15)
-						lacAtHalfRow = isHalf and true or false
-						lastAddedControl = widget
-					end
-				else
-					widget:SetAnchor(TOPLEFT)
-					lacAtHalfRow = isHalf and true or false
-					lastAddedControl = widget
-				end
-			end
-		end
-	end
-
-	optionsCreated[addonID] = true
-	cm:FireCallbacks("LAM-PanelControlsCreated", panel)
-end
-
-
---INTERNAL FUNCTION
---handles switching between panels
-local function ToggleAddonPanels(panel)	--called in OnShow of newly shown panel
-	local currentlySelected = LAMAddonPanelsMenu.currentlySelected
-	if currentlySelected and currentlySelected ~= panel then
-		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
-
-
---METHOD: REGISTER ADDON PANEL
---registers your addon with LibAddonMenu and creates a panel
---Usage:
---	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)
-	local panel = lamcc.panel(nil, panelData, addonID)	--addonID==global name of panel
-	panel:SetHidden(true)
-	panel:SetAnchor(TOPLEFT, LAMAddonPanelsMenu, TOPRIGHT, 10, 0)
-	panel:SetAnchor(BOTTOMLEFT, LAMAddonPanelsMenu, BOTTOMRIGHT, 10, 0)
-	panel:SetWidth(549)
-	panel:SetDrawLayer(DL_OVERLAY)
-	tinsert(addonsForList, {panel = addonID, name = panelData.name})
-	panel:SetHandler("OnShow", ToggleAddonPanels)
-	if panelData.slashCommand then
-		SLASH_COMMANDS[panelData.slashCommand] = function()
-			lam:OpenToPanel(panel)
-		end
-	end
-
-	return panel	--return for authors creating options manually
-end
-
-
---METHOD: REGISTER OPTION CONTROLS
---registers the options you want shown for your addon
---these are stored in a table where each key-value pair is the order
---of the options in the panel and the data for that control, respectively
---see exampleoptions.lua for an example
---see controls\<widget>.lua for each widget type
---Usage:
---	addonID = "string"; the same string passed to :RegisterAddonPanel
---	optionsTable = table; the table containing all of the options controls and their data
-function lam:RegisterOptionControls(addonID, optionsTable)	--optionsTable = {sliderData, buttonData, etc}
-	addonToOptionsMap[addonID] = optionsTable
-end
-
-
---INTERNAL FUNCTION
---handles switching between LAM's Addon Settings panel and other panels in the Settings menu
-local oldDefaultButton = ZO_OptionsWindowResetToDefaultButton
-local oldCallback = oldDefaultButton.callback
-local dummyFunc = function() end
-local panelWindow = ZO_OptionsWindow
-local bgL = ZO_OptionsWindowBGLeft
-local bgR = ZO_OptionsWindowBGLeftBGRight
-local function HandlePanelSwitching(self, panel)
-	if panel == lam.panelID then	--our addon settings panel
-		oldDefaultButton:SetCallback(dummyFunc)
-		oldDefaultButton:SetHidden(true)
-		oldDefaultButton:SetAlpha(0)	--just because it still bugs out
-		panelWindow:SetDimensions(999, 960)
-		bgL:SetWidth(666)
-		bgR:SetWidth(333)
-	else
-		local shown = LAMAddonPanelsMenu.currentlySelected
-		if shown then shown:SetHidden(true) end
-		oldDefaultButton:SetCallback(oldCallback)
-		oldDefaultButton:SetHidden(false)
-		oldDefaultButton:SetAlpha(1)
-		panelWindow:SetDimensions(768, 914)
-		bgL:SetWidth(512)
-		bgR:SetWidth(256)
-	end
-end
-
-
---INTERNAL FUNCTION
---creates LAM's Addon Settings panel
-local function CreateAddonSettingsPanel()
-	if not LAMSettingsPanelCreated then
-		local controlPanelID = "LAM_ADDON_SETTINGS_PANEL"
-		--Russian for TERAB1T's RuESO addon, which creates an "ru" locale
-		--game font does not support Cyrillic, so they are using custom fonts + extended latin charset
-		--Spanish provided by Luisen75 for their translation project
-		local controlPanelNames = {
-			en = "Addon Settings",
-			fr = "Extensions",
-			de = "Erweiterungen",
-			ru = "Îacòpoéêè äoïoìîeîèé",
-			es = "Configura Addons",
-		}
-
-		ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelNames[GetCVar("Language.2")] or controlPanelName["en"])
-
-		lam.panelID = _G[controlPanelID]
-
-		--ZO_PreHook("ZO_OptionsWindow_ChangePanels", HandlePanelSwitching)
-		ZO_PreHook(ZO_SharedOptions, "ChangePanels", HandlePanelSwitching)
-
-		LAMSettingsPanelCreated = true
-	end
-end
-
-
---INTERNAL FUNCTION
---adds each registered addon to the menu in LAM's panel
-local function CreateAddonButtons(list, addons)
-	for i = 1, #addons do
-		local button = wm:CreateControlFromVirtual("LAMAddonMenuButton"..i, list.scrollChild, "ZO_DefaultTextButton")
-		button.name = addons[i].name
-		button.panel = _G[addons[i].panel]
-		button:SetText(button.name)
-		button:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-		button:SetWidth(190)
-		if i == 1 then
-			button:SetAnchor(TOPLEFT, list.scrollChild, TOPLEFT, 5, 5)
-		else
-			button:SetAnchor(TOPLEFT, _G["LAMAddonMenuButton"..i-1], BOTTOMLEFT)
-		end
-		button:SetHandler("OnClicked", function(self) self.panel:SetHidden(false) end)
-	end
-end
-
-
---INTERNAL FUNCTION
---creates the left-hand menu in LAM's panel
-local function CreateAddonList()
-	local list
-	--check if an earlier loaded copy of LAM created it already
-	list = LAMAddonPanelsMenu or wm:CreateControlFromVirtual("LAMAddonPanelsMenu", optionsWindow, "ZO_ScrollContainer")
-	list:ClearAnchors()
-	list:SetAnchor(TOPLEFT)
-	list:SetHeight(675)
-	list:SetWidth(200)
-
-	list.bg = list.bg or wm:CreateControl(nil, list, CT_BACKDROP)
-	local bg = list.bg
-	bg:SetAnchorFill()	--offsets of 8?
-	bg:SetEdgeTexture("EsoUI\\Art\\miscellaneous\\borderedinsettransparent_edgefile.dds", 128, 16)
-	bg:SetCenterColor(0, 0, 0, 0)
-
-	list.scrollChild = LAMAddonPanelsMenuScrollChild
-	list.scrollChild:SetResizeToFitPadding(0, 15)
-
-	local generatedButtons
-	list:SetHandler("OnShow", function(self)
-			if not generatedButtons and #addonsForList > 0 then
-				--we're about to show our list for the first time - let's sort the buttons before creating them
-				table.sort(addonsForList, function(a, b)
-						return a.name < b.name
-					end)
-				CreateAddonButtons(list, addonsForList)
-				self.currentlySelected = LAMAddonMenuButton1 and LAMAddonMenuButton1.panel
-				--since our addon panels don't have a parent, let's make sure they hide when we're done with them
-				ZO_PreHookHandler(ZO_OptionsWindow, "OnHide", function() self.currentlySelected:SetHidden(true) end)
-				generatedButtons = true
-			end
-			if self.currentlySelected then self.currentlySelected:SetHidden(false) end
-		end)
-
-	--list.controlType = OPTIONS_CUSTOM
-	--list.panel = lam.panelID
-	list.data = {
-		controlType = OPTIONS_CUSTOM,
-		panel = lam.panelID,
-	}
-
-	ZO_OptionsWindow_InitializeControl(list)
-
-	return list
-end
-
-
---INITIALIZING
-CreateAddonSettingsPanel()
-CreateAddonList()
-
diff --git a/Libs/LAM2/controls/button.lua b/Libs/LAM2/controls/button.lua
deleted file mode 100644
index 187e901..0000000
--- a/Libs/LAM2/controls/button.lua
+++ /dev/null
@@ -1,89 +0,0 @@
---[[buttonData = {
-	type = "button",
-	name = "My Button",
-	tooltip = "Button's tooltip text.",
-	func = function() end,
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	icon = "icon\\path.dds",	--(optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	reference = "MyAddonButton"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 5
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("button", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	else
-		disable = control.data.disabled
-	end
-
-	control.button:SetEnabled(not disable)
-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 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)
-		control.button:SetNormalTexture(buttonData.icon)
-		control.button:SetPressedOffset(2, 2)
-	else
-		--control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton")
-		control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton")
-		control.button:SetWidth(isHalfWidth and 180 or 200)
-		control.button:SetText(buttonData.name)
-	end
-	local button = control.button
-	button:SetAnchor(isHalfWidth and CENTER or RIGHT)
-	button:SetClickSound("Click")
-	--button.tooltipText = buttonData.tooltip
-	button.data = {tooltipText = buttonData.tooltip}
-	button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-	button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-	button:SetHandler("OnClicked", function(self, ...)
-			buttonData.func(self, ...)
-			if control.panel.data.registerForRefresh then
-				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/LAM2/controls/checkbox.lua b/Libs/LAM2/controls/checkbox.lua
deleted file mode 100644
index a777c7d..0000000
--- a/Libs/LAM2/controls/checkbox.lua
+++ /dev/null
@@ -1,172 +0,0 @@
---[[checkboxData = {
-	type = "checkbox",
-	name = "My Checkbox",
-	tooltip = "Checkbox's tooltip text.",
-	getFunc = function() return db.var end,
-	setFunc = function(value) db.var = value doStuff() end,
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	default = defaults.var,	--(optional)
-	reference = "MyAddonCheckbox"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 7
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("checkbox", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
---label
-local enabledColor = ZO_DEFAULT_ENABLED_COLOR
-local enabledHLcolor = ZO_HIGHLIGHT_TEXT
-local disabledColor = ZO_DEFAULT_DISABLED_COLOR
-local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR
---checkbox
-local checkboxColor = ZO_NORMAL_TEXT
-local checkboxHLcolor = ZO_HIGHLIGHT_TEXT
-
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	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)
-	if control.value then
-		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-		control.checkbox:SetText(control.checkedText)
-	else
-		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-		control.checkbox:SetText(control.uncheckedText)
-	end
-end
-
-local function UpdateValue(control, forceDefault, value)
-	if forceDefault then	--if we are forcing defaults
-		value = control.data.default
-		control.data.setFunc(value)
-	elseif value ~= nil then	--our value could be false
-		control.data.setFunc(value)
-		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	else
-		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
-	if control.value then
-		label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
-	else
-		label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
-	end
-	control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
-end
-
-local function OnMouseExit(control)
-    ZO_Options_OnMouseExit(control)
-
-	if control.isDisabled then return end
-
-	local label = control.label
-	if control.value then
-		label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-	else
-		label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-	end
-	control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
-end
-
-
---controlName is optional
-function LAMCreateControl.checkbox(parent, checkboxData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or checkboxData.reference)
-	control:SetParent(parent.scroll or parent)
-	control:SetMouseEnabled(true)
-	--control.tooltipText = checkboxData.tooltip
-	control:SetHandler("OnMouseEnter", OnMouseEnter)
-	control:SetHandler("OnMouseExit", OnMouseExit)
-	control:SetHandler("OnMouseUp", function(control)
-			if control.isDisabled then return end
-			PlaySound(SOUNDS.DEFAULT_CLICK)
-			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")
-	label:SetText(checkboxData.name)
-	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-	label:SetHeight(26)
-
-	control.checkbox = wm:CreateControl(nil, control, CT_LABEL)
-	local checkbox = control.checkbox
-	checkbox:SetFont("ZoFontGameBold")
-	checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
-	control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper()
-	control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper()
-
-	local isHalfWidth = checkboxData.width == "half"
-	if isHalfWidth then
-		control:SetDimensions(250, 55)
-		checkbox:SetDimensions(100, 26)
-		checkbox:SetAnchor(BOTTOMRIGHT)
-		label:SetAnchor(TOPLEFT)
-		label:SetAnchor(TOPRIGHT)
-	else
-		control:SetDimensions(510, 30)
-		checkbox:SetDimensions(200, 26)
-		checkbox:SetAnchor(RIGHT)
-		label:SetAnchor(LEFT)
-		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
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/colorpicker.lua b/Libs/LAM2/controls/colorpicker.lua
deleted file mode 100644
index abd9ba4..0000000
--- a/Libs/LAM2/controls/colorpicker.lua
+++ /dev/null
@@ -1,140 +0,0 @@
---[[colorpickerData = {
-	type = "colorpicker",
-	name = "My Color Picker",
-	tooltip = "Color Picker's tooltip text.",
-	getFunc = function() return db.r, db.g, db.b, db.a end,	--(alpha is optional)
-	setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end,	--(alpha is optional)
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a},	--(optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a])
-	reference = "MyAddonColorpicker"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 5
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	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
-
-local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA)
-	if forceDefault then	--if we are forcing defaults
-		local color = control.data.default
-		valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a
-		control.data.setFunc(valueR, valueG, valueB, valueA)
-	elseif valueR and valueG and valueB then
-		control.data.setFunc(valueR, valueG, valueB, valueA or 1)
-		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	else
-		valueR, valueG, valueB, valueA = control.data.getFunc()
-	end
-
-	control.thumb:SetColor(valueR, valueG, valueB, valueA or 1)
-end
-
-
-function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or colorpickerData.reference)
-	control:SetParent(parent.scroll or parent)
-	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)
-	label:SetAnchor(TOPLEFT)
-	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)
-		label:SetDimensions(250, 26)
-		color:SetDimensions(100, 24)
-		color:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
-	else
-		control:SetDimensions(510, 30)
-		label:SetDimensions(300, 26)
-		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")
-	border:SetTextureCoords(0, .625, 0, .8125)
-	border:SetDimensions(40, 22)
-	border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
-
-	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)
-			end
-		end)
-
-	if colorpickerData.warning then
-		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
-		control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0)
-		--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()
-	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
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/custom.lua b/Libs/LAM2/controls/custom.lua
deleted file mode 100644
index 54c9775..0000000
--- a/Libs/LAM2/controls/custom.lua
+++ /dev/null
@@ -1,45 +0,0 @@
---[[customData = {
-	type = "custom",
-	reference = "MyAddonCustomControl",	--(optional) unique name for your control to use as reference
-	refreshFunc = function(customControl) end,	--(optional) function to call when panel/controls refresh
-	width = "full",	--or "half" (optional)
-}	]]
-
-local widgetVersion = 4
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("custom", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local tinsert = table.insert
-
-local function UpdateValue(control)
-	if control.data.refreshFunc then
-		control.data.refreshFunc(control)
-	end
-end
-
-function LAMCreateControl.custom(parent, customData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or customData.reference)
-	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)
-		control:SetDimensions(250, 55)
-	else
-		control:SetDimensionConstraints(510, 30, 510, 100)
-		control:SetDimensions(510, 30)
-	end
-
-	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/LAM2/controls/description.lua b/Libs/LAM2/controls/description.lua
deleted file mode 100644
index 5d7219d..0000000
--- a/Libs/LAM2/controls/description.lua
+++ /dev/null
@@ -1,67 +0,0 @@
---[[descriptionData = {
-	type = "description",
-	title = "My Title",	--(optional)
-	text = "My description text to display.",
-	width = "full",	--or "half" (optional)
-	reference = "MyAddonDescription"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 4
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("description", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local tinsert = table.insert
-
-local function UpdateValue(control)
-	if control.title then
-		control.title:SetText(control.data.title)
-	end
-	control.desc:SetText(control.data.text)
-end
-
-function LAMCreateControl.description(parent, descriptionData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or descriptionData.reference)
-	control:SetResizeToFitDescendents(true)
-	control:SetParent(parent.scroll or parent)
-	local isHalfWidth = descriptionData.width == "half"
-	if isHalfWidth then
-		control:SetDimensionConstraints(250, 55, 250, 100)
-		control:SetDimensions(250, 55)
-	else
-		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)
-	desc:SetFont("ZoFontGame")
-	desc:SetText(descriptionData.text)
-	desc:SetWidth(isHalfWidth and 250 or 510)
-
-	if descriptionData.title then
-		control.title = wm:CreateControl(nil, control, CT_LABEL)
-		local title = control.title
-		title:SetWidth(isHalfWidth and 250 or 510)
-		title:SetAnchor(TOPLEFT, control, TOPLEFT)
-		title:SetFont("ZoFontWinH4")
-		title:SetText(descriptionData.title)
-		desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT)
-	else
-		desc:SetAnchor(TOPLEFT)
-	end
-
-	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/LAM2/controls/dropdown.lua b/Libs/LAM2/controls/dropdown.lua
deleted file mode 100644
index 94cd820..0000000
--- a/Libs/LAM2/controls/dropdown.lua
+++ /dev/null
@@ -1,153 +0,0 @@
---[[dropdownData = {
-	type = "dropdown",
-	name = "My Dropdown",
-	tooltip = "Dropdown's tooltip text.",
-	choices = {"table", "of", "choices"},
-	sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted
-	getFunc = function() return db.var end,
-	setFunc = function(var) db.var = var doStuff() end,
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	default = defaults.var,	--(optional)
-	reference = "MyAddonDropdown"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 7
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	else
-		disable = control.data.disabled
-	end
-
-	control.dropdown:SetEnabled(not disable)
-	if disable then
-		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-	else
-		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-	end
-end
-
-local function UpdateValue(control, forceDefault, value)
-	if forceDefault then	--if we are forcing defaults
-		value = control.data.default
-		control.data.setFunc(value)
-		control.dropdown:SetSelectedItem(value)
-	elseif value then
-		control.data.setFunc(value)
-		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	else
-		value = control.data.getFunc()
-		control.dropdown:SetSelectedItem(value)
-	end
-end
-
-local function DropdownCallback(choice, 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
-		local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
-		entry.control = control
-		control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE)	--if sort type/order isn't specified, then don't sort
-	end
-end
-
-local function GrabSortingInfo(sortInfo)
-	local t, i = {}, 1
-	for info in string.gmatch(sortInfo, "([^%-]+)") do
-		t[i] = info
-		i = i + 1
-	end
-
-	return t
-end
-
-
-local comboboxCount = 1
-function LAMCreateControl.dropdown(parent, dropdownData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or dropdownData.reference)
-	control:SetParent(parent.scroll or parent)
-	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)
-	label:SetFont("ZoFontWinH4")
-	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 combobox = control.combobox
-	combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
-	combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
-	control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
-	local dropdown = control.dropdown
-	if dropdownData.sort then
-		local sortInfo = GrabSortingInfo(dropdownData.sort)
-		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)
-		label:SetDimensions(250, 26)
-		combobox:SetDimensions(225, 26)
-		combobox:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
-	else
-		control:SetDimensions(510, 30)
-		label:SetDimensions(300, 26)
-		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()
-	end
-	control.UpdateChoices = UpdateChoices
-	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
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/editbox.lua b/Libs/LAM2/controls/editbox.lua
deleted file mode 100644
index 0d273d3..0000000
--- a/Libs/LAM2/controls/editbox.lua
+++ /dev/null
@@ -1,155 +0,0 @@
---[[editboxData = {
-	type = "editbox",
-	name = "My Editbox",
-	tooltip = "Editbox's tooltip text.",
-	getFunc = function() return db.text end,
-	setFunc = function(text) db.text = text doStuff() end,
-	isMultiline = true,	--boolean
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	default = defaults.text,	--(optional)
-	reference = "MyAddonEditbox"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 6
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("editbox", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local tinsert = table.insert
-
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	else
-		disable = control.data.disabled
-	end
-
-	if disable then
-		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-		control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
-	else
-		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-		control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-	end
-	--control.editbox:SetEditEnabled(not disable)
-	control.editbox:SetMouseEnabled(not disable)
-end
-
-local function UpdateValue(control, forceDefault, value)
-	if forceDefault then	--if we are forcing defaults
-		value = control.data.default
-		control.data.setFunc(value)
-		control.editbox:SetText(value)
-	elseif value then
-		control.data.setFunc(value)
-		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	else
-		value = control.data.getFunc()
-		control.editbox:SetText(value)
-	end
-end
-
-
-function LAMCreateControl.editbox(parent, editboxData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or editboxData.reference)
-	control:SetParent(parent.scroll or parent)
-	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)
-				if self:HasFocus() then	--only set focus to new spots if the editbox is currently in use
-					local cursorPos = self:GetCursorPosition()
-					local text = self:GetText()
-					local textLen = text:len()
-					local newPos
-					if delta > 0 then	--scrolling up
-						local reverseText = text:reverse()
-						local revCursorPos = textLen - cursorPos
-						local revPos = reverseText:find("\n", revCursorPos+1)
-						newPos = revPos and textLen - revPos
-					else	--scrolling down
-						newPos = text:find("\n", cursorPos+1)
-					end
-					if newPos then	--if we found a new line, then scroll, otherwise don't
-						self:SetCursorPosition(newPos)
-					end
-				end
-			end)
-	else
-		control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop")
-	end
-	local editbox = control.editbox
-	editbox:SetText(editboxData.getFunc())
-	editbox:SetMaxInputChars(3000)
-	editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end)
-	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)
-		label:SetDimensions(250, 26)
-		bg:SetDimensions(225, editboxData.isMultiline and 74 or 24)
-		bg:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT)
-		if editboxData.isMultiline then
-			editbox:SetDimensionConstraints(210, 74, 210, 500)
-		end
-	else
-		control:SetDimensions(510, 30)
-		label:SetDimensions(300, 26)
-		bg:SetDimensions(200, editboxData.isMultiline and 100 or 24)
-		bg:SetAnchor(TOPRIGHT)
-		if editboxData.isMultiline then
-			editbox:SetDimensionConstraints(185, 100, 185, 500)
-		end
-	end
-
-	if editboxData.warning then
-		control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
-		control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0)
-		--control.warning.tooltipText = editboxData.warning
-		control.warning.data = {tooltipText = editboxData.warning}
-	end
-
-	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()
-	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
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/header.lua b/Libs/LAM2/controls/header.lua
deleted file mode 100644
index bbf2c60..0000000
--- a/Libs/LAM2/controls/header.lua
+++ /dev/null
@@ -1,47 +0,0 @@
---[[headerData = {
-	type = "header",
-	name = "My Header",
-	width = "full",	--or "half" (optional)
-	reference = "MyAddonHeader"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 4
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("header", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local tinsert = table.insert
-
-local function UpdateValue(control)
-	control.header:SetText(control.data.name)
-end
-
-function LAMCreateControl.header(parent, headerData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or headerData.reference)
-	control:SetParent(parent.scroll or parent)
-	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)
-	divider:SetAnchor(TOPLEFT)
-
-	control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
-	local header = control.header
-	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/LAM2/controls/panel.lua b/Libs/LAM2/controls/panel.lua
deleted file mode 100644
index 5f9f41b..0000000
--- a/Libs/LAM2/controls/panel.lua
+++ /dev/null
@@ -1,138 +0,0 @@
---[[panelData = {
-	type = "panel",
-	name = "Window Title",
-	displayName = "My Longer Window Title",	--(optional) (can be useful for long addon names or if you want to colorize it)
-	author = "Seerah",	--(optional)
-	version = "2.0",	--(optional)
-	slashCommand = "/myaddon",	--(optional) will register a keybind to open to this panel (don't forget to include the slash!)
-	registerForRefresh = true,	--boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown)
-	registerForDefaults = true,	--boolean (optional) (will set all options controls back to default values)
-	resetFunc = function() print("defaults reset") end,	--(optional) custom function to run after settings are reset to defaults
-}	]]
-
-
-local widgetVersion = 8
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("panel", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-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.UpdateValue then
-				updateControl:UpdateValue()
-			end
-			if updateControl.UpdateDisabled then
-				updateControl:UpdateDisabled()
-			end
-		end
-	end
-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"] = {
-	title = {
-		text = SI_OPTIONS_RESET_TITLE,
-	},
-	mainText = {
-		text = SI_OPTIONS_RESET_PROMPT,
-		align = TEXT_ALIGN_CENTER,
-	},
-	buttons = {
-		[1] = {
-			text = SI_OPTIONS_RESET,
-			callback = function(dialog) ForceDefaults(dialog.data[1]) end,
-		},
-		[2] = {
-			text = SI_DIALOG_CANCEL,
-		},
-	},
-}
-
-local callbackRegistered = false
-LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1
-function LAMCreateControl.panel(parent, panelData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName)
-	control:SetParent(parent)
-
-	control.bg = wm:CreateControl(nil, control, CT_BACKDROP)
-	local bg = control.bg
-	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
-		info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin")
-		info:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
-		info:SetHeight(13)
-		info:SetAnchor(TOPRIGHT, control, BOTTOMRIGHT, -5, 2)
-		if panelData.author and panelData.version then
-			--info:SetText("Version: "..panelData.version.."  -  "..GetString(SI_ADDON_MANAGER_AUTHOR)..": "..panelData.author)
-			info:SetText(string.format("Version: %s  -  %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
-		elseif panelData.author then
-			info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
-		else
-			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
-	container:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 20)
-	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
-		defaultButton:SetFont("ZoFontDialogKeybindDescription")
-		defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-		--defaultButton:SetText("Reset To Defaults")
-		defaultButton:SetText(GetString(SI_OPTIONS_RESET_TITLE))
-		defaultButton:SetDimensions(200, 30)
-		defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2)
-		defaultButton:SetHandler("OnClicked", function()
-				ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control})
-			end)
-	end
-
-	if panelData.registerForRefresh and not callbackRegistered then	--don't want to register our callback more than once
-		cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel)
-		callbackRegistered = true
-	end
-
-	control.data = panelData
-	control.controlsToRefresh = {}
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/slider.lua b/Libs/LAM2/controls/slider.lua
deleted file mode 100644
index f7ab0a3..0000000
--- a/Libs/LAM2/controls/slider.lua
+++ /dev/null
@@ -1,184 +0,0 @@
---[[sliderData = {
-	type = "slider",
-	name = "My Slider",
-	tooltip = "Slider's tooltip text.",
-	min = 0,
-	max = 20,
-	step = 1,	--(optional)
-	getFunc = function() return db.var end,
-	setFunc = function(value) db.var = value doStuff() end,
-	width = "full",	--or "half" (optional)
-	disabled = function() return db.someBooleanSetting end,	--or boolean (optional)
-	warning = "Will need to reload the UI.",	--(optional)
-	default = defaults.var,	--(optional)
-	reference = "MyAddonSlider"	--(optional) unique global reference to control
-}	]]
-
-
-local widgetVersion = 5
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("slider", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local cm = CALLBACK_MANAGER
-local round = zo_round
-local strformat = string.format
-local tinsert = table.insert
-
-local function UpdateDisabled(control)
-	local disable
-	if type(control.data.disabled) == "function" then
-		disable = control.data.disabled()
-	else
-		disable = control.data.disabled
-	end
-
-	control.slider:SetEnabled(not disable)
-	control.slidervalue:SetEditEnabled(not disable)
-	if disable then
-		control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-		control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-		control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-		control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
-	else
-		control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-		control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-		control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-		control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
-	end
-end
-
-local function UpdateValue(control, forceDefault, value)
-	if forceDefault then	--if we are forcing defaults
-		value = control.data.default
-		control.data.setFunc(value)
-	elseif value and value >= control.data.min and value <= control.data.max then
-		control.data.setFunc(value)
-		--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
-		if control.panel.data.registerForRefresh then
-			cm:FireCallbacks("LAM-RefreshPanel", control)
-		end
-	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 isHalfWidth = sliderData.width == "half"
-	if isHalfWidth then
-		control:SetDimensions(250, 55)
-	else
-		control:SetDimensions(510, 40)
-	end
-	control:SetMouseEnabled(true)
-	--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")
-	label:SetDimensions(isHalfWidth and 250 or 300, 26)
-	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
-	slider:SetDimensions(190, 14)
-	if isHalfWidth then
-		slider:SetAnchor(TOPRIGHT, label, BOTTOMRIGHT, -5, 2)
-	else
-		slider:SetAnchor(RIGHT, control, RIGHT, -5, -5)
-	end
-	slider:SetMouseEnabled(true)
-	slider:SetOrientation(ORIENTATION_HORIZONTAL)
-	--put nil for highlighted texture file path, and what look to be texture coords
-	slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16)
-	local minValue = sliderData.min
-	local maxValue = sliderData.max
-	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")
-	minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT)
-	minText:SetText(sliderData.min)
-
-	control.maxText = wm:CreateControl(nil, slider, CT_LABEL)
-	local maxText = control.maxText
-	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)
-	control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop")
-	local slidervalue = control.slidervalue
-	slidervalue:ClearAnchors()
-	slidervalue:SetAnchor(TOPLEFT, slidervaluebg, TOPLEFT, 3, 1)
-	slidervalue:SetAnchor(BOTTOMRIGHT, slidervaluebg, BOTTOMRIGHT, -3, -1)
-	slidervalue:SetTextType(TEXT_TYPE_NUMERIC)
-	slidervalue:SetFont("ZoFontGameSmall")
-	slidervalue:SetHandler("OnEscape", function(self)
-			self:LoseFocus()
-			control:UpdateValue()
-		end)
-	slidervalue:SetHandler("OnEnter", function(self)
-			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)
-			if eventReason == EVENT_REASON_SOFTWARE then return end
-			self:SetValue(value)	--do we actually need this line?
-			slidervalue:SetText(value)
-		end)
-	slider:SetHandler("OnSliderReleased", function(self, value)
-			--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()
-	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
-
-	return control
-end
\ No newline at end of file
diff --git a/Libs/LAM2/controls/submenu.lua b/Libs/LAM2/controls/submenu.lua
deleted file mode 100644
index 761dda5..0000000
--- a/Libs/LAM2/controls/submenu.lua
+++ /dev/null
@@ -1,123 +0,0 @@
---[[submenuData = {
-	type = "submenu",
-	name = "Submenu Title",
-	tooltip = "My submenu tooltip",	--(optional)
-	controls = {sliderData, buttonData}	--(optional) used by LAM
-	reference = "MyAddonSubmenu"	--(optional) unique global reference to control
-}	]]
-
-local widgetVersion = 7
-local LAM = LibStub("LibAddonMenu-2.0")
-if not LAM:RegisterWidget("submenu", widgetVersion) then return end
-
-local wm = WINDOW_MANAGER
-local am = ANIMATION_MANAGER
-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
-
-local function AnimateSubmenu(clicked)
-	local control = clicked:GetParent()
-	control.open = not control.open
-
-	if control.open then
-		control.animation:PlayFromStart()
-	else
-		control.animation:PlayFromEnd()
-	end
-end
-
-
-function LAMCreateControl.submenu(parent, submenuData, controlName)
-	local control = wm:CreateTopLevelWindow(controlName or submenuData.reference)
-	control:SetParent(parent.scroll or parent)
-	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)
-	label:SetDimensions(520, 30)
-	label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-	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)
-	scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10)
-	scroll:SetDimensionConstraints(525, 0, 525, 2500)
-
-	control.bg = wm:CreateControl(nil, label, CT_BACKDROP)
-	local bg = control.bg
-	bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5)
-	bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0)
-	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)
-	animation:SetHandler("OnStop", function(self, completedPlaying)
-			scroll:SetResizeToFitDescendents(control.open)
-			if control.open then
-				control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds")
-				scroll:SetResizeToFitPadding(5, 20)
-			else
-				control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds")
-				scroll:SetResizeToFitPadding(5, 0)
-				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
-	btmToggle:SetMouseEnabled(true)
-	btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT)
-	btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT)
-	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/LAM2/controls/texture.lua b/Libs/LAM2/controls/texture.lua
deleted file mode 100644
index 928ab82..0000000
--- a/Libs/LAM2/controls/texture.lua
+++ /dev/null
@@ -1,51 +0,0 @@
---[[textureData = {
-	type = "texture",
-	image = "file/path.dds",
-	imageWidth = 64,	--max of 250 for half width, 510 for full
-	imageHeight = 32,	--max of 100
-	tooltip = "Image's tooltip text.",	--(optional)
-	width = "full",	--or "half" (optional)
-	reference = "MyAddonTexture"	--(optional) unique global reference to control
-}	]]
-
---add texture coords support?
-
-local widgetVersion = 5
-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)
-	control:SetResizeToFitDescendents(true)
-	control:SetParent(parent.scroll or parent)
-
-	local isHalfWidth = textureData.width == "half"
-	if isHalfWidth then
-		control:SetDimensionConstraints(250, 55, 250, 100)
-		control:SetDimensions(250, 55)
-	else
-		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
-		texture.data = {tooltipText = textureData.tooltip}
-		texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-		texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit)
-	end
-
-	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
diff --git a/Libs/LibStub/LibStub.lua b/Libs/LibStub/LibStub.lua
deleted file mode 100644
index 879d132..0000000
--- a/Libs/LibStub/LibStub.lua
+++ /dev/null
@@ -1,34 +0,0 @@
--- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
--- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
--- LibStub developed for World of Warcraft by above members of the WowAce community.
--- Ported to Elder Scrolls Online by Seerah
-
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
-local strformat = string.format
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
-	LibStub = LibStub or {libs = {}, minors = {} }
-	_G[LIBSTUB_MAJOR] = LibStub
-	LibStub.minor = LIBSTUB_MINOR
-
-	function LibStub:NewLibrary(major, minor)
-		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
-		minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
-		local oldminor = self.minors[major]
-		if oldminor and oldminor >= minor then return nil end
-		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-		return self.libs[major], oldminor
-	end
-
-	function LibStub:GetLibrary(major, silent)
-		if not self.libs[major] and not silent then
-			error(strformat("Cannot find a library instance of %q.", tostring(major)), 2)
-		end
-		return self.libs[major], self.minors[major]
-	end
-
-	function LibStub:IterateLibraries() return pairs(self.libs) end
-	setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
diff --git a/README b/README
deleted file mode 100644
index 37685a4..0000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates. The Elder Scrolls® and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries. All rights reserved.
\ No newline at end of file