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 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 end 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 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 local function splitLink(s) local result = {}; for match in (s..':'):gmatch("(.-)"..':') do table.insert(result, match); end return result; end function LeoTrainer.compareLinks(link1, link2) local table1 = splitLink(link1) local table2 = splitLink(link2) table1[19] = 1 -- reset crafted table2[19] = 1 -- reset crafted return table.concat(table1, ':') == table.concat(table2, ':') 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 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) LeoTrainer.isCrafting = 0 table.insert(craftedItems, GetLastCraftingResultItemLink(1)) 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..") ...") if IsPerformingCraftProcess() == true then LeoTrainer.log("Still crafting ...") return false end data.patternIndex = LeoTrainer.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.") LeoTrainer.continueCrating = false return false end data.itemStyleId = LeoTrainer.maxStyle(data.line) if data.itemStyleId == -1 then LeoTrainer.log("Not enough known style material.") LeoTrainer.continueCrating = false return false end local request = { data.patternIndex, data.materialIndex, data.materialQuantity, data.itemStyleId, data.traitIndex + 1, data.useUniversalStyleItem } LeoTrainer.isCrafting = queueIndex CraftSmithingItem(unpack(request)) return true 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 end end LeoTrainer.log("Nothing more to craft at this station.") LeoTrainer.isCrafting = 0 LeoTrainer.continueCrating = false markItems() 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 LeoTrainer.inStation = station LeoTrainer.queueScroll:RefreshData() LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_NORMAL) LeoTrainer.GetPatternIndexes(station) local namesToPatternIndexes = {} for patternIndex = 1, GetNumSmithingPatterns() do local _, name = GetSmithingPatternInfo(patternIndex) namesToPatternIndexes[name] = patternIndex 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 LeoTrainerWindowQueuePanelQueueScrollCraftAll:SetState(BSTATE_DISABLED) LeoTrainer.inStation = 0 LeoTrainer.queueScroll:RefreshData() LeoTrainerUI.HideUI() end function LeoTrainer.isTrackingSkill(charName, craftId) return LeoTrainer.savedVariables.trackedTraits[charName][craftId] end function LeoTrainer.setTrackingSkill(charName, craftId, tracking) LeoTrainer.savedVariables.trackedTraits[charName][craftId] = tracking end function LeoTrainer.canFillSlotWithSkill(charName, craftId) return LeoTrainer.savedVariables.fillSlot[charName][craftId] end function LeoTrainer.setFillSlotWithSkill(charName, craftId, tracking) LeoTrainer.savedVariables.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 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) LeoTrainerWindowTitle:SetText(LeoTrainer.displayName .. " v" .. LeoTrainer.version) SLASH_COMMANDS["/leotrainer"] = function(cmd) LeoTrainerUI:ToggleUI() end if GetDisplayName() == "@LeandroSilva" then SLASH_COMMANDS["/rr"] = function(cmd) 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) 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) LeoTrainer.Initialize() EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_CRAFTING_STATION_INTERACT, LeoTrainer.stationEnter) 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) EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_NEW_MOVEMENT_IN_UI_MODE, onNewMovementInUIMode) CHAMPION_PERKS_SCENE:RegisterCallback('StateChange', onChampionPerksSceneStateChange) LeoTrainer.log("started.") end function LeoTrainer.OnAddOnLoaded(event, addonName) if addonName == LeoTrainer.name then EVENT_MANAGER:UnregisterForEvent(LeoTrainer.name, EVENT_ADD_ON_LOADED) onLeoAltholicInitialized() end end CALLBACK_MANAGER:RegisterCallback("LeoAltholicInitialized", onLeoAltholicInitialized) --EVENT_MANAGER:RegisterForEvent(LeoTrainer.name, EVENT_ADD_ON_LOADED, LeoTrainer.OnAddOnLoaded)