major refactoring and added auto features

Leandro Silva [03-26-20 - 09:22]
major refactoring and added auto features
Filename
Bank.lua
Bindings.xml
Craft.lua
Deconstruct.lua
Launcher.lua
Launcher.xml
LeoTrainer.lua
LeoTrainer.txt
LeoTrainer.xml
LeoTrainerConst.lua
Research.lua
Settings.lua
Settings.xml
Ui.lua
diff --git a/Bank.lua b/Bank.lua
new file mode 100755
index 0000000..35fb0f9
--- /dev/null
+++ b/Bank.lua
@@ -0,0 +1,110 @@
+
+local Bank = {
+    isClosed = true
+}
+local eventId, eventBag
+
+local function findFirstEmptyBankSlot()
+    local targetBagId = BAG_BANK
+    local targetSlotIndex = FindFirstEmptySlotInBag(targetBagId)
+    if targetSlotIndex == nil then
+        targetBagId = BAG_SUBSCRIBER_BANK
+        targetSlotIndex = FindFirstEmptySlotInBag(targetBagId)
+    end
+    return targetBagId, targetSlotIndex
+end
+
+local function getUniqueUpdateIdentifier(bagId, slotIndex)
+    return table.concat({"LeoTrainerBank", tostring(bagId), tostring(slotIndex)})
+end
+
+local function disablePersonalAssistant()
+    if not PersonalAssistant then return end
+
+    -- Check if the Addon 'PABanking' is even enabled
+    local PAB = PersonalAssistant.Banking
+    if PAB then
+        -- Unregister PABanking completely
+        EVENT_MANAGER:UnregisterForEvent(PAB.AddonName, EVENT_OPEN_BANK, "OpenBank")
+        EVENT_MANAGER:UnregisterForEvent(PAB.AddonName, EVENT_CLOSE_BANK, "CloseBank")
+    end
+end
+
+local function runPersonalAssistant(eventId, bankBag)
+    if not PersonalAssistant then return end
+
+    -- Check if the Addon 'PABanking' is even enabled
+    local PAB = PersonalAssistant.Banking
+    if PAB then
+        -- Check if the functionality is turned on within the addon
+        local PABMenuFunctions = PersonalAssistant.MenuFunctions.PABanking
+        if PABMenuFunctions.getCurrenciesEnabledSetting() or PABMenuFunctions.getCraftingItemsEnabledSetting()
+                or PABMenuFunctions.getAdvancedItemsEnabledSetting() then
+            PAB.OnBankOpen(eventId, bankBag)
+        end
+    end
+end
+
+local function depositItems(items, startIndex)
+    local itemData = items[startIndex]
+
+    local targetBagId, targetSlotIndex = findFirstEmptyBankSlot()
+    if targetBagId == nil or targetSlotIndex == nil then
+        LeoTrainer.log("Cannot deposit item. Bank full?")
+        runPersonalAssistant(eventId, eventBag)
+        return
+    end
+    if IsProtectedFunction("RequestMoveItem") then
+        CallSecureProtected("RequestMoveItem", BAG_BACKPACK, itemData.slotIndex, targetBagId, targetSlotIndex, 1)
+    else
+        RequestMoveItem(BAG_BACKPACK, itemData.slotIndex, targetBagId, targetSlotIndex, 1)
+    end
+    local identifier = getUniqueUpdateIdentifier(BAG_BACKPACK, itemData.slotIndex)
+    EVENT_MANAGER:RegisterForUpdate(identifier, 50, function()
+        local itemId = GetItemId(targetBagId, targetSlotIndex)
+        if itemId > 0 or Bank.isClosed then
+            EVENT_MANAGER:UnregisterForUpdate(identifier)
+            LeoTrainer.log("Deposited " .. itemData.itemLink)
+            if not Bank.isClosed then
+                local newIndex = startIndex + 1
+                if newIndex <= #items then
+                    depositItems(items, newIndex)
+                    return
+                end
+            end
+            LeoTrainer.debug("Done depositing")
+            runPersonalAssistant(eventId, eventBag)
+        end
+    end)
+end
+
+function Bank.OnOpenBank(event, bankBag)
+    eventId = event
+    eventBag = bankBag
+
+    if IsHouseBankBag(bankBag) then
+        runPersonalAssistant(eventId, eventBag)
+        return
+    end
+
+    Bank.isClosed = false
+
+    if not LeoTrainer.settings.bank.autoDeposit then return end
+
+    local items = LeoTrainer.craft.ScanBackpackForCrafted()
+    if #items > 0 then
+        depositItems(items, 1)
+    end
+end
+
+function Bank.OnCloseBank()
+    Bank.isClosed = true
+end
+
+function Bank.Initialize()
+    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_OPEN_BANK, Bank.OnOpenBank)
+    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CLOSE_BANK, Bank.OnCloseBank)
+    disablePersonalAssistant()
+end
+
+LeoTrainer.bank = Bank
diff --git a/Bindings.xml b/Bindings.xml
old mode 100644
new mode 100755
index 80b216d..f4396b0
--- a/Bindings.xml
+++ b/Bindings.xml
@@ -2,11 +2,17 @@
   <Layer name="SI_KEYBINDINGS_CATEGORY_GENERAL">
     <Category name="Leo's Trainer">
       <Action name="LEOTRAINER_TOGGLE_WINDOW">
-        <Down>LeoTrainerUI:ToggleUI()</Down>
+        <Down>LeoTrainer.ui:ToggleUI()</Down>
       </Action>
       <Action name="LEOTRAINER_CRAFT_NEXT">
         <Down>LeoTrainer.CraftNext()</Down>
       </Action>
+      <Action name="LEOTRAINER_DECON">
+        <Down>LeoTrainer.deconstruct.DoDeconstruct()</Down>
+      </Action>
+      <Action name="LEOTRAINER_RESEARCH">
+        <Down>LeoTrainer.research.ResearchNext()</Down>
+      </Action>
     </Category>
   </Layer>
 </Bindings>
diff --git a/Craft.lua b/Craft.lua
new file mode 100755
index 0000000..652c510
--- /dev/null
+++ b/Craft.lua
@@ -0,0 +1,183 @@
+
+local Craft = {
+    namesToPatternIndexes = {},
+    isCrafting = false
+}
+
+function Craft.Initialize()
+end
+
+function Craft.MaxStyle(piece)
+    local maxStyleId = -1
+    local maxQty = 0
+    for _,i in ipairs(LeoTrainer.const.racialStyles) do
+        if IsSmithingStyleKnown(i, piece) == true then
+            local qty = GetCurrentSmithingStyleItemCount(i)
+            if qty > maxQty then
+                maxStyleId = i
+                maxQty = qty
+            end
+        end
+    end
+    return maxStyleId
+end
+
+function Craft.GetPatternIndexes(craft)
+    Craft.namesToPatternIndexes[craft] = {
+        ["names"] = {},
+        ["lines"] = {}
+    }
+    for patternIndex = 1, GetNumSmithingPatterns() do
+        local _, name = GetSmithingPatternInfo(patternIndex)
+        Craft.namesToPatternIndexes[craft]["names"][name] = patternIndex
+    end
+
+    for line = 1, GetNumSmithingResearchLines(craft) do
+        local lineName = GetSmithingResearchLineInfo(craft, line)
+        Craft.namesToPatternIndexes[craft]["lines"][line] = Craft.namesToPatternIndexes[craft]["names"][lineName]
+    end
+end
+
+function Craft.GetPattern(craftSkill, line)
+    return Craft.namesToPatternIndexes[craftSkill]["lines"][line] or nil
+end
+
+local function wasCraftedByMe(bagId, slotIndex)
+    local creator = GetItemCreatorName(bagId, slotIndex)
+    if creator == nil then return false end
+
+    local charList = LeoAltholic.ExportCharacters()
+    for _, char in pairs(charList) do
+        if creator == char.bio.name then return true end
+    end
+
+    return false
+end
+
+function Craft.ScanBackpackForCrafted()
+    local list = {}
+    local bag = SHARED_INVENTORY:GenerateFullSlotData(nil, BAG_BACKPACK)
+    for _, data in pairs(bag) do
+        local itemLink = GetItemLink(data.bagId, data.slotIndex, LINK_STYLE_BRACKETS)
+        local type = GetItemType(data.bagId, data.slotIndex)
+        local trait = GetItemLinkTraitInfo(itemLink)
+        if wasCraftedByMe(data.bagId, data.slotIndex) and (type == ITEMTYPE_ARMOR or type == ITEMTYPE_WEAPON) and
+            trait ~= ITEM_TRAIT_TYPE_NONE and GetItemQuality(data.bagId, data.slotIndex) == ITEM_QUALITY_NORMAL then
+            table.insert(list, {
+                bagId = data.bagId,
+                slotIndex = data.slotIndex,
+                itemLink = itemLink
+            })
+        end
+    end
+    return list
+end
+
+function Craft.MarkItem(bagId, slotIndex)
+    if FCOIS then
+        local itemLinkBag = GetItemLink(bagId, slotIndex)
+        LeoTrainer.log("Marking " .. itemLinkBag .. " for research")
+        FCOIS.MarkItem(bagId, slotIndex, FCOIS_CON_ICON_RESEARCH, true)
+    end
+end
+
+local function addItemToLLC(queueIndex, data)
+
+    LeoTrainer.log("Crafting " .. data.itemLink .. " ("..data.researchName..") ...")
+
+    data.patternIndex = Craft.namesToPatternIndexes[data.craft]["lines"][data.line]
+
+    local matName, _, matReq = GetSmithingPatternMaterialItemInfo(data.patternIndex, data.materialIndex)
+    data.materialQuantity = matReq
+
+    local curMats = GetCurrentSmithingMaterialItemCount(data.patternIndex, data.materialIndex)
+    if curMats < data.materialQuantity then
+        local diff = data.materialQuantity - curMats
+        LeoTrainer.log("Not enough " .. matName .. ". Need " .. diff .. " more.")
+        return false
+    end
+
+    data.itemStyleId = Craft.MaxStyle(data.line)
+
+    if data.itemStyleId == -1 then
+        LeoTrainer.log("Not enough known style material.")
+        return false
+    end
+
+    LeoTrainer.LLC:CraftSmithingItem(
+        data.patternIndex,
+        data.materialIndex,
+        data.materialQuantity,
+        data.itemStyleId,
+        data.traitIndex + 1,
+        data.useUniversalStyleItem,
+        nil,
+        nil,
+        ITEM_QUALITY_NORMAL,
+        true,
+        queueIndex -- reference
+    )
+
+    return true
+end
+
+local function addItemsToLLC()
+    local craftSkill = GetCraftingInteractionType()
+    for index, data in ipairs(LeoTrainer.data.craftQueue) do
+        if not data.crafted and data.craft == craftSkill and LeoAltholic.CharKnowsTrait(data.craft, data.line, data.trait) == true then
+            if addItemToLLC(index, data) then Craft.isCrafting = true end
+        end
+    end
+    if Craft.isCrafting == true then return end
+
+    LeoTrainer.debug("Nothing more to craft at this station.")
+    LeoTrainer.isCrafting = false
+end
+
+function Craft.TryWritCreator(craftSkill)
+    if WritCreater then
+        EVENT_MANAGER:RegisterForEvent(WritCreater.name, EVENT_CRAFT_COMPLETED, WritCreater.craftCompleteHandler)
+        WritCreater.craftCheck(1, craftSkill)
+ 	end
+    LibLazyCrafting.craftInteract(1, craftSkill)
+end
+
+function Craft.StillHaveCraftToDo(craftSkill)
+    for _, data in pairs(LeoTrainer.data.craftQueue) do
+        if data.craft == craftSkill and not data.crafted then return true end
+    end
+
+    return false
+end
+
+function Craft.RemoveCraftedFromQueue()
+    local i=1
+    while i <= #LeoTrainer.data.craftQueue do
+        if LeoTrainer.data.craftQueue[i].crafted then
+            table.remove(LeoTrainer.data.craftQueue, i)
+        else
+            i = i + 1
+        end
+    end
+end
+
+function Craft.OnStationExit(craftSkill)
+    Craft.RemoveCraftedFromQueue()
+end
+
+function Craft.OnStationEnter(craftSkill)
+    Craft.GetPatternIndexes(craftSkill)
+
+    Craft.isCrafting = false
+
+    if #LeoTrainer.data.craftQueue > 0 and LeoTrainer.settings.craft.auto then
+        addItemsToLLC()
+        LibLazyCrafting.craftInteract(1, craftSkill)
+        return
+    end
+
+    -- LeoTrainer.debug("Nothing to craft here.")
+    LeoTrainer.nextStage()
+end
+
+LeoTrainer.craft = Craft
diff --git a/Deconstruct.lua b/Deconstruct.lua
new file mode 100755
index 0000000..92c2903
--- /dev/null
+++ b/Deconstruct.lua
@@ -0,0 +1,138 @@
+local Deconstruct = {
+    queue = {},
+    keybindStripDescriptor =
+    {
+        {
+            name = "Deconstruct",
+            keybind = "LEOTRAINER_DECON",
+            callback = function() LeoTrainer.deconstruct.DoDeconstruct() end--,
+        },
+        alignment = KEYBIND_STRIP_ALIGN_CENTER,
+    }
+}
+
+function Deconstruct.CanItemBeDeconstructed(bagId, slotIndex, itemLink, craftSkill)
+    if not FCOIS then return false end
+
+    if itemLink == nil then itemLink = GetItemLink(bagId, slotIndex) end
+
+    -- local type = GetItemType(bagId, slotIndex)
+    -- if type ~= ITEMTYPE_ARMOR and type ~= ITEMTYPE_WEAPON then return false end
+
+    local markedDecon = true
+    if FCOIS.IsIconEnabled(FCOIS_CON_ICON_DECONSTRUCTION) then
+        markedDecon = FCOIS.IsMarked(bagId, slotIndex, FCOIS_CON_ICON_DECONSTRUCTION)
+    end
+
+    local markedIntri = true
+    if FCOIS.IsIconEnabled(FCOIS_CON_ICON_INTRICATE) then
+        markedIntri = FCOIS.IsMarked(bagId, slotIndex, FCOIS_CON_ICON_INTRICATE)
+    end
+
+    if not markedDecon and not markedIntri then
+        -- LeoTrainer.debug(itemLink .. " not marked for deconstruct nor intricate")
+        return false
+    end
+
+    local hasSet, setName = GetItemLinkSetInfo(itemLink)
+    if not LeoTrainer.settings.deconstruct.allowSets and hasSet then
+        -- LeoTrainer.debug(itemLink .. " is from set " .. setName)
+        return false
+    end
+
+    if craftSkill > 0 and LeoTrainer.settings.deconstruct.maxQuality[craftSkill] < GetItemQuality(bagId, slotIndex) then
+        -- LeoTrainer.debug(itemLink .. " is with higher quality")
+        return false
+    end
+
+    if bagId ~= BAG_BACKPACK then
+        local line = LeoTrainer.CraftToLineSkill(craftSkill)
+        local craftLevel = select(8, GetSkillAbilityInfo(SKILL_TYPE_TRADESKILL, line, 1))
+        local itemLevel = GetItemLinkRequiredLevel(itemLink)
+        -- LeoTrainer.debug(itemLink .. " CraftLvel " .. tostring(craftLevel) .. " itemLevel " .. tostring(itemLevel))
+        if LeoTrainer.settings.deconstruct.onlyClosestLevel and craftLevel > 0 and
+            (itemLevel / 5 < craftLevel - 3 or itemLevel / 5 > craftLevel + 6) then
+                -- LeoTrainer.debug(itemLink .. " is with level too far")
+                return false
+        end
+    end
+
+    return true
+end
+
+function Deconstruct.HandleItem(bagId, slotIndex, itemLink, craftSkill)
+    if bagId ~= BAG_BACKPACK and not LeoTrainer.settings.deconstruct.allowBank then return false end
+
+    if not Deconstruct.CanItemBeDeconstructed(bagId, slotIndex, itemLink, craftSkill) then return false end
+
+    if LeoTrainer.settings.deconstruct.listInChat then
+        local bagName = "Backpack"
+        if bagId == BAG_BANK or bagId == BAG_SUBSCRIBER_BANK then bagName = "Bank" end
+        LeoTrainer.log("Can be deconstructed: " .. itemLink .. " (" .. bagName .. ")")
+    end
+
+    table.insert(Deconstruct.queue, {
+        bagId = bagId,
+        slotIndex = slotIndex,
+        itemLink = itemLink,
+        craftSkill = craftSkill,
+        selected = false
+    })
+
+    return true
+end
+
+function Deconstruct.DoDeconstruct(fromBags)
+    if fromBags == nil then
+        fromBags = {BAG_BACKPACK}
+        if LeoTrainer.settings.deconstruct.allowBank then
+            fromBags = {BAG_BACKPACK,BAG_BANK,BAG_SUBSCRIBER_BANK}
+        end
+    end
+
+    KEYBIND_STRIP:RemoveKeybindButtonGroup(Deconstruct.keybindStripDescriptor)
+    if #Deconstruct.queue > 0 then
+        PrepareDeconstructMessage()
+        for i, itemData in pairs(Deconstruct.queue) do
+            for _, bagId in pairs(fromBags) do
+                if itemData.bagId == bagId then
+                    LeoTrainer.log("Deconstructing " .. itemData.itemLink)
+                    AddItemToDeconstructMessage(itemData.bagId, itemData.slotIndex, 1)
+                end
+            end
+        end
+        SendDeconstructMessage()
+        Deconstruct.queue = {}
+        return true
+    end
+    return false
+end
+
+function Deconstruct.ShouldDeconstruct(craftSkill)
+    local line = LeoTrainer.CraftToLineSkill(craftSkill)
+    return GetSkillLineDynamicInfo(SKILL_TYPE_TRADESKILL, line) < 50
+end
+
+function Deconstruct.OnStationEnter(craftSkill)
+    -- LeoTrainer.debug("deconstruct OnStationEnter")
+    local line = LeoTrainer.CraftToLineSkill(craftSkill)
+    local maxLevel = GetSkillLineDynamicInfo(SKILL_TYPE_TRADESKILL, line) == 50
+    if #Deconstruct.queue > 0 and not maxLevel then
+        KEYBIND_STRIP:AddKeybindButtonGroup(Deconstruct.keybindStripDescriptor)
+    end
+    local done = false
+    if LeoTrainer.settings.deconstruct.auto then
+        done = Deconstruct.DoDeconstruct()
+    end
+    LeoTrainer.nextStage(done)
+end
+
+function Deconstruct.OnStationExit(craftSkill)
+    KEYBIND_STRIP:RemoveKeybindButtonGroup(Deconstruct.keybindStripDescriptor)
+    Deconstruct.queue = {}
+end
+
+function Deconstruct.Initialize()
+end
+
+LeoTrainer.deconstruct = Deconstruct
diff --git a/Launcher.lua b/Launcher.lua
old mode 100644
new mode 100755
index d8376e4..670c6ce
--- a/Launcher.lua
+++ b/Launcher.lua
@@ -5,7 +5,7 @@ function LeoTrainer_Launcher_OnMouseEnter(control)
 end

 function LeoTrainer_Launcher_OnMouseClicked(control)
-    LeoTrainerUI.ToggleUI()
+    LeoTrainer.ui.ToggleUI()
 end

 LeoTrainer_Launcher = ZO_Object:Subclass()
diff --git a/Launcher.xml b/Launcher.xml
old mode 100644
new mode 100755
diff --git a/LeoTrainer.lua b/LeoTrainer.lua
old mode 100644
new mode 100755
index 7678cdf..5d162c1
--- a/LeoTrainer.lua
+++ b/LeoTrainer.lua
@@ -1,250 +1,316 @@
-local craftedItems = {}
-
-local function copy(obj, seen)
-    if type(obj) ~= 'table' then return obj end
-    if seen and seen[obj] then return seen[obj] end
-    local s = seen or {}
-    local res = setmetatable({}, getmetatable(obj))
-    s[obj] = res
-    for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
-    return res
+
+function LeoTrainer.IsInUsableStation()
+    local station = GetCraftingInteractionType()
+
+    return station == CRAFTING_TYPE_BLACKSMITHING or
+        station == CRAFTING_TYPE_WOODWORKING or
+        station == CRAFTING_TYPE_CLOTHIER or
+        station == CRAFTING_TYPE_JEWELRYCRAFTING
 end

-function LeoTrainer.maxStyle(piece)
-    local maxStyleId = -1
-    local maxQty = 0
-    for _,i in ipairs(LeoTrainer.const.racialStyles) do
-        if IsSmithingStyleKnown(i, piece) == true then
-            local qty = GetCurrentSmithingStyleItemCount(i)
-            if qty > maxQty then
-                maxStyleId = i
-                maxQty = qty
-            end
+function LeoTrainer.LLC_Completed(event, station, result)
+    if event == LLC_NO_FURTHER_CRAFT_POSSIBLE then
+        LeoTrainer.debug("Nothing more to craft at this station.")
+        if LeoTrainer.stage == LEOTRAINER_STAGE_CRAFT then
+            LeoTrainer.nextStage()
         end
+        return
     end
-    return maxStyleId
-end

-function LeoTrainer.GetPatternIndexes(craft)
-    LeoTrainer.namesToPatternIndexes[craft] = {
-        ["names"] = {},
-        ["lines"] = {}
-    }
-    for patternIndex = 1, GetNumSmithingPatterns() do
-        local _, name = GetSmithingPatternInfo(patternIndex)
-        LeoTrainer.namesToPatternIndexes[craft]["names"][name] = patternIndex
-    end
+    if event ~= LLC_CRAFT_SUCCESS then return end

-    for line = 1, GetNumSmithingResearchLines(craft) do
-        local lineName, lineIcon, numTraits = GetSmithingResearchLineInfo(craft, line)
-        LeoTrainer.namesToPatternIndexes[craft]["lines"][line] = LeoTrainer.namesToPatternIndexes[craft]["names"][lineName]
-    end
-end
+    if result.Requester ~= LeoTrainer.name then return end

-local function splitLink(s)
-    local result = {};
-    for match in (s..':'):gmatch("(.-)"..':') do
-        table.insert(result, match);
-    end
-    return result;
-end
+    LeoTrainer.data.craftQueue[result.reference].crafted = true
+    LeoTrainer.ui.queueScroll:RefreshData()

-function LeoTrainer.compareLinks(link1, link2)
-    local table1 = splitLink(link1)
-    local table2 = splitLink(link2)
+    LeoTrainer.craft.MarkItem(result.bag, result.slot)

-    table1[19] = 1 -- reset crafted
-    table2[19] = 1 -- reset crafted
+    if LeoTrainer.craft.StillHaveCraftToDo(station) then return end

-    return table.concat(table1, ':') == table.concat(table2, ':')
+    LeoTrainer.debug("All crafts done at this station.")
+    LeoTrainer.nextStage()
 end

-local function markItems()
-    if not FCOIS then return end
-
-    local backpack = SHARED_INVENTORY:GenerateFullSlotData(nil,BAG_BACKPACK)
-    for _, crafted in pairs(craftedItems) do
-        for _, data in pairs(backpack) do
-            local itemLinkBag = GetItemLink(data.bagId,data.slotIndex)
-            if LeoTrainer.compareLinks(crafted, itemLinkBag) then
-                LeoTrainer.log("Marking " .. itemLinkBag .. " for research")
-                FCOIS.MarkItem(data.bagId, data.slotIndex, FCOIS_CON_ICON_RESEARCH, true)
-                break
-            end
+function LeoTrainer.OnCraftComplete(event, station)
+    EVENT_MANAGER:UnregisterForUpdate(LeoTrainer.name .. ".ResearchItemTimeout")
+
+    if LeoTrainer.research.isResearching then
+        local myName = GetUnitName("player")
+        local researching, total = LeoAltholic.GetResearchCounters(station)
+        table.remove(LeoTrainer.research.queue, 1)
+        LeoTrainer.research.isResearching = false
+        if #LeoTrainer.research.queue > 0 then
+            zo_callLater(function() LeoTrainer.ResearchNext(true) end, 400)
+            return
         end
     end
-    craftedItems = {}
-    --LeoTrainer.log("Done marking")
-end
-
-function LeoTrainer.OnCraftFailed(event, station)
-end
-
-function LeoTrainer.OnCraftComplete(event, station)

     if LeoTrainer.isCrafting == 0 then return end

-    LeoTrainer.RemoveFromQueue(LeoTrainer.isCrafting)
+    local data = LeoTrainer.RemoveFromQueue(LeoTrainer.isCrafting)
     LeoTrainer.isCrafting = 0

-    table.insert(craftedItems, GetLastCraftingResultItemLink(1))
+    data.crafted = GetLastCraftingResultItemLink(1)
+    table.insert(craftedItems, data)

     if GetCraftingInteractionType() ~= CRAFTING_TYPE_INVALID and LeoTrainer.continueCrating == true then
         zo_callLater(function() LeoTrainer.CraftNext() end, 200)
     end
 end

-function LeoTrainer.CraftItem(queueIndex, data)
-
-    LeoTrainer.log("Crafting " .. data.itemLink .. " ("..data.researchName..") ...")
+function LeoTrainer.nextStage(moreDelay)
+    LeoTrainer.stage = LeoTrainer.stage + 1
+    if LeoTrainer.stage > LEOTRAINER_STAGE_DONE then
+        LeoTrainer.stage = LEOTRAINER_STAGE_START
+    end
+    local craftSkill = GetCraftingInteractionType()
+    if craftSkill > 0 then
+        zo_callLater(function() LeoTrainer.continueAtStation(craftSkill) end, moreDelay and 200 or 10)
+    end
+end

-    if IsPerformingCraftProcess() == true then
-        LeoTrainer.log("Still crafting ...")
-        return false
+function LeoTrainer.continueAtStation(craftSkill)
+    if LeoTrainer.stage == LEOTRAINER_STAGE_RESEARCH then
+        LeoTrainer.ui.OnStationEnter(craftSkill)
+        zo_callLater(function() LeoTrainer.research.OnStationEnter(craftSkill) end, 10)
+        return
     end

-    data.patternIndex = LeoTrainer.namesToPatternIndexes[data.craft]["lines"][data.line]
+    if LeoTrainer.stage == LEOTRAINER_STAGE_DECONSTRUCT then
+        zo_callLater(function() LeoTrainer.deconstruct.OnStationEnter(craftSkill) end, 10)
+        return
+    end

-    local matName, _, matReq = GetSmithingPatternMaterialItemInfo(data.patternIndex, data.materialIndex)
-    data.materialQuantity = matReq
+    if LeoTrainer.stage == LEOTRAINER_STAGE_CRAFT then
+        zo_callLater(function() LeoTrainer.craft.OnStationEnter(craftSkill) end, 10)
+        return
+    end

-    local curMats = GetCurrentSmithingMaterialItemCount(data.patternIndex, data.materialIndex)
-    if curMats < data.materialQuantity then
-        local diff = data.materialQuantity - curMats
-        LeoTrainer.log("Not enough " .. matName .. ". Need " .. diff .. " more.")
-        LeoTrainer.continueCrating = false
-        return false
+    if LeoTrainer.stage == LEOTRAINER_STAGE_DONE then
+        zo_callLater(function() LeoTrainer.craft.TryWritCreator(craftSkill) end, 10)
+        return
     end
+end

-    data.itemStyleId = LeoTrainer.maxStyle(data.line)
+function LeoTrainer.stationEnter(craftSkill)
+    if not LeoTrainer.IsInUsableStation() then
+        LeoTrainer.craft.TryWritCreator(craftSkill)
+        return
+    end

-    if data.itemStyleId == -1 then
-        LeoTrainer.log("Not enough known style material.")
-        LeoTrainer.continueCrating = false
-        return false
+    if WritCreater then
+        EVENT_MANAGER:UnregisterForEvent(WritCreater.name, EVENT_CRAFT_COMPLETED)
     end

-    local request = {
-        data.patternIndex,
-        data.materialIndex,
-        data.materialQuantity,
-        data.itemStyleId,
-        data.traitIndex + 1,
-        data.useUniversalStyleItem
-    }
-
-    LeoTrainer.isCrafting = queueIndex
-    CraftSmithingItem(unpack(request))
-    return true
+    LeoTrainer.ScanBags(craftSkill)
+
+    LeoTrainer.stage = LEOTRAINER_STAGE_RESEARCH
+
+    LeoTrainer.continueAtStation(craftSkill)
+    -- LeoTrainerStation:SetHidden(false)
 end

-function LeoTrainer.CraftNext()
-    local list = LeoTrainer.GetQueue()
-    for index, data in ipairs(list) do
-        if data.craft == LeoTrainer.inStation and LeoAltholic.CharKnowsTrait(data.craft, data.line, data.trait) == true then
-            LeoTrainer.CraftItem(index, data)
-            return
+function LeoTrainer.stationExit(_, craftSkill)
+    EVENT_MANAGER:UnregisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED)
+    EVENT_MANAGER:UnregisterForEvent(WritCreater.name, EVENT_CRAFT_COMPLETED)
+
+    LeoTrainer.ui.OnStationExit(craftSkill)
+    LeoTrainer.research.OnStationExit(craftSkill)
+    LeoTrainer.deconstruct.OnStationExit(craftSkill)
+    LeoTrainer.craft.OnStationExit(craftSkill)
+end
+
+local craftSkillsBySound = {
+    [ITEM_SOUND_CATEGORY_BOW]             = CRAFTING_TYPE_WOODWORKING,
+    [ITEM_SOUND_CATEGORY_DAGGER]          = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_HEAVY_ARMOR]     = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_LIGHT_ARMOR]     = CRAFTING_TYPE_CLOTHIER,
+    [ITEM_SOUND_CATEGORY_MEDIUM_ARMOR]    = CRAFTING_TYPE_CLOTHIER,
+    [ITEM_SOUND_CATEGORY_NECKLACE]        = CRAFTING_TYPE_JEWELRYCRAFTING,
+    [ITEM_SOUND_CATEGORY_ONE_HAND_AX]     = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_ONE_HAND_HAMMER] = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_ONE_HAND_SWORD]  = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_RING]            = CRAFTING_TYPE_JEWELRYCRAFTING,
+    [ITEM_SOUND_CATEGORY_SHIELD]          = CRAFTING_TYPE_WOODWORKING,
+    [ITEM_SOUND_CATEGORY_STAFF]           = CRAFTING_TYPE_WOODWORKING,
+    [ITEM_SOUND_CATEGORY_TWO_HAND_AX]     = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_TWO_HAND_HAMMER] = CRAFTING_TYPE_BLACKSMITHING,
+    [ITEM_SOUND_CATEGORY_TWO_HAND_SWORD]  = CRAFTING_TYPE_BLACKSMITHING,
+}
+
+function LeoTrainer.CraftToLineSkill(craftSkill)
+    if craftSkill == CRAFTING_TYPE_BLACKSMITHING then return 2
+    elseif craftSkill == CRAFTING_TYPE_CLOTHIER then return 3
+    elseif craftSkill == CRAFTING_TYPE_WOODWORKING then return 7
+    elseif craftSkill == CRAFTING_TYPE_JEWELRYCRAFTING then return 5 end
+
+    return 0
+end
+
+function LeoTrainer.ItemLinkToCraftskill(itemLink)
+    return craftSkillsBySound[GetItemSoundCategoryFromLink(itemLink)] or 0
+end
+
+local function isLineBeingResearched(research, craft, line)
+    for _, researching in pairs(research.doing[craft]) do
+        if researching.line == line then
+            if researching.doneAt and researching.doneAt - GetTimeStamp() > 0 then
+                return true
+            end
         end
     end
-    LeoTrainer.log("Nothing more to craft at this station.")
-    LeoTrainer.isCrafting = 0
-    LeoTrainer.continueCrating = false
-    markItems()
+    return false
+end
+
+local function get(tbl, k, ...)
+    if tbl == nil or tbl[k] == nil then return nil end
+    if select('#', ...) == 0 then return tbl[k] end
+    return get(tbl[k], ...)
 end

-function LeoTrainer.stationEnter(eventcode, station)
-    if station ~= CRAFTING_TYPE_BLACKSMITHING and station ~= CRAFTING_TYPE_WOODWORKING and
-            station ~= CRAFTING_TYPE_CLOTHIER and station ~= CRAFTING_TYPE_JEWELRYCRAFTING then return end
+local function set(tbl, k, maybeValue, ...)
+    if select('#', ...) == 0 then
+      -- this will throw if the top-level tbl is nil, which is the desired behavior
+      tbl[k] = maybeValue
+      return
+    end
+    if tbl[k] == nil then tbl[k] = {} end
+    set(tbl[k], maybeValue, ...)
+end
+
+function LeoTrainer.GetPriorityLineList(charName, craftSkillFilter)
+    local charList
+    if charName == nil then
+        charList = LeoAltholic.ExportCharacters()
+    else
+        charList = {LeoAltholic.GetCharByName(charName)}
+    end
+
+    local craftSKillList = LeoAltholic.craftResearch
+    if craftSkillFilter ~= nil then craftSKillList = {craftSkillFilter} end
+    local knownCount = {}
+    local unknownTraits = {}
+    local lineList = {}
+    for _, char in pairs(charList) do
+        for _, craftSkill in pairs(craftSKillList) do
+            set(lineList, char.bio.name, craftSkill, {})
+
+            if LeoTrainer.isTrackingSkill(char.bio.name, craftSkill) and LeoTrainer.canFillSlotWithSkill(char.bio.name, craftSkill) then
+
+                for line = 1, GetNumSmithingResearchLines(craftSkill) do
+                    local lineName, _, numTraits = GetSmithingResearchLineInfo(craftSkill, line)
+
+                    set(unknownTraits, char.bio.name, craftSkill, line, {})
+                    set(knownCount, char.bio.name, craftSkill, line, 0)
+
+                    for trait = 1, numTraits do
+                        local isKnown, isResearching = LeoAltholic.ResearchStatus(craftSkill, line, trait, char.bio.name)
+                        if isKnown or isResearching then
+                            local numKnown = get(knownCount, char.bio.name, craftSkill, line)
+                            numKnown = numKnown + 1
+                            set(knownCount, char.bio.name, craftSkill, line, numKnown)
+                        elseif not isKnown then
+                            table.insert(unknownTraits[char.bio.name][craftSkill][line], trait)
+                        end
+                    end
+
+                    table.insert(lineList[char.bio.name][craftSkill], {
+                        line = line,
+                        lineName = lineName,
+                        count = knownCount[char.bio.name][craftSkill][line],
+                        unknownTraits = unknownTraits[char.bio.name][craftSkill][line],
+                        isResearching = isLineBeingResearched(char.research, craftSkill, line)
+                    })
+                end

-    LeoTrainer.inStation = station
-    LeoTrainer.queueScroll:RefreshData()
-    LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_NORMAL)
-    LeoTrainer.GetPatternIndexes(station)
+                table.sort(lineList[char.bio.name][craftSkill], function(a, b)
+                    return a.count < b.count
+                end)

-    local namesToPatternIndexes = {}
-    for patternIndex = 1, GetNumSmithingPatterns() do
-        local _, name = GetSmithingPatternInfo(patternIndex)
-        namesToPatternIndexes[name] = patternIndex
+            end
+        end
     end
+
+    return lineList
 end

-function LeoTrainer.stationExit(eventcode, station)
-    if station ~= CRAFTING_TYPE_BLACKSMITHING and station ~= CRAFTING_TYPE_WOODWORKING and
-            station ~= CRAFTING_TYPE_CLOTHIER and station ~= CRAFTING_TYPE_JEWELRYCRAFTING then return end
+function LeoTrainer.ScanBags(craftSkill)
+    local shouldResearch = LeoTrainer.research.ShouldResearch(craftSkill)
+    local shouldDeconstruct = LeoTrainer.deconstruct.ShouldDeconstruct(craftSkill)
+    local list = {}
+    local items = SHARED_INVENTORY:GenerateFullSlotData(nil, BAG_BACKPACK, BAG_BANK, BAG_SUBSCRIBER_BANK)
+    for _, data in pairs(items) do
+        local itemLink = GetItemLink(data.bagId, data.slotIndex, LINK_STYLE_BRACKETS)
+
+        local itemCraftSkill = LeoTrainer.ItemLinkToCraftskill(itemLink)
+        if itemCraftSkill ~= nil and itemCraftSkill > 0 and itemCraftSkill == craftSkill then
+            local handled = false
+            if shouldResearch then
+                handled = LeoTrainer.research.HandleItem(data.bagId, data.slotIndex, itemLink, craftSkill)
+            end
+            if not handled and shouldDeconstruct then
+                handled = LeoTrainer.deconstruct.HandleItem(data.bagId, data.slotIndex, itemLink, craftSkill)
+            end
+        end
+    end

-    LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_DISABLED)
-    LeoTrainer.inStation = 0
-    LeoTrainer.queueScroll:RefreshData()
-    LeoTrainerUI.HideUI()
+    return list
 end

 function LeoTrainer.isTrackingSkill(charName, craftId)
-    return LeoTrainer.savedVariables.trackedTraits[charName][craftId]
+    return LeoTrainer.data.trackedTraits[charName][craftId]
 end

 function LeoTrainer.setTrackingSkill(charName, craftId, tracking)
-    LeoTrainer.savedVariables.trackedTraits[charName][craftId] = tracking
+    LeoTrainer.data.trackedTraits[charName][craftId] = tracking
 end

 function LeoTrainer.canFillSlotWithSkill(charName, craftId)
-    return LeoTrainer.savedVariables.fillSlot[charName][craftId]
+    return LeoTrainer.data.fillSlot[charName][craftId]
 end

 function LeoTrainer.setFillSlotWithSkill(charName, craftId, tracking)
-    LeoTrainer.savedVariables.fillSlot[charName][craftId] = tracking
+    LeoTrainer.data.fillSlot[charName][craftId] = tracking
 end

 function LeoTrainer.Initialize()

-    LeoTrainer.savedVariables = ZO_SavedVars:NewAccountWide("LeoTrainerSavedVariables", 1, nil, nil, GetWorldName())
-    if LeoTrainer.savedVariables.trackedTraits == nil then
-        LeoTrainer.savedVariables.trackedTraits = {}
-    end
-    if not LeoTrainer.savedVariables.queue then
-        LeoTrainer.savedVariables.queue = {}
-    end
-    if not LeoTrainer.savedVariables.fillSlot then
-        LeoTrainer.savedVariables.fillSlot = {}
-    end
-    if not LeoTrainer.savedVariables.trainNirnhoned then
-        LeoTrainer.savedVariables.trainNirnhoned = false
-    end
-    if not LeoTrainer.savedVariables.researchItems then
-        LeoTrainer.savedVariables.researchItems = false
-    end
-    if not LeoTrainer.savedVariables.onlyResearchFCO then
-        LeoTrainer.savedVariables.onlyResearchFCO = false
-    end
-    if not LeoTrainer.savedVariables.defaultTrainer then
-        LeoTrainer.savedVariables.defaultTrainer = "Anyone"
-    end
-    for i, char in ipairs(LeoAltholic.ExportCharacters()) do
-        if LeoTrainer.savedVariables.trackedTraits[char.bio.name] == nil then
-            LeoTrainer.savedVariables.trackedTraits[char.bio.name] = {}
-        end
-        if not LeoTrainer.savedVariables.fillSlot[char.bio.name] then
-            LeoTrainer.savedVariables.fillSlot[char.bio.name] = {}
-        end
-        for _, craftId in pairs(LeoAltholic.craftResearch) do
-            LeoTrainer.savedVariables.trackedTraits[char.bio.name][craftId] = LeoTrainer.savedVariables.trackedTraits[char.bio.name][craftId] or false
-            LeoTrainer.savedVariables.fillSlot[char.bio.name][craftId] = LeoTrainer.savedVariables.fillSlot[char.bio.name][craftId] or false
-        end
-    end
+    LeoTrainer.settings = LibSavedVars
+        :NewAccountWide( "LeoTrainer_Settings", "Account", LeoTrainer.settingsDefaults )
+        :AddCharacterSettingsToggle( "LeoTrainer_Settings", "Characters" )
+    LeoTrainer.settings.loaded = true

-    local LibFeedback = LibStub:GetLibrary("LibFeedback")
-    local showButton, feedbackWindow = LibFeedback:initializeFeedbackWindow(LeoTrainer,
-            LeoTrainer.name,LeoTrainerWindow, "@LeandroSilva",
-            {TOPRIGHT, LeoTrainerWindow, TOPRIGHT,-50,3},
-            {0,1000,10000,"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y9KM4PZU2UZ6A"},
-            "If you found a bug, have a request or a suggestion, or simply wish to donate, send a mail.")
-    LeoTrainer.feedback = feedbackWindow
-    LeoTrainer.feedback:SetDrawLayer(DL_OVERLAY)
-    LeoTrainer.feedback:SetDrawTier(DT_MEDIUM)
+    LeoTrainer.data = LibSavedVars:NewAccountWide( "LeoTrainer_Data", LeoTrainer.dataDefaults )
+    LeoTrainer.data.loaded = true

-    LeoTrainerWindowTitle:SetText(LeoTrainer.displayName .. " v" .. LeoTrainer.version)
+    LeoTrainer.stage = LEOTRAINER_STAGE_START
+
+    LeoTrainer.craft.Initialize()
+    LeoTrainer.research.Initialize()
+    LeoTrainer.bank.Initialize()
+    LeoTrainer.ui.Initialize()

     SLASH_COMMANDS["/leotrainer"] = function(cmd)
-        LeoTrainerUI:ToggleUI()
+        if cmd == nil or cmd == "" then
+            LeoTrainer.ui:ToggleUI()
+            return
+        end
+
+        if cmd == "debug" then
+            if not LeoTrainer.isDebug then
+                LeoTrainer.isDebug = true
+                LeoTrainer.debug("Debug mode ON")
+            else
+                LeoTrainer.isDebug = false
+                LeoTrainer.log("Debug mode OFF")
+            end
+            return
+        end
+
+        if cmd == "decon" and LeoTrainer.IsInUsableStation() then
+            LeoTrainer.deconstruct.DoDeconstruct()
+        end
     end

     if GetDisplayName() == "@LeandroSilva" then
@@ -252,57 +318,24 @@ function LeoTrainer.Initialize()
             ReloadUI()
         end
     end
-
-    LeoTrainer.knowledge = {}
-    LeoTrainer.missingKnowledge = {}
-    local charList = LeoAltholic.ExportCharacters()
-    for _, char in pairs(charList) do
-        for _,craft in pairs(LeoAltholic.craftResearch) do
-            if LeoTrainer.knowledge[craft] == nil then LeoTrainer.knowledge[craft] = {} end
-            if LeoTrainer.missingKnowledge[craft] == nil then LeoTrainer.missingKnowledge[craft] = {} end
-            for line = 1, GetNumSmithingResearchLines(craft) do
-                if LeoTrainer.knowledge[craft][line] == nil then LeoTrainer.knowledge[craft][line] = {} end
-                if LeoTrainer.missingKnowledge[craft][line] == nil then LeoTrainer.missingKnowledge[craft][line] = {} end
-                local lineName, lineIcon, numTraits = GetSmithingResearchLineInfo(craft, line)
-                for trait = 1, numTraits do
-                    if LeoTrainer.knowledge[craft][line][trait] == nil then LeoTrainer.knowledge[craft][line][trait] = {} end
-                    if LeoTrainer.missingKnowledge[craft][line][trait] == nil then LeoTrainer.missingKnowledge[craft][line][trait] = {} end
-                    if char.research.done[craft][line][trait] == true then
-                        table.insert(LeoTrainer.knowledge[craft][line][trait], char.bio.name)
-                    else
-                        table.insert(LeoTrainer.missingKnowledge[craft][line][trait], char.bio.name)
-                    end
-                end
-            end
-        end
-    end
-
-    LeoTrainer.settings = LeoTrainer_Settings:New()
-    LeoTrainer.settings:CreatePanel()
-
-    LeoTrainer.launcher = LeoTrainer_Launcher:New()
-    LeoTrainer.launcher:SetHidden(false)
-
-    LeoTrainerUI.RestorePosition()
-    LeoTrainer.CreateUI()
-    LeoTrainer.UpdateUI()
 end

 function LeoTrainer.log(message)
     d(LeoTrainer.chatPrefix .. message)
 end

-local function OnSettingsControlsCreated(panel)
-    LeoTrainer_Settings:OnSettingsControlsCreated(panel)
+function LeoTrainer.debug(message)
+    if not LeoTrainer.isDebug then return end
+    LeoTrainer.log('[D] ' .. message)
 end

 local function onNewMovementInUIMode(eventCode)
-    if not LeoTrainerWindow:IsHidden() then LeoTrainerUI:CloseUI() end
+    if not LeoTrainerWindow:IsHidden() then LeoTrainer.ui:CloseUI() end
 end

 local function onChampionPerksSceneStateChange(oldState,newState)
     if newState == SCENE_SHOWING then
-        if not LeoTrainerWindow:IsHidden() then LeoTrainerUI:CloseUI() end
+        if not LeoTrainerWindow:IsHidden() then LeoTrainer.ui:CloseUI() end
     end
 end

@@ -312,14 +345,20 @@ local function onLeoAltholicInitialized()

     LeoTrainer.Initialize()

-    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFTING_STATION_INTERACT, LeoTrainer.stationEnter)
+    if WritCreater then
+        EVENT_MANAGER:UnregisterForEvent(WritCreater.name, EVENT_CRAFTING_STATION_INTERACT)
+        EVENT_MANAGER:UnregisterForEvent(WritCreater.name, EVENT_CRAFT_COMPLETED)
+    end
+    EVENT_MANAGER:UnregisterForEvent("LibLazyCrafting", EVENT_CRAFTING_STATION_INTERACT)
+
+    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFTING_STATION_INTERACT, function (_, ...) LeoTrainer.stationEnter(...) end)
     EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_END_CRAFTING_STATION_INTERACT, LeoTrainer.stationExit)
-    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED, LeoTrainer.OnCraftComplete)
-    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFT_FAILED, LeoTrainer.OnCraftFailed)
-    CALLBACK_MANAGER:RegisterCallback("LAM-PanelControlsCreated", OnSettingsControlsCreated)
+    CALLBACK_MANAGER:RegisterCallback("LAM-PanelControlsCreated", function(panel) LeoTrainer_SettingsMenu:OnSettingsControlsCreated(panel) end)
     EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_NEW_MOVEMENT_IN_UI_MODE, onNewMovementInUIMode)
     CHAMPION_PERKS_SCENE:RegisterCallback('StateChange', onChampionPerksSceneStateChange)

+    LeoTrainer.LLC = LibLazyCrafting:AddRequestingAddon(LeoTrainer.name, true, LeoTrainer.LLC_Completed)
+
     LeoTrainer.log("started.")
 end

@@ -331,4 +370,3 @@ function LeoTrainer.OnAddOnLoaded(event, addonName)
 end

 CALLBACK_MANAGER:RegisterCallback("LeoAltholicInitialized", onLeoAltholicInitialized)
---EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_ADD_ON_LOADED, LeoTrainer.OnAddOnLoaded)
diff --git a/LeoTrainer.txt b/LeoTrainer.txt
old mode 100644
new mode 100755
index 6bf884a..dfa4054
--- a/LeoTrainer.txt
+++ b/LeoTrainer.txt
@@ -1,15 +1,20 @@
 ## Title: Leo's Trainer
-## APIVersion: 100029 100030
-## Version: 1.3.3
-## AddOnVersion: 133
+## APIVersion: 100030
+## Version: 2.0.0
+## AddOnVersion: 200
 ## Author: |c39B027@LeandroSilva|r
-## SavedVariables: LeoTrainerSavedVariables
-## DependsOn: LeoAltholic LibStub LibFeedback LibAddonMenu-2.0
+## SavedVariables: LeoTrainer_Settings LeoTrainer_Data
+## OptionalDependsOn: FCOItemSaver PersonalAssistant DolgubonsLazyWritCreator
+## DependsOn: LeoAltholic LibLazyCrafting LibFeedback LibAddonMenu-2.0 LibSavedVars

 LeoTrainerConst.lua
-LeoTrainerUI.lua
 LeoTrainer.lua
 LeoTrainer.xml
+Ui.lua
+Craft.lua
+Research.lua
+Deconstruct.lua
+Bank.lua
 Settings.xml
 Settings.lua
 Launcher.xml
diff --git a/LeoTrainer.xml b/LeoTrainer.xml
old mode 100644
new mode 100755
index a287286..36e8a32
--- a/LeoTrainer.xml
+++ b/LeoTrainer.xml
@@ -7,9 +7,9 @@
         <TopLevelControl name="LeoTrainerWindow" mouseEnabled="true" movable="true" hidden="true" clampedToScreen="true">
             <Dimensions x="850" y="840" />
             <Anchor point="TOP" relativeTo="GuiRoot" relativePoint="TOPCENTER" offsetY="100" />
-            <OnMoveStop> LeoTrainerUI:OnWindowMoveStop() </OnMoveStop>
-            <OnHide> LeoTrainerUI:OnHide(self, hidden) </OnHide>
-            <OnShow> LeoTrainerUI:OnShow(self, hidden) </OnShow>
+            <OnMoveStop> LeoTrainer.ui:OnWindowMoveStop() </OnMoveStop>
+            <OnHide> LeoTrainer.ui:OnHide(self, hidden) </OnHide>
+            <OnShow> LeoTrainer.ui:OnShow(self, hidden) </OnShow>
             <Controls>
                 <Backdrop name="$(parent)BG" centerColor="000000" edgeColor="222222">
                     <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)"/>
@@ -24,7 +24,7 @@
                 <Button name="$(parent)Close" clickSound="Click">
                     <Anchor point="TOPRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)BG" offsetX="-5" offsetY="4"/>
                     <Dimensions x="40" y="40"/>
-                    <OnClicked>LeoTrainerUI:CloseUI()</OnClicked>
+                    <OnClicked>LeoTrainer.ui:CloseUI()</OnClicked>
                     <Controls>
                         <Backdrop name="$(parent)BG" centerColor="101010" edgeColor="202020">
                             <AnchorFill/>
@@ -55,7 +55,7 @@
                     <OnMouseExit>ZO_Tooltips_HideTextTooltip()</OnMouseExit>
                     <OnClicked>
                         SCENE_MANAGER:HideTopLevel(LeoTrainerWindow)
-                        DoCommand("/leotraineroptions")
+                        DoCommand("/lto")
                     </OnClicked>
                     <Controls>
                         <Backdrop name="$(parent)BG" centerColor="101010" edgeColor="202020">
@@ -150,110 +150,110 @@
                         <Label name="$(parent)Trait11" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="0" offsetY="50"/>
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait12" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait11" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait13" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait12" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait14" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait13" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait15" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait14" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait16" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait15" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait17" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait16" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait18" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait17" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait19" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait18" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>

                         <Label name="$(parent)Trait1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait11" relativePoint="TOPLEFT" offsetX="400" offsetY="0"/>
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait2" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait1" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait3" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait2" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait4" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait3" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait5" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait4" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait6" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait5" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait7" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait6" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait8" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait7" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait9" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait8" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>

@@ -354,55 +354,55 @@
                         <Label name="$(parent)Trait1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait19" relativePoint="TOPLEFT" offsetX="0" offsetY="50"/>
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait2" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait1" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait3" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait2" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait4" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait3" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait5" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait4" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait6" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait5" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait7" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait6" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait8" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait7" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait9" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait8" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>

@@ -541,110 +541,110 @@
                         <Label name="$(parent)Trait11" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="10" offsetY="50"/>
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait12" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait11" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait13" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait12" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait14" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait13" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait15" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait14" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait16" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait15" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait17" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait16" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait18" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait17" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait19" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait18" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>

                         <Label name="$(parent)Trait1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait11" relativePoint="TOPLEFT" offsetX="320" offsetY="0"/>
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait2" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait1" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait3" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait2" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait4" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait3" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait5" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait4" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait6" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait5" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait7" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait6" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait8" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait7" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>
                         <Label name="$(parent)Trait9" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Trait8" relativePoint="BOTTOMLEFT" />
                             <Dimensions x="150" y="28"/>
-                            <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                            <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                             <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                         </Label>

@@ -669,55 +669,55 @@
                                 <Label name="$(parent)Trait1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="10" offsetY="50"/>
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait2" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait1" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait3" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait2" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait4" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait3" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait5" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait4" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait6" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait5" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait7" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait6" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait8" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait7" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                                 <Label name="$(parent)Trait9" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Trait8" relativePoint="BOTTOMLEFT" />
                                     <Dimensions x="150" y="28"/>
-                                    <OnMouseEnter> LeoTrainer:OnMouseEnterTrait(self) </OnMouseEnter>
+                                    <OnMouseEnter> LeoTrainer.ui:OnMouseEnterTrait(self) </OnMouseEnter>
                                     <OnMouseExit>ClearTooltip(ItemTooltip)</OnMouseExit>
                                 </Label>
                             </Controls>
@@ -911,6 +911,5 @@
             </OnInitialized>
         </Control>

-
     </Controls>
 </GuiXml>
diff --git a/LeoTrainerConst.lua b/LeoTrainerConst.lua
old mode 100644
new mode 100755
index 5f402f6..327cf7e
--- a/LeoTrainerConst.lua
+++ b/LeoTrainerConst.lua
@@ -1,18 +1,61 @@

-LeoTrainer = {}
-LeoTrainerUI = {}
+LeoTrainer = {
+    ui = {},
+    craft = {},
+    research = {},
+    bank = {},
+    deconstruct = {}
+}
 LeoTrainer.name = "LeoTrainer"
 LeoTrainer.displayName = "Leo's Trainer"
-LeoTrainer.version = "1.3.3"
+LeoTrainer.version = "2.0.0"
 LeoTrainer.chatPrefix = "|c39B027" .. LeoTrainer.name .. "|r: "
 LeoTrainer.setting = nil
 LeoTrainer.hidden = true
 LeoTrainer.filterKnown = false
-LeoTrainer.inStation = 0
 LeoTrainer.myself = {}
-LeoTrainer.namesToPatternIndexes = {}
-LeoTrainer.isCrafting = 0
-LeoTrainer.continueCrating = false
+LeoTrainer.isDebug = false
+LeoTrainer.settingsDefaults = {
+    research = {
+        auto = false,
+        listInChat = true,
+        allowCrafted = true,
+        allowSets = false,
+        maxQuality = {
+            [CRAFTING_TYPE_BLACKSMITHING]   = ITEM_QUALITY_NORMAL,
+            [CRAFTING_TYPE_CLOTHIER]        = ITEM_QUALITY_NORMAL,
+            [CRAFTING_TYPE_WOODWORKING]     = ITEM_QUALITY_NORMAL,
+            [CRAFTING_TYPE_JEWELRYCRAFTING] = ITEM_QUALITY_NORMAL,
+        },
+    },
+    craft = {
+        auto = false
+    },
+    deconstruct = {
+        auto = false,
+        listInChat = true,
+        allowBank = true,
+        allowSets = false,
+        onlyClosestLevel = false,
+        maxQuality = {
+            [CRAFTING_TYPE_BLACKSMITHING]   = ITEM_QUALITY_ARCANE,
+            [CRAFTING_TYPE_CLOTHIER]        = ITEM_QUALITY_ARCANE,
+            [CRAFTING_TYPE_WOODWORKING]     = ITEM_QUALITY_ARCANE,
+            [CRAFTING_TYPE_JEWELRYCRAFTING] = ITEM_QUALITY_ARCANE,
+        },
+    },
+    bank = {
+        autoDeposit = false
+    }
+}
+LeoTrainer.dataDefaults = {
+    trackedTraits = {},
+    craftQueue = {},
+    fillSlot = {},
+    trainNirnhoned = false,
+    defaultTrainer = "Anyone",
+    position = { left = 200; top = 200; }
+}

 LeoTrainer.const = {}

@@ -519,5 +562,13 @@ LeoTrainer.const.colors = {
     blue = ZO_ColorDef:New(0,0,1,1),
 }

+LEOTRAINER_STAGE_START = 0
+LEOTRAINER_STAGE_RESEARCH = 1
+LEOTRAINER_STAGE_DECONSTRUCT = 2
+LEOTRAINER_STAGE_CRAFT = 3
+LEOTRAINER_STAGE_DONE = 4
+
 ZO_CreateStringId('SI_BINDING_NAME_LEOTRAINER_TOGGLE_WINDOW', "Show/Hide Main Window")
 ZO_CreateStringId('SI_BINDING_NAME_LEOTRAINER_CRAFT_NEXT', "Craft next in queue")
+ZO_CreateStringId('SI_BINDING_NAME_LEOTRAINER_DECON', "Deconstruct")
+ZO_CreateStringId('SI_BINDING_NAME_LEOTRAINER_RESEARCH', "Research")
\ No newline at end of file
diff --git a/Research.lua b/Research.lua
new file mode 100755
index 0000000..b285ff4
--- /dev/null
+++ b/Research.lua
@@ -0,0 +1,359 @@
+
+local Research = {
+    queue = {},
+    isResearching = false,
+    keybindStripDescriptor =
+    {
+        {
+            name = "Research",
+            keybind = "LEOTRAINER_RESEARCH",
+            callback = function() LeoTrainer.research.ResearchNext() end--,
+        },
+        alignment = KEYBIND_STRIP_ALIGN_CENTER,
+    }
+}
+
+function Research.GetResearchData(link)
+    if not link then return false end
+
+    local craftSkill, line
+    local trait = GetItemLinkTraitInfo(link)
+    local equipType = GetItemLinkEquipType(link)
+
+    if trait == ITEM_TRAIT_TYPE_NONE or trait == ITEM_TRAIT_TYPE_ARMOR_INTRICATE or trait == ITEM_TRAIT_TYPE_ARMOR_ORNATE
+        or trait == ITEM_TRAIT_TYPE_WEAPON_INTRICATE or trait == ITEM_TRAIT_TYPE_WEAPON_ORNATE
+        or trait == ITEM_TRAIT_TYPE_JEWELRY_INTRICATE or trait == ITEM_TRAIT_TYPE_JEWELRY_ORNATE then return false end
+
+    local armorType = GetItemLinkArmorType(link)
+    local weaponType = GetItemLinkWeaponType(link)
+    if trait == ITEM_TRAIT_TYPE_ARMOR_NIRNHONED then trait = 19 end
+    if trait == ITEM_TRAIT_TYPE_WEAPON_NIRNHONED then trait = 9 end
+    if weaponType == WEAPONTYPE_AXE then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 1;
+    elseif weaponType == WEAPONTYPE_HAMMER then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 2;
+    elseif weaponType == WEAPONTYPE_SWORD then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 3
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_AXE then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 4;
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_HAMMER then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 5;
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_SWORD then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 6;
+    elseif weaponType == WEAPONTYPE_DAGGER then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = 7;
+    elseif weaponType == WEAPONTYPE_BOW then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 1;
+    elseif weaponType == WEAPONTYPE_FIRE_STAFF then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 2;
+    elseif weaponType == WEAPONTYPE_FROST_STAFF then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 3;
+    elseif weaponType == WEAPONTYPE_LIGHTNING_STAFF then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 4;
+    elseif weaponType == WEAPONTYPE_HEALING_STAFF then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 5;
+    elseif weaponType == WEAPONTYPE_SHIELD then craftSkill = CRAFTING_TYPE_WOODWORKING; line = 6;trait=trait-10;
+    elseif equipType == EQUIP_TYPE_CHEST then line = 1
+    elseif equipType == EQUIP_TYPE_FEET then line = 2
+    elseif equipType == EQUIP_TYPE_HAND then line = 3
+    elseif equipType == EQUIP_TYPE_HEAD then line = 4
+    elseif equipType == EQUIP_TYPE_LEGS then line = 5
+    elseif equipType == EQUIP_TYPE_SHOULDERS then line = 6
+    elseif equipType == EQUIP_TYPE_WAIST then line = 7
+    end
+
+    if equipType == EQUIP_TYPE_NECK or equipType == EQUIP_TYPE_RING then
+        craftSkill = CRAFTING_TYPE_JEWELRYCRAFTING
+        line = equipType == EQUIP_TYPE_NECK and 1 or 2
+        if trait == ITEM_TRAIT_TYPE_JEWELRY_ARCANE then trait = 1
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_HEALTHY then trait = 2
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_ROBUST then trait = 3
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_TRIUNE then trait = 4
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_INFUSED then trait = 5
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_PROTECTIVE then trait = 6
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_SWIFT then trait = 7
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_HARMONY then trait = 8
+        elseif trait == ITEM_TRAIT_TYPE_JEWELRY_BLOODTHIRSTY then trait = 9
+        end
+    else
+        if armorType == ARMORTYPE_HEAVY then craftSkill = CRAFTING_TYPE_BLACKSMITHING; line = line + 7; trait = trait - 10; end
+        if armorType == ARMORTYPE_MEDIUM then craftSkill = CRAFTING_TYPE_CLOTHIER; line = line + 7; trait = trait - 10; end
+        if armorType == ARMORTYPE_LIGHT then craftSkill = CRAFTING_TYPE_CLOTHIER; trait = trait - 10; end
+    end
+    if craftSkill and line and trait then return craftSkill, line, trait
+    else return false end
+end
+
+local function canIResearchItem(itemLink)
+    local craftSkill, line, trait = Research.GetResearchData(itemLink)
+
+    if craftSkill == nil then return false end
+
+    local isKnown, isResearching = LeoAltholic.ResearchStatus(craftSkill, line, trait)
+    if isKnown then
+        -- LeoTrainer.debug('already known')
+        return false
+    end
+
+    if isResearching then
+        -- LeoTrainer.debug('is researching')
+        return false
+    end
+
+    return true
+end
+
+function Research.CanItemBeResearched(bagId, slotIndex, itemLink, craftSkill)
+    if not FCOIS then return false end
+
+    if itemLink == nil then itemLink = GetItemLink(bagId, slotIndex) end
+
+    local type = GetItemType(bagId, slotIndex)
+    if type ~= ITEMTYPE_ARMOR and type ~= ITEMTYPE_WEAPON then return false end
+
+    if FCOIS.IsIconEnabled(FCOIS_CON_ICON_RESEARCH) and not FCOIS.IsMarked(bagId, slotIndex, FCOIS_CON_ICON_RESEARCH) then
+        -- LeoTrainer.debug(itemLink .. " not marked for research")
+        return false
+    end
+
+    if LeoTrainer.settings.research.allowCrafted and GetItemCreatorName(bagId, slotIndex) == nil then
+        -- LeoTrainer.debug(itemLink .. " not crafted")
+        return false
+    end
+
+    local hasSet, setName = GetItemLinkSetInfo(itemLink)
+    if not LeoTrainer.settings.research.allowSets and hasSet then
+        -- LeoTrainer.debug(itemLink .. " is from set " .. setName)
+        return false
+    end
+
+    if craftSkill ~= nil and craftSkill > 0 and LeoTrainer.settings.research.maxQuality[craftSkill] < GetItemQuality(bagId, slotIndex) then
+        -- LeoTrainer.debug(itemLink .. " is with higher quality")
+        return false
+    end
+
+    return true
+end
+
+function Research.ScanBags()
+    local list = {}
+    local items = SHARED_INVENTORY:GenerateFullSlotData(nil, BAG_BACKPACK, BAG_BANK, BAG_SUBSCRIBER_BANK)
+    for _, data in pairs(items) do
+        local itemLink = GetItemLink(data.bagId, data.slotIndex, LINK_STYLE_BRACKETS)
+        local craftSkill, line, trait = LeoTrainer.research.GetResearchData(itemLink)
+        if LeoTrainer.research.CanItemBeResearched(data.bagId, data.slotIndex, itemLink, craftSkill) then
+            table.insert(list, {
+                bagId = data.bagId,
+                slotIndex = data.slotIndex,
+                itemLink = itemLink,
+                craftSkill = craftSkill,
+                line = line,
+                trait = trait,
+                selected = false
+            })
+        end
+    end
+
+    return list
+end
+
+function Research.HandleItem(bagId, slotIndex, itemLink, craftSkill)
+
+    local itemCraftSkill, line, trait = Research.GetResearchData(itemLink)
+
+    if itemCraftSkill ~= craftSkill then return false end
+
+    if not Research.CanItemBeResearched(bagId, slotIndex, itemLink, craftSkill) then return false end
+
+    if not canIResearchItem(itemLink) then return false end
+
+    if LeoTrainer.settings.research.listInChat then
+        LeoTrainer.log("Can be researched: " .. itemLink)
+    end
+
+    table.insert(Research.queue, {
+        bagId = bagId,
+        slotIndex = slotIndex,
+        itemLink = itemLink,
+        craftSkill = craftSkill,
+        line = line,
+        trait = trait,
+        selected = false,
+        isResearching = false
+    })
+
+    return true
+end
+
+function Research.OnResearchComplete(_, craftSkill)
+    EVENT_MANAGER:UnregisterForUpdate(LeoTrainer.name .. ".ResearchTimeout")
+    EVENT_MANAGER:UnregisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED)
+
+    if not Research.isResearching then
+        LeoTrainer.nextStage(true)
+        return
+    end
+
+    local myName = GetUnitName("player")
+    local researching, total = LeoAltholic.GetResearchCounters(craftSkill)
+    for j, data in pairs(Research.queue) do
+        if data.isResearching == true then
+            table.remove(Research.queue, j)
+            break
+        end
+    end
+    Research.isResearching = false
+
+    if researching >= total then
+        LeoTrainer.debug("No empty research slots.")
+        LeoTrainer.nextStage(true)
+        return
+    end
+
+    if #Research.queue > 0 then
+        zo_callLater(function() Research.ResearchNext(craftSkill) end, 200)
+        return
+    end
+
+    LeoTrainer.nextStage(true)
+end
+
+local function OnResearchTimeout(craftSkill)
+    return function()
+        ZO_Alert(UI_ALERT_CATEGORY_ALERT, nil, "Timeout during research")
+        EVENT_MANAGER:UnregisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED)
+        LeoTrainer.nextStage()
+    end
+end
+
+local function get(tbl, k, ...)
+    if tbl == nil or tbl[k] == nil then return nil end
+    if select('#', ...) == 0 then return tbl[k] end
+    return get(tbl[k], ...)
+end
+
+local lineList
+
+function Research.ResearchNext(craftSkill)
+    Research.isResearching = false
+
+    if craftSkill == nil then craftSkill = GetCraftingInteractionType() end
+
+    if #Research.queue == 0 then
+        LeoTrainer.debug("Nothing on research queue")
+        LeoTrainer.nextStage()
+        return
+    end
+
+    if not LeoTrainer.IsInUsableStation() or not LeoAltholic.HasStillResearchFor(craftSkill) then
+        LeoTrainer.debug("Nothing to research here.")
+        LeoTrainer.nextStage()
+        return
+    end
+
+    local myName = GetUnitName("player")
+    local researching, total = LeoAltholic.GetResearchCounters(craftSkill, myName)
+    if researching >= total then
+        LeoTrainer.debug("No empty research slots.")
+        LeoTrainer.nextStage()
+        return
+    end
+    if IsPerformingCraftProcess() == true then
+        LeoTrainer.debug("Still crafting")
+        Research.isResearching = true
+        zo_callLater(function() Research.ResearchNext(craftSkill) end, 500)
+        return
+    end
+
+    -- loop through the priority list and items to find a match
+    if lineList == nil then lineList = LeoTrainer.GetPriorityLineList(myName, craftSkill) end
+    for i, lineData in ipairs(lineList[myName][craftSkill]) do
+        if not lineData.added and not lineData.isResearching then
+            for j, data in pairs(Research.queue) do
+                if lineData.line == data.line then
+                    lineList[myName][craftSkill][i].added = true
+                    local itemLink = GetItemLink(data.bagId, data.slotIndex, LINK_STYLE_BRACKETS)
+                    local traitType = GetItemLinkTraitInfo(itemLink)
+                    local traitName = GetString("SI_ITEMTRAITTYPE", traitType)
+                    local message = zo_strformat("<<1>> <<2>> (<<3>>)",
+                        GetString(SI_GAMEPAD_SMITHING_CURRENT_RESEARCH_HEADER),
+                        itemLink,
+                        traitName)
+                    LeoTrainer.log(message)
+
+                    EVENT_MANAGER:RegisterForUpdate(LeoTrainer.name .. ".ResearchTimeout", 2000, OnResearchTimeout(craftSkill))
+                    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED, Research.OnResearchComplete) -- normal craft is handled by LLC
+
+                    Research.isResearching = true
+                    Research.queue[j].isResearching = true
+                    ResearchSmithingTrait(data.bagId, data.slotIndex)
+                    return
+                end
+            end
+        end
+    end
+
+    LeoTrainer.debug("No item found for research")
+    LeoTrainer.nextStage()
+end
+
+function Research.ShouldResearch(craftSkill)
+    return LeoAltholic.HasStillResearchFor(craftSkill)
+end
+
+function Research.OnStationEnter(craftSkill)
+    lineList = nil
+    if not LeoAltholic.HasStillResearchFor(craftSkill) then
+        LeoTrainer.nextStage()
+        return
+    end
+
+    if #Research.queue > 0 then
+        KEYBIND_STRIP:AddKeybindButtonGroup(Research.keybindStripDescriptor)
+    end
+
+    if #Research.queue == 0 or not LeoTrainer.settings.research.auto then
+        LeoTrainer.nextStage()
+        return
+    end
+
+    Research.ResearchNext(craftSkill)
+end
+
+function Research.OnStationExit(craftSkill)
+    EVENT_MANAGER:UnregisterForUpdate(LeoTrainer.name .. ".ResearchTimeout")
+    EVENT_MANAGER:UnregisterForEvent(LeoTrainer.name, EVENT_CRAFT_COMPLETED)
+    KEYBIND_STRIP:RemoveKeybindButtonGroup(Research.keybindStripDescriptor)
+    Research.isResearching = false
+    lineList = nil
+    Research.queue = {}
+end
+
+function Research.Initialize()
+    local charList = LeoAltholic.ExportCharacters()
+
+    LeoTrainer.knowledge = {}
+    LeoTrainer.missingKnowledge = {}
+
+    for _, char in pairs(charList) do
+        if LeoTrainer.data.trackedTraits[char.bio.name] == nil then
+            LeoTrainer.data.trackedTraits[char.bio.name] = {}
+        end
+        if not LeoTrainer.data.fillSlot[char.bio.name] then
+            LeoTrainer.data.fillSlot[char.bio.name] = {}
+        end
+        for _, craftId in pairs(LeoAltholic.craftResearch) do
+            LeoTrainer.data.trackedTraits[char.bio.name][craftId] = LeoTrainer.data.trackedTraits[char.bio.name][craftId] or false
+            LeoTrainer.data.fillSlot[char.bio.name][craftId] = LeoTrainer.data.fillSlot[char.bio.name][craftId] or false
+        end
+
+        for _,craft in pairs(LeoAltholic.craftResearch) do
+            if LeoTrainer.knowledge[craft] == nil then LeoTrainer.knowledge[craft] = {} end
+            if LeoTrainer.missingKnowledge[craft] == nil then LeoTrainer.missingKnowledge[craft] = {} end
+            for line = 1, GetNumSmithingResearchLines(craft) do
+                if LeoTrainer.knowledge[craft][line] == nil then LeoTrainer.knowledge[craft][line] = {} end
+                if LeoTrainer.missingKnowledge[craft][line] == nil then LeoTrainer.missingKnowledge[craft][line] = {} end
+                local _, _, numTraits = GetSmithingResearchLineInfo(craft, line)
+                for trait = 1, numTraits do
+                    if LeoTrainer.knowledge[craft][line][trait] == nil then LeoTrainer.knowledge[craft][line][trait] = {} end
+                    if LeoTrainer.missingKnowledge[craft][line][trait] == nil then LeoTrainer.missingKnowledge[craft][line][trait] = {} end
+                    if char.research.done[craft][line][trait] == true then
+                        table.insert(LeoTrainer.knowledge[craft][line][trait], char.bio.name)
+                    else
+                        table.insert(LeoTrainer.missingKnowledge[craft][line][trait], char.bio.name)
+                    end
+                end
+            end
+        end
+    end
+end
+
+LeoTrainer.research = Research
diff --git a/Settings.lua b/Settings.lua
old mode 100644
new mode 100755
index fd22fe3..78af961
--- a/Settings.lua
+++ b/Settings.lua
@@ -1,19 +1,57 @@

 LeoTrainer.craftNames = {"Blacksmith", "Clothing", "Woodworking", "Jewelry"}

-LeoTrainer_Settings = ZO_Object:Subclass()
-local LAM = LibStub("LibAddonMenu-2.0")
+LeoTrainer_SettingsMenu = ZO_Object:Subclass()
+local LAM = LibAddonMenu2

-function LeoTrainer_Settings:New(...)
+function LeoTrainer_SettingsMenu:New(...)
     local object = ZO_Object.New(self)
     object:Initialize(...)
     return object
 end

-function LeoTrainer_Settings:Initialize()
+function LeoTrainer_SettingsMenu:Initialize()
 end

-function LeoTrainer_Settings:CreatePanel()
+function LeoTrainer_SettingsMenu:SelectAll(craftSkill)
+    for i, char in ipairs(LeoAltholic.GetCharacters()) do
+        if craftSkill ~= nil then
+            LeoTrainer.setTrackingSkill(char.bio.name, craftSkill, true)
+            LeoTrainer.setFillSlotWithSkill(char.bio.name, craftSkill, true)
+        else
+            for _, craftSkill in ipairs({ CRAFTING_TYPE_BLACKSMITHING, CRAFTING_TYPE_CLOTHIER, CRAFTING_TYPE_WOODWORKING, CRAFTING_TYPE_JEWELRYCRAFTING }) do
+                LeoTrainer.setTrackingSkill(char.bio.name, craftSkill, true)
+                LeoTrainer.setFillSlotWithSkill(char.bio.name, craftSkill, true)
+            end
+        end
+    end
+    ReloadUI()
+end
+function LeoTrainer_SettingsMenu:DeselectAll(craftSkill)
+    for i, char in ipairs(LeoAltholic.GetCharacters()) do
+        if craftSkill ~= nil then
+            LeoTrainer.setTrackingSkill(char.bio.name, craftSkill, false)
+            LeoTrainer.setFillSlotWithSkill(char.bio.name, craftSkill, false)
+        else
+            for _, craftSkill in ipairs({ CRAFTING_TYPE_BLACKSMITHING, CRAFTING_TYPE_CLOTHIER, CRAFTING_TYPE_WOODWORKING, CRAFTING_TYPE_JEWELRYCRAFTING }) do
+                LeoTrainer.setTrackingSkill(char.bio.name, craftSkill, false)
+                LeoTrainer.setFillSlotWithSkill(char.bio.name, craftSkill, false)
+            end
+        end
+    end
+    ReloadUI()
+end
+
+local qualityChoices = {}
+local qualityChoicesValues = {}
+for quality = ITEM_QUALITY_MIN_VALUE, ITEM_QUALITY_MAX_VALUE do
+    local qualityColor = GetItemQualityColor(quality)
+    local qualityString = qualityColor:Colorize(GetString("SI_ITEMQUALITY", quality))
+    table.insert(qualityChoicesValues, quality)
+    table.insert(qualityChoices, qualityString)
+end
+
+function LeoTrainer_SettingsMenu:CreatePanel()
     local OptionsName = "LeoTrainerOptions"
     local panelData = {
         type = "panel",
@@ -21,11 +59,10 @@ function LeoTrainer_Settings:CreatePanel()
         displayName = "|c39B027"..LeoTrainer.displayName.."|r",
         author = "@LeandroSilva",
         version = LeoTrainer.version,
-        registerForRefresh = false,
+        registerForRefresh = true,
         registerForDefaults = false,
-        slashCommand = "/leotraineroptions",
+        slashCommand = "/lto",
         website = "http://www.esoui.com/downloads/info2162-LeosTrainer.html",
-        --resetFunc = function() end
     }
     LAM:RegisterAddonPanel(OptionsName, panelData)

@@ -36,29 +73,155 @@ function LeoTrainer_Settings:CreatePanel()
         table.insert(charNames, char.bio.name)
     end

+    local researchMaxQualities = {
+        {
+            type = "description",
+            text = GetString(SI_KEEP_UPGRADE_AT_MAX)
+        }
+    }
+    local deconstructMaxQualities = {
+        {
+            type = "description",
+            text = GetString(SI_KEEP_UPGRADE_AT_MAX)
+        }
+    }
+    for _, craftSkill in ipairs({ CRAFTING_TYPE_BLACKSMITHING, CRAFTING_TYPE_CLOTHIER, CRAFTING_TYPE_WOODWORKING, CRAFTING_TYPE_JEWELRYCRAFTING }) do
+        table.insert(researchMaxQualities, {
+            type = "dropdown",
+            width = "half",
+            choices = qualityChoices,
+            choicesValues = qualityChoicesValues,
+            name = zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(craftSkill)),
+            getFunc = function() return LeoTrainer.settings.research.maxQuality[craftSkill] end,
+            setFunc = function(value) LeoTrainer.settings.research.maxQuality[craftSkill] = value end,
+            default = LeoTrainer.settingsDefaults.research.maxQuality[craftSkill],
+            disabled = function() return not LeoTrainer.settings.research.auto end,
+        });
+        table.insert(deconstructMaxQualities, {
+            type = "dropdown",
+            width = "half",
+            choices = qualityChoices,
+            choicesValues = qualityChoicesValues,
+            name = zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(craftSkill)),
+            getFunc = function() return LeoTrainer.settings.deconstruct.maxQuality[craftSkill] end,
+            setFunc = function(value) LeoTrainer.settings.deconstruct.maxQuality[craftSkill] = value end,
+            default = LeoTrainer.settingsDefaults.deconstruct.maxQuality[craftSkill],
+            disabled = function() return not LeoTrainer.settings.deconstruct.auto end,
+        });
+    end
+
+
     local optionsData = {
         {
             type = "header",
             name = "|c3f7fff"..GetString(SI_GAMEPAD_OPTIONS_MENU).."|r"
-        },{
+        },
+        {
             type = "checkbox",
             name = zo_strformat(GetString(SI_GAMEPAD_ALCHEMY_USE_REAGENT), GetString(SI_ITEMTRAITTYPE25)),
             default = false,
-            getFunc = function() return LeoTrainer.savedVariables.trainNirnhoned end,
-            setFunc = function(value) LeoTrainer.savedVariables.trainNirnhoned = value end,
+            getFunc = function() return LeoTrainer.data.trainNirnhoned end,
+            setFunc = function(value) LeoTrainer.data.trainNirnhoned = value end,
+        },
+        LeoTrainer.settings:GetLibAddonMenuAccountCheckbox(),
+        {
+            type = "submenu",
+            name = GetString(SI_SMITHING_TAB_RESEARCH),
+            controls = {
+                {
+                    type = "description",
+                    text = "To avoid problems, auto research will ony work with marked items for research by FCOItemSaver. Also, only until max skill level. This addon will automatically mark items after crafts them."
+                },{
+                    type = "checkbox",
+                    name = "Research automatically when in station",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.research.auto end,
+                    setFunc = function(value) LeoTrainer.settings.research.auto = value end,
+                    disabled = function() return not FCOIS end,
+                },{
+                    type = "checkbox",
+                    name = "List items in the chat",
+                    default = true,
+                    getFunc = function() return LeoTrainer.settings.research.listInChat end,
+                    setFunc = function(value) LeoTrainer.settings.research.listInChat = value end,
+                },{
+                    type = "checkbox",
+                    name = "Allow crafted items",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.research.allowCrafted end,
+                    setFunc = function(value) LeoTrainer.settings.research.allowCrafted = value end,
+                    disabled = function() return not LeoTrainer.settings.research.auto end,
+                },{
+                    type = "checkbox",
+                    name = "Allow set items",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.research.allowSets end,
+                    setFunc = function(value) LeoTrainer.settings.research.allowSets = value end,
+                    disabled = function() return not LeoTrainer.settings.research.auto end,
+                },
+                unpack(researchMaxQualities)
+            }
         },{
-            type = "checkbox",
-            name = "Look for items in bags and bank",
-            default = false,
-            getFunc = function() return LeoTrainer.savedVariables.researchItems end,
-            setFunc = function(value) LeoTrainer.savedVariables.researchItems = value end,
+            type = "submenu",
+            name = GetString(SI_CRAFTING_PERFORM_FREE_CRAFT),
+            controls = {
+                {
+                    type = "checkbox",
+                    name = "Craft automatically when in station",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.craft.auto end,
+                    setFunc = function(value) LeoTrainer.settings.craft.auto = value end,
+                }
+            }
+        },{
+            type = "submenu",
+            name = GetString(SI_SMITHING_TAB_DECONSTRUCTION),
+            controls = {
+                {
+                    type = "description",
+                    text = "To avoid problems, auto deconstruct will ony work with marked items by FCOItemSaver and marked with deconstruction or inticate icons. Also, only until max skill level."
+                },{
+                    type = "checkbox",
+                    name = "Deconstruct automatically when in station",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.deconstruct.auto end,
+                    setFunc = function(value) LeoTrainer.settings.deconstruct.auto = value end,
+                    disabled = function() return not FCOIS end,
+                },{
+                    type = "checkbox",
+                    name = "List items in the chat",
+                    default = true,
+                    getFunc = function() return LeoTrainer.settings.deconstruct.listInChat end,
+                    setFunc = function(value) LeoTrainer.settings.deconstruct.listInChat = value end,
+                },{
+                    type = "checkbox",
+                    name = "Allow items in Bank",
+                    tooltip = "On: will scan backpack and bank. Off: Only backpack",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.deconstruct.allowBank end,
+                    setFunc = function(value) LeoTrainer.settings.deconstruct.allowBank = value end,
+                },{
+                    type = "checkbox",
+                    name = "Allow set items",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.deconstruct.allowSets end,
+                    setFunc = function(value) LeoTrainer.settings.deconstruct.allowSets = value end,
+                },
+                unpack(deconstructMaxQualities)
+            }
+        },{
+            type = "submenu",
+            name = GetString(SI_INTERACT_OPTION_BANK),
+            controls = {
+                {
+                    type = "checkbox",
+                    name = "Deposit crafted items automatically",
+                    default = false,
+                    getFunc = function() return LeoTrainer.settings.bank.autoDeposit end,
+                    setFunc = function(value) LeoTrainer.settings.bank.autoDeposit = value end,
+                }
+            }
         },{
-            type = "checkbox",
-            name = "Only marked with research by FCOItemSaver",
-            default = false,
-            getFunc = function() return LeoTrainer.savedVariables.onlyResearchFCO end,
-            setFunc = function(value) LeoTrainer.savedVariables.onlyResearchFCO = value end,
-        }, {
             type = "header",
             name = "|c3f7fffCharacters|r"
         },{
@@ -67,12 +230,24 @@ function LeoTrainer_Settings:CreatePanel()
             tooltip = "This character will be selected as the default trainer if knows the trait.",
             choices = charNames,
             default = "Anyone",
-            getFunc = function() return LeoTrainer.savedVariables.defaultTrainer end,
-            setFunc = function(value) LeoTrainer.savedVariables.defaultTrainer = value end
+            getFunc = function() return LeoTrainer.settings.defaultTrainer end,
+            setFunc = function(value) LeoTrainer.settings.defaultTrainer = value end
         },{
             type = "description",
             text = "Select which crafting skills will be available for each char and which ones will be used when filling empty research slots"
         },{
+            type = "button",
+            name = "Select all",
+            func = function() LeoTrainer_SettingsMenu:SelectAll() end,
+            warning = "Will need to reload the UI.",
+            width = "half",
+        },{
+            type = "button",
+            name = "Deselect all",
+            func = function() LeoTrainer_SettingsMenu:DeselectAll() end,
+            warning = "Will need to reload the UI.",
+            width = "half",
+        },{
             type = "custom",
             reference = OptionsName .. "Characters"
         }
@@ -80,7 +255,7 @@ function LeoTrainer_Settings:CreatePanel()
     LAM:RegisterOptionControls(OptionsName, optionsData)
 end

-function LeoTrainer_Settings:AddCharacters()
+function LeoTrainer_SettingsMenu:AddCharacters()
     if LeoTrainerOptionsCharactersSection then return end
     local control = CreateControlFromVirtual("$(parent)", LeoTrainerOptionsCharacters, "LeoTrainer_SettingsCharacters", "Section")
     self.container = control:GetNamedChild("Container")
@@ -90,7 +265,7 @@ function LeoTrainer_Settings:AddCharacters()
     end
 end

-function LeoTrainer_Settings_OnMouseEnter(control, tooltip)
+function LeoTrainer_SettingsMenu_OnMouseEnter(control, tooltip)
     InitializeTooltip(InformationTooltip, control, BOTTOMLEFT, 0, -2, TOPLEFT)
     SetTooltipText(InformationTooltip, tooltip)
 end
@@ -105,7 +280,7 @@ local function ToggleFill(checkbox, checked)
     LeoTrainer.setFillSlotWithSkill(control.data.charName, checkbox.data.craftId, checked)
 end

-function LeoTrainer_Settings:AddCharacter(id, char, last)
+function LeoTrainer_SettingsMenu:AddCharacter(id, char, last)
     local control = CreateControlFromVirtual("$(parent)", self.container, "LeoTrainer_SettingsCharacter", id)
     if last then
         control:SetAnchor(TOPLEFT, last, BOTTOMLEFT, 0, 0)
@@ -137,7 +312,7 @@ function LeoTrainer_Settings:AddCharacter(id, char, last)
     return control
 end

-function LeoTrainer_Settings:ClearCharacter(id)
+function LeoTrainer_SettingsMenu:ClearCharacter(id)
     if self.container then
         local control = self.container:GetNamedChild(id)
         if control then
@@ -146,14 +321,14 @@ function LeoTrainer_Settings:ClearCharacter(id)
     end
 end

-function LeoTrainer_Settings:OnSettingsControlsCreated(panel)
+function LeoTrainer_SettingsMenu:OnSettingsControlsCreated(panel)
     --Each time an options panel is created, once for each addon viewed
     if panel:GetName() == "LeoTrainerOptions" then
         self:AddCharacters()
     end
 end

-function LeoTrainer_Settings:IsCreated()
+function LeoTrainer_SettingsMenu:IsCreated()
     if self.container then
         return true
     else
diff --git a/Settings.xml b/Settings.xml
old mode 100644
new mode 100755
index a9cd806..6fea90e
--- a/Settings.xml
+++ b/Settings.xml
@@ -15,25 +15,25 @@
 						<Texture name="$(parent)ST_1" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_blacksmithing_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)" relativePoint="LEFT" offsetY="30"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_BLACKSMITHING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_BLACKSMITHING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)ST_2" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_clothing_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)ST_1" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_CLOTHIER)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_CLOTHIER)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)ST_6" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_woodworking_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)ST_2" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_WOODWORKING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_WOODWORKING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)ST_7" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_jewelrycrafting_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)ST_6" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_JEWELRYCRAFTING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_JEWELRYCRAFTING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>

@@ -44,25 +44,25 @@
 						<Texture name="$(parent)FS_1" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_blacksmithing_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)" relativePoint="LEFT" offsetX="190" offsetY="30"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_BLACKSMITHING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_BLACKSMITHING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)FS_2" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_clothing_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)FS_1" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_CLOTHIER)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_CLOTHIER)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)FS_6" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_woodworking_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)FS_2" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_WOODWORKING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_WOODWORKING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 						<Texture name="$(parent)FS_7" textureFile="esoui/art/inventory/inventory_tabicon_craftbag_jewelrycrafting_up.dds" mouseEnabled="true">
 							<Anchor point="LEFT" relativeTo="$(parent)FS_6" relativePoint="RIGHT" offsetX="-4"/>
 							<Dimensions x="36" y="36"/>
-							<OnMouseEnter>LeoTrainer_Settings_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_JEWELRYCRAFTING)))</OnMouseEnter>
+							<OnMouseEnter>LeoTrainer_SettingsMenu_OnMouseEnter(self, zo_strformat(SI_ABILITY_NAME, ZO_GetCraftingSkillName(CRAFTING_TYPE_JEWELRYCRAFTING)))</OnMouseEnter>
 							<OnMouseExit>ZO_Options_OnMouseExit(self)</OnMouseExit>
 						</Texture>
 					</Controls>
diff --git a/Ui.lua b/Ui.lua
new file mode 100755
index 0000000..b1b26a7
--- /dev/null
+++ b/Ui.lua
@@ -0,0 +1,694 @@
+
+LeoTrainer.ui.hidden = true
+
+local function addLine(tooltip, text, color, alignment)
+    if not color then color = ZO_TOOLTIP_DEFAULT_COLOR end
+    local r, g, b = color:UnpackRGB()
+    tooltip:AddLine(text, "LeoTrainerNormalFont", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, alignment, alignment ~= TEXT_ALIGN_LEFT)
+end
+
+local function addLineTitle(tooltip, text, color)
+    if not color then color = ZO_SELECTED_TEXT end
+    local r, g, b = color:UnpackRGB()
+    tooltip:AddLine(text, "ZoFontHeader3", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, TEXT_ALIGN_CENTER, true)
+end
+
+local function addLineSubTitle(tooltip, text, color, alignment)
+    if not color then color = ZO_SELECTED_TEXT end
+    if not alignment then alignment = TEXT_ALIGN_CENTER end
+    local r, g, b = color:UnpackRGB()
+    tooltip:AddLine(text, "ZoFontWinH3", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, alignment, true)
+end
+
+function LeoTrainer.ui:OnWindowMoveStop()
+    LeoTrainer.data.position = {
+        left = LeoTrainerWindow:GetLeft(),
+        top = LeoTrainerWindow:GetTop()
+    }
+end
+
+function LeoTrainer.ui:OnHide(control, hidden)
+    if hidden then LeoTrainer.ui.HideUI() end
+end
+
+function LeoTrainer.ui:OnShow(control, hidden)
+    if not hidden then LeoTrainer.ui.ShowUI() end
+end
+
+function LeoTrainer.ui:isHidden()
+    return LeoTrainer.ui.hidden
+end
+
+function LeoTrainer.ui.RestorePosition()
+    local position = LeoTrainer.data.position or { left = 200; top = 200; }
+    local left = position.left
+    local top = position.top
+
+    LeoTrainerWindow:ClearAnchors()
+    LeoTrainerWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
+    LeoTrainerWindow:SetDrawTier(DT_MEDIUM)
+end
+
+function LeoTrainer.ui.CloseUI()
+    SCENE_MANAGER:HideTopLevel(LeoTrainerWindow)
+end
+
+function LeoTrainer.ui.ShowUI()
+    LeoTrainer.ui.UpdateUI()
+    LeoTrainer.hidden = false;
+end
+
+function LeoTrainer.ui.HideUI()
+    LeoTrainer.hidden = true;
+end
+
+function LeoTrainer.ui.ToggleUI()
+    SCENE_MANAGER:ToggleTopLevel(LeoTrainerWindow)
+end
+
+function LeoTrainer.ui:OnMouseEnterTrait(control)
+    InitializeTooltip(ItemTooltip, control, LEFT, 5, 0)
+    ItemTooltip:SetLink(ZO_LinkHandler_CreateLink("",nil,ITEM_LINK_TYPE,control.materialItemID,30,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0))
+    ItemTooltip:SetHidden(false)
+end
+
+function LeoTrainer.ui.OnStationEnter(craftSkill)
+    LeoTrainer.ui.queueScroll:RefreshData()
+    LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_NORMAL)
+end
+
+function LeoTrainer.ui.OnStationExit(craftSkill)
+    LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_DISABLED)
+    LeoTrainer.ui.queueScroll:RefreshData()
+    LeoTrainer.ui.HideUI()
+    -- LeoTrainerStation:SetHidden(true)
+end
+
+function LeoTrainer.ui.Initialize()
+    local showButton, feedbackWindow = LibFeedback:initializeFeedbackWindow(LeoTrainer,
+        LeoTrainer.name,LeoTrainerWindow, "@LeandroSilva",
+        {TOPRIGHT, LeoTrainerWindow, TOPRIGHT,-50,3},
+        {0,1000,10000,"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y9KM4PZU2UZ6A"},
+        "If you found a bug, have a request or a suggestion, or simply wish to donate, send a mail.")
+    LeoTrainer.feedback = feedbackWindow
+    LeoTrainer.feedback:SetDrawTier(DT_MEDIUM)
+
+    LeoTrainerWindowTitle:SetText(LeoTrainer.displayName .. " v" .. LeoTrainer.version)
+
+    LeoTrainer.settingsMenu = LeoTrainer_SettingsMenu:New()
+    LeoTrainer.settingsMenu:CreatePanel()
+
+    LeoTrainer.launcher = LeoTrainer_Launcher:New()
+    LeoTrainer.launcher:SetHidden(false)
+
+    LeoTrainer.ui.RestorePosition()
+    LeoTrainer.ui.CreateUI()
+    LeoTrainer.ui.UpdateUI()
+end
+
+local function copy(obj)
+    if type(obj) ~= 'table' then return obj end
+    return ZO_ShallowTableCopy(obj)
+end
+
+LeoTrainerQueueList = ZO_SortFilterList:Subclass()
+function LeoTrainerQueueList:New(control)
+
+    ZO_SortFilterList.InitializeSortFilterList(self, control)
+
+    local sorterKeys =
+    {
+        ["trainer"] = {},
+        ["trainee"] = { tiebreaker = "trainer"},
+        ["researchName"] = { tiebreaker = "trainee"},
+        ["item"] = { tiebreaker = "researchName"},
+    }
+
+    self.masterList = {}
+    self.currentSortKey = "trainee"
+    self.currentSortOrder = ZO_SORT_ORDER_UP
+    ZO_ScrollList_AddDataType(self.list, 1, "LeoTrainerQueueListTemplate", 32, function(control, data) self:SetupEntry(control, data) end)
+
+    self.sortFunction = function(listEntry1, listEntry2)
+        return ZO_TableOrderingFunction(listEntry1.data, listEntry2.data, self.currentSortKey, sorterKeys, self.currentSortOrder)
+    end
+
+    return self
+end
+
+function LeoTrainerQueueList:SetupEntry(control, data)
+
+    control.data = data
+
+    control.trainer = GetControl(control, "Trainer")
+    control.trainer:SetText(data.trainer)
+    control.trainer.knownList = data.knownList
+    if data.knownList ~= nil and #data.knownList > 1 then
+        control.trainer:SetHandler('OnMouseEnter', function(self)
+            InitializeTooltip(InformationTooltip, self, LEFT, 5, 0)
+            addLineTitle(InformationTooltip, "Trainers", ZO_TOOLTIP_DEFAULT_COLOR)
+            ZO_Tooltip_AddDivider(InformationTooltip)
+
+            for _, knowName in pairs(data.knownList) do
+                addLine(InformationTooltip, knowName, LeoTrainer.const.colors.green)
+            end
+
+            addLine(InformationTooltip, zo_iconTextFormat("esoui/art/icons/icon_lmb.dds", 26, 26, "Change Trainer"))
+            InformationTooltip:SetHidden(false)
+        end)
+        control.trainer:SetHandler('OnMouseUp', function(control, button, upInside)
+            if not upInside or (button ~= MOUSE_BUTTON_INDEX_RIGHT and button ~= MOUSE_BUTTON_INDEX_LEFT) then return end
+            local newTrainer
+            for trainerIndex, trainer in pairs(data.knownList) do
+                if trainer == data.trainer then
+                    if trainerIndex < #data.knownList then
+                        newTrainer = data.knownList[trainerIndex + 1]
+                    else
+                        newTrainer = data.knownList[1]
+                    end
+                    break
+                end
+            end
+            LeoTrainer.data.craftQueue[data.queueIndex].trainer = newTrainer
+            LeoTrainer.ui.queueScroll:RefreshData()
+        end)
+    end
+
+    control.trainee = GetControl(control, "Trainee")
+    control.trainee:SetText(data.trainee)
+
+    control.researchName = GetControl(control, "Trait")
+    control.researchName:SetText(data.researchName)
+
+    control.item = GetControl(control, "Item")
+    control.item:SetText(data.itemLink)
+    control.item:SetHandler('OnMouseUp', function(control, button, upInside)
+        if upInside == false then return end
+        if button == MOUSE_BUTTON_INDEX_RIGHT then
+            LeoTrainer.RemoveFromQueue(data.queueIndex)
+        end
+    end)
+
+    ZO_SortFilterList.SetupRow(self, control, data)
+end
+
+function LeoTrainerQueueList:BuildMasterList()
+    self.masterList = {}
+    local list = LeoTrainer.GetCraftQueue()
+    if list then
+        for k, v in ipairs(list) do
+            local data = copy(v)
+            data.queueIndex = k
+            table.insert(self.masterList, data)
+        end
+    end
+end
+
+function LeoTrainerQueueList:SortScrollList()
+    local scrollData = ZO_ScrollList_GetDataList(self.list)
+    table.sort(scrollData, self.sortFunction)
+end
+
+function LeoTrainerQueueList:FilterScrollList()
+
+    local scrollData = ZO_ScrollList_GetDataList(self.list)
+    ZO_ClearNumericallyIndexedTable(scrollData)
+
+    local station = GetCraftingInteractionType()
+
+    for i = 1, #self.masterList do
+        local data = self.masterList[i]
+        local canShow = true
+        if canShow == true and station > 0 and data.craft ~= station then
+            canShow = false
+        end
+        if station > 0 and data.trainer ~= "Anyone" and data.trainer ~= LeoAltholic.CharName then
+            canShow = false
+        end
+
+        if data.crafted then canShow = false end
+
+        if canShow then
+            table.insert(scrollData, ZO_ScrollList_CreateDataEntry(1, data))
+        end
+    end
+end
+
+local function getTraitResearchData(research, craft, line, trait)
+    local isKnown = research.done[craft][line][trait] or false
+    local isResearching = false
+    local doneAt
+    if isKnown == false then
+        for _, researching in pairs(research.doing[craft]) do
+            if researching.line == line and researching.trait == trait then
+                doneAt = researching.doneAt
+                isResearching = true
+                break
+            end
+        end
+    end
+    return isKnown, isResearching, doneAt
+end
+
+local function isLineBeingResearched(research, craft, line)
+    for _, researching in pairs(research.doing[craft]) do
+        if researching.line == line then
+            if researching.doneAt and researching.doneAt - GetTimeStamp() > 0 then
+                return true
+            end
+        end
+    end
+    return false
+end
+
+local function getNumOngoingResearches(research, craft)
+    local num = 0
+    for _, researching in pairs(research.doing[craft]) do
+        if researching.doneAt - GetTimeStamp() > 0 then
+            num = num + 1
+        end
+    end
+    return num
+end
+
+local function getFirstUnknownTraitCanBeTrained(craft, line, unknownTraits, trainer)
+    for _, trait in pairs(unknownTraits) do
+
+        if trainer == nil and #LeoTrainer.knowledge[craft][line][trait] > 0 then
+            return trait, LeoTrainer.knowledge[craft][line][trait]
+        elseif trainer ~= nil then
+            for _, charName in pairs(LeoTrainer.knowledge[craft][line][trait]) do
+                if charName == trainer then
+                    return trait, LeoTrainer.knowledge[craft][line][trait]
+                end
+            end
+        end
+    end
+    return nil, {}
+end
+
+function LeoTrainer.ui.CreateUI()
+    local traitIcons = {}
+    for traitItemIndex = 1, GetNumSmithingTraitItems() do
+        local traitType, _, icon, _, _, _, _ = GetSmithingTraitItemInfo(traitItemIndex)
+        if traitType and traitType ~= ITEM_TRAIT_TYPE_NONE then
+            traitIcons[traitType] = icon
+        end
+    end
+
+    for _,craft in pairs(LeoAltholic.craftResearch) do
+        local panel = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft'..craft.."Panel")
+        if craft == CRAFTING_TYPE_JEWELRYCRAFTING then
+            panel = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft6PanelCraft7Panel')
+        end
+        for line = 1, GetNumSmithingResearchLines(craft) do
+            local lineName, lineIcon, numTraits = GetSmithingResearchLineInfo(craft, line)
+            local labelLine = panel:GetNamedChild('Line' .. line)
+            labelLine.tooltip = lineName
+            labelLine:SetText("|t30:30:"..lineIcon.."|t")
+            for trait = 1, numTraits do
+                local traitType = GetSmithingResearchLineTraitInfo(craft, line, trait)
+                local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
+                local i = trait
+                local posY = 14 + (trait * 28)
+                if craft == CRAFTING_TYPE_BLACKSMITHING and line <= 7 then
+                    i = i + 10
+                elseif craft == CRAFTING_TYPE_WOODWORKING and line <= 5 then
+                    i = i + 10
+                end
+                local labelTrait = panel:GetNamedChild('Trait' .. i)
+                labelTrait:SetText(traitName .. " |t28:28:"..traitIcons[traitType].."|t")
+                labelTrait.materialItemID = LeoTrainer.const.traitMaterials[traitType]
+
+                local t = WINDOW_MANAGER:CreateControl('LeoTrainerWindowCraft'..craft..'Line'..line..'Trait'..trait..'Texture', labelLine, CT_TEXTURE)
+                t:SetAnchor(CENTER, labelLine, CENTER, 0, posY)
+                t:SetDimensions(25,25)
+                t:SetMouseEnabled(true)
+                t:SetHandler('OnMouseExit', function(self)
+                    ClearTooltip(InformationTooltip)
+                    InformationTooltip:SetHidden(true)
+                end)
+
+            end
+
+            local label = WINDOW_MANAGER:CreateControl('LeoTrainerWindowCraft'..craft..'Line'..line..'Count', labelLine, CT_LABEL)
+            label:SetAnchor(CENTER, labelLine, CENTER, 8, 300)
+            label:SetDimensions(25,25)
+            label:SetFont("LeoTrainerLargeFont")
+        end
+    end
+    LeoTrainer.ui.queueScroll = LeoTrainerQueueList:New(LeoTrainerWindowQueuePanelQueueScroll)
+    LeoTrainer.ui.queueScroll:RefreshData()
+
+    local LeoTrainerCharDropdown = CreateControlFromVirtual('LeoTrainerCharDropdown', LeoTrainerWindow, 'LeoTrainerCharDropdown')
+    LeoTrainerCharDropdown:SetDimensions(200,35)
+    LeoTrainerCharDropdown:SetAnchor(RIGHT, LeoTrainerWindowBlacksmithingButton, LEFT, -50, 4)
+    LeoTrainerCharDropdown.m_comboBox:SetSortsItems(false)
+    local charDropdown = ZO_ComboBox_ObjectFromContainer(LeoTrainerCharDropdown)
+    charDropdown:ClearItems()
+
+    local defaultItem
+    for _, char in pairs(LeoAltholic.ExportCharacters()) do
+        local entry = charDropdown:CreateItemEntry(char.bio.name, function()
+            LeoTrainer.ui.UpdateUI(char.bio.name)
+        end)
+        if char.bio.name == LeoAltholic.CharName then
+            defaultItem = entry
+        end
+        charDropdown:AddItem(entry)
+    end
+    if defaultItem ~= nil then
+        charDropdown:SelectItem(defaultItem)
+    end
+end
+
+function LeoTrainer.ui.UpdateUI(charName)
+
+    if charName == nil then charName = LeoAltholic.CharName end
+
+    local items = {} -- TODO LeoTrainer.ScanBags()
+    local traitIcons = {}
+    for traitItemIndex = 1, GetNumSmithingTraitItems() do
+        local traitType, _, icon, _, _, _, _ = GetSmithingTraitItemInfo(traitItemIndex)
+        if traitType and traitType ~= ITEM_TRAIT_TYPE_NONE then
+            traitIcons[traitType] = icon
+        end
+    end
+
+    for _,craft in pairs(LeoAltholic.craftResearch) do
+        local panel = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft'..craft.."Panel")
+        if craft == CRAFTING_TYPE_JEWELRYCRAFTING then
+            panel = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft6PanelCraft7Panel')
+        end
+        for line = 1, GetNumSmithingResearchLines(craft) do
+            local lineName, lineIcon, numTraits = GetSmithingResearchLineInfo(craft, line)
+            local knownTraits = 0
+            for trait = 1, numTraits do
+                local traitType = GetSmithingResearchLineTraitInfo(craft, line, trait)
+                local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
+
+                local t = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft'..craft..'Line'..line..'Trait'..trait..'Texture')
+
+                local isKnown = #LeoTrainer.knowledge[craft][line][trait] > 0
+                local isUnknown = #LeoTrainer.knowledge[craft][line][trait] == 0
+                local allKnown = #LeoTrainer.missingKnowledge[craft][line][trait] == 0
+
+                local hasItem = false
+                for _, itemData in pairs(items) do
+                    if itemData.craft == craft and itemData.line == line and itemData.trait == trait then
+                        hasItem = LeoTrainer.CanItemBeResearched(itemData.bagId, itemData.slotIndex, itemData.item)
+                        if hasItem then
+                            break
+                        end
+                    end
+                end
+
+                local myself = false
+                for _,knowName in pairs(LeoTrainer.knowledge[craft][line][trait]) do
+                    if knowName == charName then
+                        myself = true
+                        break
+                    end
+                end
+                local icon
+                local color
+                if myself == true then
+                    icon = 'esoui/art/buttons/accept_up.dds'
+                    knownTraits = knownTraits + 1
+                    if allKnown then
+                        color = {0,1,0,1}
+                    else
+                        color = {1,1,0,1}
+                    end
+                else
+                    icon = 'esoui/art/buttons/decline_up.dds'
+                    if isUnknown then
+                        color = {1,0,0,1}
+                    else
+                        color = {1,0.7,0,1}
+                    end
+                end
+                if hasItem and not allKnown then
+                    icon = 'esoui/art/buttons/pointsplus_up.dds'
+                end
+
+                t:SetColor(unpack(color))
+                t:SetTexture(icon)
+                t:SetHandler('OnMouseEnter', function(self)
+                    InitializeTooltip(InformationTooltip, self, LEFT, 5, 0)
+                    addLineTitle(InformationTooltip, lineName .." - ".. traitName, ZO_TOOLTIP_DEFAULT_COLOR)
+                    ZO_Tooltip_AddDivider(InformationTooltip)
+
+                    addLineSubTitle(InformationTooltip, "Trainers", ZO_TOOLTIP_DEFAULT_COLOR, TEXT_ALIGN_LEFT)
+                    if allKnown then
+                        addLine(InformationTooltip, "All", LeoTrainer.const.colors.green)
+                    elseif isKnown then
+                        for _, knowName in pairs(LeoTrainer.knowledge[craft][line][trait]) do
+                            addLine(InformationTooltip, knowName, LeoTrainer.const.colors.green)
+                        end
+                    else
+                        addLine(InformationTooltip, "None", LeoTrainer.const.colors.red)
+                    end
+
+                    addLineSubTitle(InformationTooltip, "Trainees", ZO_TOOLTIP_DEFAULT_COLOR, TEXT_ALIGN_LEFT)
+                    if allKnown then
+                        addLine(InformationTooltip, "None", LeoTrainer.const.colors.green)
+                    elseif isUnknown then
+                        addLine(InformationTooltip, "All", LeoTrainer.const.colors.red)
+                    else
+                        for _, knowName in pairs(LeoTrainer.missingKnowledge[craft][line][trait]) do
+                            addLine(InformationTooltip, knowName, LeoTrainer.const.colors.red)
+                        end
+                    end
+                    local inBag = ""
+                    local inBank = ""
+                    for _, itemData in pairs(items) do
+                        if itemData.craft == craft and itemData.line == line and itemData.trait == trait then
+                            if LeoTrainer.research.CanItemBeResearched(itemData.bagId, itemData.slotIndex, itemData.item) then
+                                if itemData.bagId == BAG_BANK or itemData.bagId == BAG_SUBSCRIBER_BANK then
+                                    inBank = inBank .."[".. itemData.item .. "] "
+                                elseif itemData.bagId == BAG_BACKPACK then
+                                    inBag = inBag .."["..  itemData.item .. "] "
+                                end
+                            end
+                        end
+                    end
+                    if inBag ~= "" or inBank ~= "" then
+                        addLineSubTitle(InformationTooltip, "Researchable Items", ZO_TOOLTIP_DEFAULT_COLOR, TEXT_ALIGN_LEFT)
+                    end
+                    if inBag ~= "" then
+                        addLine(InformationTooltip, GetString(SI_INVENTORY_MENU_INVENTORY) ..": ".. inBag, LeoTrainer.const.colors.green)
+                    end
+                    if inBank ~= "" then
+                        addLine(InformationTooltip, GetString(SI_CURRENCYLOCATION1) ..": ".. inBank, LeoTrainer.const.colors.green)
+                    end
+                    if not allKnown and not isUnknown then
+                        addLine(InformationTooltip, zo_iconTextFormat("esoui/art/icons/icon_lmb.dds", 26, 26, "Queue 1"))
+                        addLine(InformationTooltip, zo_iconTextFormat("esoui/art/icons/icon_rmb.dds", 26, 26, "Queue All"))
+                    end
+                    InformationTooltip:SetHidden(false)
+                end)
+                if isKnown then
+                    t:SetHandler('OnMouseUp', function(control, button, upInside)
+                        if not upInside or (button ~= MOUSE_BUTTON_INDEX_RIGHT and button ~= MOUSE_BUTTON_INDEX_LEFT) then return end
+                        if #LeoTrainer.missingKnowledge[craft][line][trait] > 0 then
+                            --local matReq = LeoTrainer.const.materialRequirements[craft][line]
+                            local styleId = LeoTrainer.craft.MaxStyle(line)
+                            if trait == 9 and LeoTrainer.data.trainNirnhoned == false then
+                                LeoTrainer.log("Nirnhoned training is disabled in settings.")
+                                return
+                            end
+
+                            local trainerName
+                            local _, knownList = getFirstUnknownTraitCanBeTrained(craft, line, {trait}, trainer)
+                            for _, knownName in pairs(knownList) do
+                                if knownName == LeoTrainer.settings.defaultTrainer then
+                                    trainerName = knownName
+                                    break
+                                end
+                            end
+                            if traitName == nil then
+                                trainerName = knownList[1]
+                            end
+
+                            for _, charName in pairs(LeoTrainer.missingKnowledge[craft][line][trait]) do
+                                local traineeName = "Anyone"
+                                if button == MOUSE_BUTTON_INDEX_RIGHT then
+                                    traineeName = charName
+                                end
+                                LeoTrainer.AddToQueue({
+                                    trainer = trainerName,
+                                    trainee = traineeName,
+                                    craft = craft,
+                                    line = line,
+                                    trait = trait,
+                                    patternIndex = -1,
+                                    materialIndex = 1,
+                                    materialQuantity = -1,
+                                    itemStyleId = styleId,
+                                    traitIndex = traitType,
+                                    useUniversalStyleItem = false,
+                                    researchName = lineName .. " " .. traitName,
+                                    itemLink = LeoTrainer.const.craftItems[craft][line][trait],
+                                    crafted = false
+                                })
+                                if button == MOUSE_BUTTON_INDEX_LEFT then
+                                    break
+                                end
+                            end
+                            LeoTrainer.ui.queueScroll:RefreshData()
+                        end
+                    end)
+                end
+            end
+            local labelCount = WINDOW_MANAGER:GetControlByName('LeoTrainerWindowCraft'..craft..'Line'..line..'Count')
+            labelCount:SetText(knownTraits)
+            if knownTraits < 2 then
+                labelCount:SetColor(1,0,0,1)
+            elseif knownTraits < 4 then
+                labelCount:SetColor(1,0.7,0,1)
+            elseif knownTraits < 6 then
+                labelCount:SetColor(1,1,0,1)
+            elseif knownTraits == 9 then
+                labelCount:SetColor(0,1,0,1)
+            else
+                labelCount:SetColor(1,1,1,1)
+            end
+        end
+    end
+    LeoTrainer.ui.queueScroll:RefreshData()
+end
+
+function LeoTrainer.GetCraftQueue()
+    return LeoTrainer.data.craftQueue or {}
+end
+
+function LeoTrainer.ClearQueue()
+    LeoTrainer.data.craftQueue = {}
+    LeoTrainer.LLC:cancelItem()
+    LeoTrainer.ui.queueScroll:RefreshData()
+end
+
+function LeoTrainer.AddToQueue(data)
+    for _, item in pairs(LeoTrainer.GetCraftQueue()) do
+        if data.trainer ~= "Anyone" and data.trainee ~= "Anyone" and item.trainer == data.trainer and item.trainee == data.trainee and item.craft == data.craft and
+                item.line == data.line and item.trait == data.trait then
+            return false
+        end
+    end
+    table.insert(LeoTrainer.GetCraftQueue(), data)
+    return true
+end
+
+function LeoTrainer.RemoveFromQueue(pos)
+    local data = LeoTrainer.GetCraftQueue()[pos]
+    table.remove(LeoTrainer.GetCraftQueue(), pos)
+    LeoTrainer.ui.queueScroll:RefreshData()
+    return data
+end
+
+function LeoTrainer.FillMySlots()
+    LeoTrainer.FillSlots(nil, LeoAltholic.CharName)
+end
+
+function LeoTrainer.FillKnownSlots()
+    LeoTrainer.FillSlots(LeoAltholic.CharName, nil)
+end
+
+function LeoTrainer.GetResearchPriority(charName, craftSkill)
+
+end
+
+local function get(tbl, k, ...)
+    if tbl == nil or tbl[k] == nil then return nil end
+    if select('#', ...) == 0 then return tbl[k] end
+    return get(tbl[k], ...)
+end
+
+local function set(tbl, k, maybeValue, ...)
+    if select('#', ...) == 0 then
+      -- this will throw if the top-level tbl is nil, which is the desired behavior
+      tbl[k] = maybeValue
+      return
+    end
+    if tbl[k] == nil then tbl[k] = {} end
+    set(tbl[k], maybeValue, ...)
+end
+
+function LeoTrainer.FillSlots(trainer, trainee)
+    local lineList = LeoTrainer.GetPriorityLineList()
+    local charList = LeoAltholic.ExportCharacters()
+    local items = LeoTrainer.research.ScanBags()
+
+    for _, char in pairs(charList) do
+        if (trainee == nil or trainee == char.bio.name) and trainer == nil or (trainer ~= nil and trainer ~= char.bio.name) then
+            for _, craft in pairs(LeoAltholic.craftResearch) do
+                if LeoTrainer.isTrackingSkill(char.bio.name, craft) and LeoTrainer.canFillSlotWithSkill(char.bio.name, craft) then
+                    local styleId
+                    local max = char.research.done[craft].max - getNumOngoingResearches(char.research, craft)
+                    for i = 1, max do
+                        for j, lineData in ipairs(lineList[char.bio.name][craft]) do
+                            if not lineData.added and not lineData.isResearching then
+                                local trait, knownList = getFirstUnknownTraitCanBeTrained(craft, lineData.line, lineData.unknownTraits, trainer)
+                                local hasItem = false
+                                if trait ~= nil and (trait ~= 9 or LeoTrainer.data.trainNirnhoned == true) then
+                                    for itemIndex, itemData in pairs(items) do
+                                        if itemData.selected == false and itemData.craftSkill == craft and itemData.line == lineData.line and itemData.trait == trait then
+                                            LeoTrainer.debug("Found item for research " .. itemData.itemLink)
+                                            hasItem = true
+                                            items[itemIndex].selected = true
+                                            break
+                                        end
+                                    end
+
+                                    if not hasItem then
+                                        local traitType = GetSmithingResearchLineTraitInfo(craft, lineData.line, trait)
+                                        local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
+                                        if not styleId then styleId = LeoTrainer.craft.MaxStyle(lineData.line) end
+                                        local trainerName
+                                        if trainer ~= nil then
+                                            trainerName = trainer
+                                        else
+                                            for _, knownName in pairs(knownList) do
+                                                if knownName == LeoTrainer.settings.defaultTrainer then
+                                                    trainerName = knownName
+                                                    break
+                                                end
+                                            end
+                                            if trainerName == nil then
+                                                trainerName = knownList[1]
+                                            end
+                                        end
+                                        local data = {
+                                            trainer = trainerName,
+                                            trainee = char.bio.name,
+                                            craft = craft,
+                                            line = lineData.line,
+                                            trait = trait,
+                                            patternIndex = -1,
+                                            materialIndex = 1,
+                                            materialQuantity = -1,
+                                            itemStyleId = styleId,
+                                            traitIndex = traitType,
+                                            useUniversalStyleItem = false,
+                                            researchName = lineData.lineName .. " " .. traitName,
+                                            itemLink = LeoTrainer.const.craftItems[craft][lineData.line][trait],
+                                            knownList = knownList,
+                                            crafted = false
+                                        }
+                                        if trainer ~= nil then data.trainer = trainer end
+                                        if trainee ~= nil then data.trainee = trainee end
+                                        LeoTrainer.AddToQueue(data)
+                                    end
+                                    lineList[char.bio.name][craft][j].added = true
+                                    break
+                                end
+                            end
+                        end
+                    end
+                    LeoTrainer.ui.queueScroll:RefreshData()
+                end
+            end
+        end
+    end
+end