New release

Leandro Silva [11-01-18 - 22:51]
New release
Filename
Bindings.xml
LeoTrainer.lua
LeoTrainer.txt
LeoTrainer.xml
LeoTrainerConst.lua
LeoTrainerUI.lua
Settings.lua
diff --git a/Bindings.xml b/Bindings.xml
index 8e39b76..80b216d 100644
--- a/Bindings.xml
+++ b/Bindings.xml
@@ -2,7 +2,7 @@
   <Layer name="SI_KEYBINDINGS_CATEGORY_GENERAL">
     <Category name="Leo's Trainer">
       <Action name="LEOTRAINER_TOGGLE_WINDOW">
-        <Down>LeoTrainer:ToggleUI()</Down>
+        <Down>LeoTrainerUI:ToggleUI()</Down>
       </Action>
       <Action name="LEOTRAINER_CRAFT_NEXT">
         <Down>LeoTrainer.CraftNext()</Down>
diff --git a/LeoTrainer.lua b/LeoTrainer.lua
index 34b195f..d8157f0 100644
--- a/LeoTrainer.lua
+++ b/LeoTrainer.lua
@@ -25,51 +25,6 @@ function LeoTrainer.maxStyle(piece)
     return maxStyleId
 end

-function LeoTrainer.GetCharKnowsTrait(craft, line, trait, charList)
-    local known = {}
-    local unknown = {}
-    local myself = false
-    local all = {}
-    if LeoAltholic.TodayReset == nil then
-        if charList == nil then charList = LeoAltholic.GetCharacters() end
-        for i, char in ipairs(charList) do
-            all[char.bio.name] = char.research[craft][line][trait] ~= false
-            if char.research[craft][line][trait] ~= false then
-                if char.bio.name == GetUnitName("player") then
-                    myself = true
-                end
-                table.insert(known, char.bio.name)
-            else
-                table.insert(unknown, char.bio.name)
-            end
-        end
-    else
-        if charList == nil then charList = LeoAltholic.ExportCharacters() end
-        for i, char in ipairs(charList) do
-            local knows = LeoAltholic.CharKnowsTrait(craft, line, trait, char.bio.name)
-            all[char.bio.name] = knows
-            if knows then
-                if char.bio.name == GetUnitName("player") then
-                    myself = true
-                end
-                table.insert(known, char.bio.name)
-            else
-                table.insert(unknown, char.bio.name)
-            end
-        end
-    end
-    return myself, known, unknown, all
-end
-
-function LeoTrainer.IKnowTrait(craft, line, trait)
-    if LeoAltholic.TodayReset ~= nil then
-        return LeoAltholic.CharKnowsTrait(craft, line, trait)
-    else
-        local myself = LeoAltholic.GetMyself()
-        return myself.research[craft][line][trait] == true
-    end
-end
-
 function LeoTrainer.GetPatternIndexes(craft)
     LeoTrainer.namesToPatternIndexes[craft] = {
         ["names"] = {},
@@ -87,22 +42,15 @@ function LeoTrainer.GetPatternIndexes(craft)
 end

 function LeoTrainer.OnCraftFailed(event, station)
-    --GetString("SI_TRADESKILLRESULT", result)
-    --d("FAILED " .. event)
 end

 function LeoTrainer.OnCraftComplete(event, station)

-    --local numItemsGained = GetNumLastCraftingResultItemsAndPenalty()
-    --local craftFailed = numItemsGained == 0
-    --d(craftFailed)
-
     if LeoTrainer.isCrafting == 0 then return end

     LeoTrainer.RemoveFromQueue(LeoTrainer.isCrafting)
     LeoTrainer.isCrafting = 0

-    -- Player still at station and pressed Craft All
     if GetCraftingInteractionType() ~= CRAFTING_TYPE_INVALID and LeoTrainer.continueCrating == true then
         zo_callLater(function() LeoTrainer.CraftNext() end, 200)
     end
@@ -155,7 +103,7 @@ end
 function LeoTrainer.CraftNext()
     local list = LeoTrainer.GetQueue()
     for index, data in ipairs(list) do
-        if data.craft == LeoTrainer.inStation and LeoTrainer.IKnowTrait(data.craft, data.line, data.trait) == true then
+        if data.craft == LeoTrainer.inStation and LeoAltholic.CharKnowsTrait(data.craft, data.line, data.trait) == true then
             LeoTrainer.CraftItem(index, data)
             return
         end
@@ -171,7 +119,6 @@ function LeoTrainer.stationEnter(eventcode, station)

     LeoTrainer.inStation = station
     LeoTrainer.queueScroll:RefreshData()
-    LeoTrainerWindowQueuePanelQueueScrollCraftNext:SetState(BSTATE_NORMAL)
     LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_NORMAL)
     LeoTrainer.GetPatternIndexes(station)

@@ -180,38 +127,16 @@ function LeoTrainer.stationEnter(eventcode, station)
         local _, name = GetSmithingPatternInfo(patternIndex)
         namesToPatternIndexes[name] = patternIndex
     end
-
-    --[[for line = 1, GetNumSmithingResearchLines(station) do
-        local lineName, lineIcon, numTraits = GetSmithingResearchLineInfo(station, line)
-        local patternIndex = namesToPatternIndexes[lineName]
-        local _, _, matReq = GetSmithingPatternMaterialItemInfo(patternIndex, 1)
-        d(line.." "..lineName.." "..patternIndex.." "..matReq)
-        for trait = 1, numTraits do
-            local traitType = GetSmithingResearchLineTraitInfo(station, line, trait)
-            local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
-            --local styleId = maxStyle(lineId)
-            --local requestResult = {
-            --    patternIndex,
-            --    1,
-            --    matReq,
-            --    styleId,
-            --    traitType + 1,
-            --    LINK_STYLE_BRACKETS
-            --}
-            --d(GetSmithingPatternResultLink(unpack(requestResult)) .. "{line="..line..", patternIndex="..patternIndex..", materialIndex=1, materialQuantity="..matReq..", itemStyleId="..styleId..", trait="..trait..", traitType="..traitType.."} -- " .. lineName .. " " .. traitName)
-        end
-    end]]
 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

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

 function LeoTrainer.isTrackingSkill(charName, craftId)
@@ -242,7 +167,16 @@ function LeoTrainer.Initialize()
     if not LeoTrainer.savedVariables.fillSlot then
         LeoTrainer.savedVariables.fillSlot = {}
     end
-    for i, char in ipairs(LeoAltholic.GetCharacters()) do
+    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
+    for i, char in ipairs(LeoAltholic.ExportCharacters()) do
         if LeoTrainer.savedVariables.trackedTraits[char.bio.name] == nil then
             LeoTrainer.savedVariables.trackedTraits[char.bio.name] = {}
         end
@@ -266,7 +200,7 @@ function LeoTrainer.Initialize()
     LeoTrainerWindowTitle:SetText(LeoTrainer.displayName .. " v" .. LeoTrainer.version)

     SLASH_COMMANDS["/leotrainer"] = function(cmd)
-        LeoTrainer:ShowUI()
+        LeoTrainerUI:ShowUI()
     end

     if GetDisplayName() == "@LeandroSilva" then
@@ -275,11 +209,39 @@ function LeoTrainer.Initialize()
         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)
@@ -290,6 +252,16 @@ local function OnSettingsControlsCreated(panel)
     LeoTrainer_Settings:OnSettingsControlsCreated(panel)
 end

+local function onNewMovementInUIMode(eventCode)
+    if not LeoTrainerWindow:IsHidden() then LeoTrainerUI:CloseUI() end
+end
+
+local function onChampionPerksSceneStateChange(oldState,newState)
+    if newState == SCENE_SHOWING then
+        if not LeoTrainerWindow:IsHidden() then LeoTrainerUI:CloseUI() end
+    end
+end
+
 local function onLeoAltholicInitialized()
     CALLBACK_MANAGER:UnregisterCallback("LeoAltholicInitialized", onLeoAltholicInitialized)
     SCENE_MANAGER:RegisterTopLevel(LeoTrainerWindow, false)
@@ -301,6 +273,8 @@ local function onLeoAltholicInitialized()
     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)
+    EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_NEW_MOVEMENT_IN_UI_MODE, onNewMovementInUIMode)
+    CHAMPION_PERKS_SCENE:RegisterCallback('StateChange', onChampionPerksSceneStateChange)

     LeoTrainer.log("started.")
 end
diff --git a/LeoTrainer.txt b/LeoTrainer.txt
index 59a7c10..c9ce42e 100644
--- a/LeoTrainer.txt
+++ b/LeoTrainer.txt
@@ -1,6 +1,6 @@
 ## Title: Leo's Trainer
 ## APIVersion: 100024 100025
-## Version: 1.0.3
+## Version: 1.1.0
 ## Author: |c39B027@LeandroSilva|r
 ## SavedVariables: LeoTrainerSavedVariables
 ## DependsOn: LeoAltholic
diff --git a/LeoTrainer.xml b/LeoTrainer.xml
index f68a3f4..9f3c732 100644
--- a/LeoTrainer.xml
+++ b/LeoTrainer.xml
@@ -1,12 +1,15 @@
 <GuiXml>
+    <Font name="LeoTrainerLargeFont" font="$(MEDIUM_FONT)|18|soft-shadow-thin"/>
     <Font name="LeoTrainerNormalFont" font="$(MEDIUM_FONT)|16|soft-shadow-thin"/>
     <Font name="LeoTrainerSmallFont" font="$(MEDIUM_FONT)|14|soft-shadow-thin"/>
     <Controls>

         <TopLevelControl name="LeoTrainerWindow" mouseEnabled="true" movable="true" hidden="true" clampedToScreen="true">
-            <Dimensions x="850" y="810" />
+            <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>
             <Controls>
                 <Backdrop name="$(parent)BG" centerColor="000000" edgeColor="222222">
                     <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)"/>
@@ -21,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>LeoTrainer:HideUI()</OnClicked>
+                    <OnClicked>LeoTrainerUI:CloseUI()</OnClicked>
                     <Controls>
                         <Backdrop name="$(parent)BG" centerColor="101010" edgeColor="202020">
                             <AnchorFill/>
@@ -141,7 +144,7 @@
                 <!-- Blacksmithing = 1 -->
                 <Backdrop name="$(parent)Craft1Panel" tier="1" centerColor="000000" edgeColor="202020">
                     <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)" offsetX="0" offsetY="52"/>
-                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="370"/>
+                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="400"/>
                     <Edge edgeSize="1"/>
                     <Controls>
                         <Label name="$(parent)Trait11" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
@@ -345,7 +348,7 @@
                 <!-- Clothing = 1 -->
                 <Backdrop name="$(parent)Craft2Panel" hidden="true" tier="1" centerColor="000000" edgeColor="202020">
                     <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)" offsetX="0" offsetY="52"/>
-                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="370"/>
+                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="400"/>
                     <Edge edgeSize="1"/>
                     <Controls>
                         <Label name="$(parent)Trait1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="RIGHT">
@@ -494,7 +497,7 @@
                 <!-- Woodworking = 6 and Jewel crafting = 7 -->
                 <Backdrop name="$(parent)Craft6Panel" hidden="true" tier="1" centerColor="000000" edgeColor="202020">
                     <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeTo="$(parent)" offsetX="0" offsetY="52"/>
-                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="370"/>
+                    <Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT" relativeTo="$(parent)" offsetX="0" offsetY="400"/>
                     <Edge edgeSize="1"/>
                     <Controls>
                         <Label name="$(parent)Line1" mouseEnabled="true" font="LeoTrainerNormalFont" color="E8DFAF" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
@@ -745,13 +748,13 @@
                             <Dimensions x="180" y="28"/>
                         </Label>

-                        <Texture name="$(parent)Icon3" color="5555FF" textureFile="esoui/art/buttons/pointsplus_up.dds">
+                        <Texture name="$(parent)Icon3" color="FFFFFFF" textureFile="esoui/art/buttons/pointsplus_up.dds">
                             <Dimensions y="25" x="25"/>
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Icon2Label" relativePoint="TOPRIGHT" offsetX="6"/>
                         </Texture>
-                        <Label name="$(parent)Icon3Label" text="Has item" font="LeoTrainerNormalFont" color="5555FF" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT">
+                        <Label name="$(parent)Icon3Label" text="Has item" font="LeoTrainerNormalFont" color="FFFFFF" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Icon3" relativePoint="TOPRIGHT" offsetX="6"/>
-                            <Dimensions x="80" y="28"/>
+                            <Dimensions x="60" y="28"/>
                         </Label>

                         <Texture name="$(parent)Icon4" color="FFAA00" textureFile="esoui/art/buttons/decline_up.dds">
@@ -767,7 +770,7 @@
                             <Dimensions y="25" x="25"/>
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Icon4Label" relativePoint="TOPRIGHT" offsetX="6"/>
                         </Texture>
-                        <Label name="$(parent)Icon5Label" text="Unknown for all" font="LeoTrainerNormalFont" color="FF0000" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT">
+                        <Label name="$(parent)Icon5Label" text="Unknown by all" font="LeoTrainerNormalFont" color="FF0000" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT">
                             <Anchor point="TOPLEFT" relativeTo="$(parent)Icon5" relativePoint="TOPRIGHT" offsetX="6"/>
                             <Dimensions x="100" y="28"/>
                         </Label>
@@ -819,49 +822,47 @@
                                     <Dimensions x="800" y="300" />
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)Headers" relativePoint="BOTTOMLEFT" offsetY="20" />
                                 </Control>
-                                <Button name="$(parent)Mine" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Show Known">
-                                    <Dimensions x="150" y="30" />
+                                <Button name="$(parent)FillSlots" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Fill all slots">
+                                    <Dimensions x="160" y="30" />
                                     <Anchor point="TOPLEFT" relativeTo="$(parent)List" relativePoint="BOTTOMLEFT" offsetX="-8" offsetY="10"/>
                                     <OnClicked>
-                                        if LeoTrainer.filterKnown == true then
-                                            LeoTrainer.filterKnown = false
-                                            self:SetText("Show Known")
-                                        else
-                                            LeoTrainer.filterKnown = true
-                                            self:SetText("Show All")
-                                        end
-                                        LeoTrainer.queueScroll:RefreshData()
+                                        LeoTrainer.FillSlots()
                                     </OnClicked>
+                                    <OnMouseEnter>ZO_Tooltips_ShowTextTooltip(self, TOP, 'Fill all empty research slots for each character known by any other with the line/trait that will require less time')</OnMouseEnter>
+                                    <OnMouseExit>ZO_Tooltips_HideTextTooltip()</OnMouseExit>
                                 </Button>
-                                <Button name="$(parent)CraftNext" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Craft next">
-                                    <Dimensions x="150" y="30" />
-                                    <Anchor point="TOPLEFT" relativeTo="$(parent)Mine" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
-                                    <ButtonState state="DISABLED"/>
+                                <Button name="$(parent)FillMySlots" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Fill my slots">
+                                    <Dimensions x="160" y="30" />
+                                    <Anchor point="TOPLEFT" relativeTo="$(parent)FillSlots" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
                                     <OnClicked>
-                                        LeoTrainer.CraftNext()
+                                        LeoTrainer.FillMySlots()
                                     </OnClicked>
+                                    <OnMouseEnter>ZO_Tooltips_ShowTextTooltip(self, TOP, 'Fill all empty research slots for CURRENT character known by the any character with the line/trait that will require less time')</OnMouseEnter>
+                                    <OnMouseExit>ZO_Tooltips_HideTextTooltip()</OnMouseExit>
                                 </Button>
-                                <Button name="$(parent)CraftAll" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Craft all">
-                                    <Dimensions x="150" y="30" />
-                                    <Anchor point="TOPLEFT" relativeTo="$(parent)CraftNext" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
-                                    <ButtonState state="DISABLED"/>
+                                <Button name="$(parent)FillKnownSlots" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Fill slots I know">
+                                    <Dimensions x="160" y="30" />
+                                    <Anchor point="TOPLEFT" relativeTo="$(parent)FillMySlots" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
                                     <OnClicked>
-                                        LeoTrainer.continueCrating = true
-                                        LeoTrainer.CraftNext()
+                                        LeoTrainer.FillKnownSlots()
                                     </OnClicked>
+                                    <OnMouseEnter>ZO_Tooltips_ShowTextTooltip(self, TOP, 'Fill all empty research slots for each character known ONLY by the current character with the line/trait that will require less time')</OnMouseEnter>
+                                    <OnMouseExit>ZO_Tooltips_HideTextTooltip()</OnMouseExit>
                                 </Button>
-                                <Button name="$(parent)FillSlots" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Fill slots">
-                                    <Dimensions x="150" y="30" />
-                                    <Anchor point="TOPLEFT" relativeTo="$(parent)CraftAll" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
+                                <Button name="$(parent)Clear" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Clear Queue">
+                                    <Dimensions x="160" y="30" />
+                                    <Anchor point="TOPLEFT" relativeTo="$(parent)FillKnownSlots" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
                                     <OnClicked>
-                                        LeoTrainer.FillSlots()
+                                        LeoTrainer.ClearQueue()
                                     </OnClicked>
                                 </Button>
-                                <Button name="$(parent)Clear" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Clear Queue">
-                                    <Dimensions x="150" y="30" />
-                                    <Anchor point="TOPLEFT" relativeTo="$(parent)FillSlots" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
+                                <Button name="$(parent)CraftAll" inherits="ZO_DefaultButton" font="ZoFontWinH4" text="Start Craft">
+                                    <Dimensions x="160" y="30" />
+                                    <Anchor point="TOPLEFT" relativeTo="$(parent)Clear" relativePoint="TOPRIGHT" offsetX="0" offsetY="0"/>
+                                    <ButtonState state="DISABLED"/>
                                     <OnClicked>
-                                        LeoTrainer.ClearQueue()
+                                        LeoTrainer.continueCrating = true
+                                        LeoTrainer.CraftNext()
                                     </OnClicked>
                                 </Button>

@@ -869,7 +870,6 @@
                         </Control>
                     </Controls>
                 </Backdrop>
-
             </Controls>
         </TopLevelControl>

@@ -907,5 +907,12 @@
             </Controls>
         </Control>

+        <Control name="LeoTrainerCharDropdown" inherits="ZO_ComboBox" virtual="true">
+            <OnInitialized>
+                ZO_ComboBox:New(self)
+            </OnInitialized>
+        </Control>
+
+
     </Controls>
 </GuiXml>
diff --git a/LeoTrainerConst.lua b/LeoTrainerConst.lua
index 7368e95..c7fcfe0 100644
--- a/LeoTrainerConst.lua
+++ b/LeoTrainerConst.lua
@@ -1,8 +1,9 @@

 LeoTrainer = {}
+LeoTrainerUI = {}
 LeoTrainer.name = "LeoTrainer"
 LeoTrainer.displayName = "Leo's Trainer"
-LeoTrainer.version = "1.0.3"
+LeoTrainer.version = "1.1.0"
 LeoTrainer.chatPrefix = "|c39B027" .. LeoTrainer.name .. "|r: "
 LeoTrainer.setting = nil
 LeoTrainer.hidden = true
diff --git a/LeoTrainerUI.lua b/LeoTrainerUI.lua
index e1c5328..25ff838 100644
--- a/LeoTrainerUI.lua
+++ b/LeoTrainerUI.lua
@@ -1,23 +1,51 @@

-function LeoTrainer.ShowUI()
-    SCENE_MANAGER:ShowTopLevel(LeoTrainerWindow)
-    LeoTrainerWindow:SetHidden(false)
-    LeoTrainer.hidden = false;
+LeoTrainerUI.hidden = true
+
+function LeoTrainerUI:OnWindowMoveStop()
+    LeoTrainer.savedVariables.position = {
+        left = LeoTrainerWindow:GetLeft(),
+        top = LeoTrainerWindow:GetTop()
+    }
+end
+
+function LeoTrainerUI:OnHide(control, hidden)
+    if hidden then LeoTrainerUI.HideUI() end
+end
+
+function LeoTrainerUI:OnShow(control, hidden)
+    if not hidden then LeoTrainerUI.ShowUI() end
+end
+
+function LeoTrainerUI:isHidden()
+    return LeoTrainerUI.hidden
+end
+
+function LeoTrainerUI.RestorePosition()
+    local position = LeoTrainer.savedVariables.position or { left = 200; top = 200; }
+    local left = position.left
+    local top = position.top
+
+    LeoTrainerWindow:ClearAnchors()
+    LeoTrainerWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
+    LeoTrainerWindow:SetDrawLayer(DL_OVERLAY)
+    LeoTrainerWindow:SetDrawTier(DT_MEDIUM)
 end

-function LeoTrainer.HideUI()
+function LeoTrainerUI.CloseUI()
     SCENE_MANAGER:HideTopLevel(LeoTrainerWindow)
-    LeoTrainerWindow:SetHidden(true)
+end
+
+function LeoTrainerUI.ShowUI()
+    LeoTrainer.UpdateUI()
+    LeoTrainer.hidden = false;
+end
+
+function LeoTrainerUI.HideUI()
     LeoTrainer.hidden = true;
 end

-function LeoTrainer.ToggleUI()
+function LeoTrainerUI.ToggleUI()
     SCENE_MANAGER:ToggleTopLevel(LeoTrainerWindow)
-    if LeoTrainer.hidden then
-        LeoTrainer.ShowUI()
-    else
-        LeoTrainer.HideUI()
-    end
 end

 function LeoTrainer:OnMouseEnterTrait(control)
@@ -50,7 +78,8 @@ function LeoTrainerQueueList:New(control)
     }

     self.masterList = {}
-    self.currentSortKey = "researchName"
+    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)
@@ -110,9 +139,6 @@ function LeoTrainerQueueList:FilterScrollList()
     for i = 1, #self.masterList do
         local data = self.masterList[i]
         local canShow = true
-        if LeoTrainer.filterKnown == true and LeoTrainer.IKnowTrait(data.craft, data.line, data.trait) == false then
-            canShow = false
-        end
         if canShow == true and LeoTrainer.inStation > 0 and data.craft ~= LeoTrainer.inStation then
             canShow = false
         end
@@ -125,7 +151,7 @@ end
 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, "", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, alignment, alignment ~= TEXT_ALIGN_LEFT)
+    tooltip:AddLine(text, "LeoTrainerNormalFont", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, alignment, alignment ~= TEXT_ALIGN_LEFT)
 end

 local function addLineCenter(tooltip, text, color)
@@ -146,6 +172,88 @@ local function addLineSubTitle(tooltip, text, color, alignment)
     tooltip:AddLine(text, "ZoFontWinH3", r, g, b, CENTER, MODIFY_TEXT_TYPE_NONE, alignment, true)
 end

+local function getResearchData(link)
+    if not link then return false end
+
+    local craft, 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 craft = CRAFTING_TYPE_BLACKSMITHING; line = 1;
+    elseif weaponType == WEAPONTYPE_HAMMER then craft = CRAFTING_TYPE_BLACKSMITHING; line = 2;
+    elseif weaponType == WEAPONTYPE_SWORD then craft = CRAFTING_TYPE_BLACKSMITHING; line = 3
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_AXE then craft = CRAFTING_TYPE_BLACKSMITHING; line = 4;
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_HAMMER then craft = CRAFTING_TYPE_BLACKSMITHING; line = 5;
+    elseif weaponType == WEAPONTYPE_TWO_HANDED_SWORD then craft = CRAFTING_TYPE_BLACKSMITHING; line = 6;
+    elseif weaponType == WEAPONTYPE_DAGGER then craft = CRAFTING_TYPE_BLACKSMITHING; line = 7;
+    elseif weaponType == WEAPONTYPE_BOW then craft = CRAFTING_TYPE_WOODWORKING; line = 1;
+    elseif weaponType == WEAPONTYPE_FIRE_STAFF then craft = CRAFTING_TYPE_WOODWORKING; line = 2;
+    elseif weaponType == WEAPONTYPE_FROST_STAFF then craft = CRAFTING_TYPE_WOODWORKING; line = 3;
+    elseif weaponType == WEAPONTYPE_LIGHTNING_STAFF then craft = CRAFTING_TYPE_WOODWORKING; line = 4;
+    elseif weaponType == WEAPONTYPE_HEALING_STAFF then craft = CRAFTING_TYPE_WOODWORKING; line = 5;
+    elseif weaponType == WEAPONTYPE_SHIELD then craft = 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
+        craft = 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 craft = CRAFTING_TYPE_BLACKSMITHING; line = line + 7; trait = trait - 10; end
+        if armorType == ARMORTYPE_MEDIUM then craft = CRAFTING_TYPE_CLOTHIER; line = line + 7; trait = trait - 10; end
+        if armorType == ARMORTYPE_LIGHT then craft = CRAFTING_TYPE_CLOTHIER; trait = trait - 10; end
+    end
+    if craft and line and trait then return craft, line, trait
+    else return false end
+end
+
+local function scanItems(bag)
+    local list = {}
+    if not bag then bag = SHARED_INVENTORY:GenerateFullSlotData(nil,BAG_BACKPACK,BAG_BANK) end
+    for _, data in pairs(bag) do
+        local itemLink = GetItemLink(data.bagId,data.slotIndex)
+        local type = GetItemType(data.bagId,data.slotIndex)
+
+        if type == ITEMTYPE_ARMOR or type == ITEMTYPE_WEAPON then
+            local traitType, _ = GetItemLinkTraitInfo(itemLink)
+            local craft, line, trait = getResearchData(itemLink)
+            table.insert(list, {
+                bagId = data.bagId,
+                slot = data.slotIndex,
+                item = itemLink,
+                craft = craft,
+                line = line,
+                trait = trait
+            })
+        end
+    end
+    return list
+end
+
 function LeoTrainer.CreateUI()
     local traitIcons = {}
     for traitItemIndex = 1, GetNumSmithingTraitItems() do
@@ -182,29 +290,119 @@ function LeoTrainer.CreateUI()
                 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.queueScroll = LeoTrainerQueueList:New(LeoTrainerWindowQueuePanelQueueScroll)
+    LeoTrainer.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.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.UpdateUI(charName)

-                local myself, known, unknown, all = LeoTrainer.GetCharKnowsTrait(craft, line, trait)
+    if charName == nil then charName = LeoAltholic.CharName end
+
+    local items = {}
+    if LeoTrainer.savedVariables.researchItems then
+        items = scanItems()
+    end
+    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
+                        if not LeoTrainer.savedVariables.onlyResearchFCO or (FCOIS and FCOIS.IsIconEnabled(FCOIS_CON_ICON_RESEARCH) and FCOIS.IsMarked(itemData.bagId, itemData.slot, FCOIS_CON_ICON_RESEARCH)) then
+                            hasItem = true
+                            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'
-                    if #unknown == 0 then
+                    knownTraits = knownTraits + 1
+                    if allKnown then
                         color = {0,1,0,1}
                     else
                         color = {1,1,0,1}
-                        --icon = 'esoui/art/buttons/pointsplus_up.dds'
                     end
                 else
                     icon = 'esoui/art/buttons/decline_up.dds'
-                    if #known == 0 then
+                    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:SetMouseEnabled(true)
                 t:SetTexture(icon)
                 t:SetHandler('OnMouseEnter', function(self)
                     InitializeTooltip(InformationTooltip, self, LEFT, 5, 0)
@@ -212,43 +410,69 @@ function LeoTrainer.CreateUI()
                     ZO_Tooltip_AddDivider(InformationTooltip)

                     addLineSubTitle(InformationTooltip, "Trainers", ZO_TOOLTIP_DEFAULT_COLOR, TEXT_ALIGN_LEFT)
-                    if #known > 0 then
-                        for _, charName in pairs(known) do
-                            addLine(InformationTooltip, charName, LeoTrainer.const.colors.green)
+                    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 #unknown > 0 then
-                        for _, charName in pairs(unknown) do
-                            addLine(InformationTooltip, charName, LeoTrainer.const.colors.red)
-                        end
-                    else
+                    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 not LeoTrainer.savedVariables.onlyResearchFCO or (FCOIS and FCOIS.IsIconEnabled(FCOIS_CON_ICON_RESEARCH) and FCOIS.IsMarked(itemData.bagId, itemData.slot, FCOIS_CON_ICON_RESEARCH)) then
+                                if itemData.bagId == BAG_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 #known > 0 and #unknown > 0 then
+                    if not allKnown and not isUnknown then
                         text = "Queue for EACH trainee"
                         addLine(InformationTooltip, zo_iconTextFormat("esoui/art/icons/icon_lmb.dds", 26, 26, text))
                         --addLine(InformationTooltip, zo_iconTextFormat("esoui/art/icons/icon_rmb.dds", 26, 26, "Choose trainees"))
                     end
                     InformationTooltip:SetHidden(false)
                 end)
-                t:SetHandler('OnMouseExit', function(self)
-                    ClearTooltip(InformationTooltip)
-                    InformationTooltip:SetHidden(true)
-                end)
-                if #known > 0 and #unknown > 0 then
+                if isKnown then
                     t:SetHandler('OnMouseUp', function(control, button, upInside)
                         if not upInside then return end
                         if button == MOUSE_BUTTON_INDEX_RIGHT then
                             return
                         end
-                        if button == MOUSE_BUTTON_INDEX_LEFT and #unknown > 0 then
+                        if button == MOUSE_BUTTON_INDEX_LEFT and #LeoTrainer.missingKnowledge[craft][line][trait] > 0 then
                             --local matReq = LeoTrainer.const.materialRequirements[craft][line]
                             local styleId = LeoTrainer.maxStyle(line)
-                            for _, charName in pairs(unknown) do
+                            if trait == 9 and LeoTrainer.savedVariables.trainNirnhoned == false then
+                                LeoTrainer.log("Nirnhoned training is disabled in settings.")
+                                return
+                            end
+                            for _, charName in pairs(LeoTrainer.missingKnowledge[craft][line][trait]) do
                                 LeoTrainer.AddToQueue({
                                     trainer = "Anyone",
                                     trainee = charName,
@@ -270,9 +494,21 @@ function LeoTrainer.CreateUI()
                     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.queueScroll = LeoTrainerQueueList:New(LeoTrainerWindowQueuePanelQueueScroll)
     LeoTrainer.queueScroll:RefreshData()
 end

@@ -294,125 +530,120 @@ function LeoTrainer.RemoveFromQueue(pos)
     LeoTrainer.queueScroll:RefreshData()
 end

-local function getMaxCraft(char, craft)
-    if char.research.done ~= nil then
-        return char.research.done[craft].max
+local function getTraitData(research, craft, line, trait)
+    local traitData = research.done[craft][line][trait] or false
+    if traitData == false then
+        for _, researching in pairs(research.doing[craft]) do
+            if researching.line == line and researching.trait == trait then
+                return researching.doneAt
+            end
+        end
     end
-    return char.research[craft].max
+    return traitData
 end

-local function getTraitData(research, craft, line, trait)
-    local traitData
-    if research.doing ~= nil then
-        traitData = research.done[craft][line][trait] or false
-        if traitData == false then
-            for _, researching in pairs(research.doing[craft]) do
-                if researching.line == line and researching.trait == trait then
-                    return researching.time, research.done[craft].max
-                end
+local function getFirstUnknownTraitCanBeTrained(craft, line, unknownTraits, trainer)
+    if trainer == nil then
+        for _, trait in pairs(unknownTraits) do
+            if #LeoTrainer.knowledge[craft][line][trait] > 0 then
+                return trait, LeoTrainer.knowledge[craft][line][trait]
             end
         end
-        return traitData
-    else
-        traitData = research[craft][line][trait] or false
-        if type(traitData) == 'number' then
-            traitData = traitData - GetTimeStamp()
+        return nil, {}
+    end
+
+    for _, trait in pairs(unknownTraits) do
+        for _, charName in pairs(LeoTrainer.knowledge[craft][line][trait]) do
+            if charName == trainer then
+                return trait, LeoTrainer.knowledge[craft][line][trait]
+            end
         end
-        return traitData
     end
+    return nil, {}
+
+end
+
+function LeoTrainer.FillMySlots()
+    LeoTrainer.FillSlots(nil, LeoAltholic.CharName)
 end

-function LeoTrainer.FillSlots()
+function LeoTrainer.FillKnownSlots()
+    LeoTrainer.FillSlots(LeoAltholic.CharName, nil)
+end
+
+function LeoTrainer.FillSlots(trainer, trainee)
+    local charList = LeoAltholic.ExportCharacters()
+    local researchingLines = {}
     local knownCount = {}
-    local traitsKnown = {}
-    local charList
-    if LeoAltholic.TodayReset ~= nil then
-        charList = LeoAltholic.ExportCharacters()
-    else
-        charList = LeoAltholic.GetCharacters()
-    end
+    local unknownTraits = {}
     for _, char in pairs(charList) do
-        knownCount[char.bio.name] = {}
-        for _,craft in pairs(LeoAltholic.craftResearch) do
-            if LeoTrainer.isTrackingSkill(char.bio.name, craft) and LeoTrainer.canFillSlotWithSkill(char.bio.name, craft) then
-                local researching = 0
-                knownCount[char.bio.name][craft] = {}
-                if traitsKnown[craft] == nil then traitsKnown[craft] = {} end
-                local lower = {}
-                for line = 1, GetNumSmithingResearchLines(craft) do
-                    local lineName, _, numTraits = GetSmithingResearchLineInfo(craft, line)
-                    knownCount[char.bio.name][craft][line] = 0
-                    local firstUnknownTrait = {
-                        id = 0,
-                        name = ''
-                    }
-                    if traitsKnown[craft][line] == nil then traitsKnown[craft][line] = {} end
-                    for trait = 1, numTraits do
-                        local traitType = GetSmithingResearchLineTraitInfo(craft, line, trait)
-                        local traitData = getTraitData(char.research, craft, line, trait)
-                        local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
-
-                        if traitsKnown[craft][line][trait] == nil then
-                            local _, known, unknown, all = LeoTrainer.GetCharKnowsTrait(craft, line, trait, charList)
-                            traitsKnown[craft][line][trait] = known
-                        end
-                        if type(traitData) == 'number' and traitData > 0 then
-                            researching = researching + 1
-                        elseif (type(traitData) == 'number' and traitData <= 0) or traitData == true then
-                            knownCount[char.bio.name][craft][line] = knownCount[char.bio.name][craft][line] + 1
-                        elseif traitData == false and firstUnknownTrait.id == 0 then
-                            firstUnknownTrait.id = trait
-                            firstUnknownTrait.name = traitName
+        if (trainee == nil or trainee == char.bio.name) and trainer == nil or (trainer ~= nil and trainer ~= char.bio.name) then
+            knownCount[char.bio.name] = {}
+            unknownTraits[char.bio.name] = {}
+            researchingLines[char.bio.name] = {}
+            for _,craft in pairs(LeoAltholic.craftResearch) do
+                if LeoTrainer.isTrackingSkill(char.bio.name, craft) and LeoTrainer.canFillSlotWithSkill(char.bio.name, craft) then
+                    knownCount[char.bio.name][craft] = {}
+                    unknownTraits[char.bio.name][craft] = {}
+                    researchingLines[char.bio.name][craft] = {}
+                    local lineList = {}
+                    for line = 1, GetNumSmithingResearchLines(craft) do
+                        knownCount[char.bio.name][craft][line] = 0
+                        unknownTraits[char.bio.name][craft][line] = {}
+                        researchingLines[char.bio.name][craft][line] = false
+                        local lineName, _, numTraits = GetSmithingResearchLineInfo(craft, line)
+                        for trait = 1, numTraits do
+                            local traitData = getTraitData(char.research, craft, line, trait)
+                            if type(traitData) == 'number' and GetDiffBetweenTimeStamps(traitData, GetTimeStamp()) > 0 then
+                                researchingLines[char.bio.name][craft][line] = true
+                            elseif (type(traitData) == 'number' and GetDiffBetweenTimeStamps(traitData, GetTimeStamp()) <= 0) or traitData == true then
+                                knownCount[char.bio.name][craft][line] = knownCount[char.bio.name][craft][line] + 1
+                            elseif traitData == false then
+                                table.insert(unknownTraits[char.bio.name][craft][line], trait)
+                            end
                         end
-                    end
-                    if firstUnknownTrait.id > 0 and #lower < getMaxCraft(char, craft) then
-                        table.insert(lower, {
+                        table.insert(lineList, {
                             line = line,
                             lineName = lineName,
                             count = knownCount[char.bio.name][craft][line],
-                            trait = firstUnknownTrait.id,
-                            traitName = firstUnknownTrait.name
+                            unknownTraits = unknownTraits[char.bio.name][craft][line]
                         })
-                    elseif firstUnknownTrait.id > 0 then
-                        local changed = false
-                        for i = 1, #lower do
-                            if changed == false and lower[i].count > knownCount[char.bio.name][craft][line] then
-                                lower[i].line = line
-                                lower[i].lineName = lineName
-                                lower[i].count = knownCount[char.bio.name][craft][line]
-                                lower[i].trait = firstUnknownTrait.id
-                                lower[i].traitName = firstUnknownTrait.name
-                                changed = true
-                            end
-                        end
                     end
-                end
-                if #lower > 0 and researching < getMaxCraft(char, craft) then
-                    table.sort(lower, function(a, b)
+                    table.sort(lineList, function(a, b)
                         return a.count < b.count
                     end)
-                    local styleId = LeoTrainer.maxStyle(lower.line)
-                    local max = math.min(#lower, getMaxCraft(char, craft) - researching)
+                    local styleId
+                    local max = char.research.done[craft].max - #char.research.doing[craft]
                     for i = 1, max do
-                        if #traitsKnown[craft][lower[i].line][lower[i].trait] == 0 then
-                            LeoTrainer.log("No one knows "..lower[i].lineName .. " " .. lower[i].traitName.." for " ..char.bio.name.."'s training.")
-                        else
-                            local traitType = GetSmithingResearchLineTraitInfo(craft, lower[i].line, lower[i].trait)
-                            LeoTrainer.AddToQueue({
-                                trainer = "Anyone",
-                                trainee = char.bio.name,
-                                craft = craft,
-                                line = lower[i].line,
-                                trait = lower[i].trait,
-                                patternIndex = -1,
-                                materialIndex = 1,
-                                materialQuantity = -1,
-                                itemStyleId = styleId,
-                                traitIndex = traitType,
-                                useUniversalStyleItem = false,
-                                researchName = lower[i].lineName .. " " .. lower[i].traitName,
-                                itemLink = LeoTrainer.const.craftItems[craft][lower[i].line][lower[i].trait]
-                            })
+                        for j, lineData in ipairs(lineList) do
+                            if not lineData.added then
+                                local trait, knownList = getFirstUnknownTraitCanBeTrained(craft, lineData.line, lineData.unknownTraits, trainer)
+                                if trait ~= nil then
+                                    local traitType = GetSmithingResearchLineTraitInfo(craft, lineData.line, trait)
+                                    local traitName = GetString('SI_ITEMTRAITTYPE', traitType)
+                                    if not styleId then styleId = LeoTrainer.maxStyle(lineData.line) end
+                                    local data = {
+                                        trainer = "Anyone",
+                                        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]
+                                    }
+                                    if trainer ~= nil then data.trainer = trainer end
+                                    if trainee ~= nil then data.trainee = trainee end
+                                    LeoTrainer.AddToQueue(data)
+                                    lineList[j].added = true
+                                    break
+                                end
+                            end
                         end
                     end
                     LeoTrainer.queueScroll:RefreshData()
diff --git a/Settings.lua b/Settings.lua
index 3b64b68..591a3a0 100644
--- a/Settings.lua
+++ b/Settings.lua
@@ -32,6 +32,33 @@ function LeoTrainer_Settings:CreatePanel()
     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,
+        },{
+            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 = "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"
         },{
             type = "description",