-- $Revision: 212 $ -- Cauldron tradeskill functions local L = LibStub("AceLocale-3.0"):GetLocale("Cauldron") function Cauldron:GetTradeSkillName() local skillName = GetTradeSkillLine(); if not skillName then return nil; end CURRENT_TRADESKILL = skillName; if IsTradeSkillLinked() then skillName = "Linked-"..skillName; end if IsTradeSkillGuild() then skillName = "Guild-"..skillName; end return skillName, CURRENT_TRADESKILL; end function Cauldron:NeedsSkillUpdate() -- Cauldron:info("checking for skill update"); local skillName = Cauldron:GetTradeSkillName(); if not skillName then return false; end -- initialize the trade skill entry if not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName] then Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName] = {}; -- Cauldron:info("no skill entry; update needed"); return true; end -- initialize the reagent map if not Cauldron.db.realm.userdata[Cauldron.vars.playername].reagentMap then Cauldron.db.realm.userdata[Cauldron.vars.playername].reagentMap = {}; -- Cauldron:info("no reagent map; update needed"); return true; end -- save the skill entry in a local var local skillDB = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName]; if not skillDB.recipes then skillDB.recipes = {}; end local numTradeSkills = GetNumTradeSkills(); local name, rank, maxRank = GetTradeSkillLine(); if skillDB.rescan and skillDB.rescan.failedRecipes and (#skillDB.rescan.failedRecipes > 0) then return true; end if (tonumber(numTradeSkills) ~= tonumber(skillDB.actualSkillCount)) then return true; end if (tonumber(rank) ~= tonumber(skillDB.skillLevel)) then return true; end if ((time() - tonumber(skillDB.lastScanDate)) > 184000) then end return false; end function Cauldron:UpdateSkillItemCounts() local skillName, rank, maxRank = GetTradeSkillLine(); local baseSkillName = nil; skillName, baseSkillName = Cauldron:GetTradeSkillName(); if not skillName then return; end local skillDB = self.db.realm.userdata[self.vars.playername].skills[skillName]; if not skillDB then return; end for i=1,GetNumTradeSkills() do local name, difficulty, avail, expanded, verb, numSkillUps = GetTradeSkillInfo(i); if name and difficulty ~= "header" then local minMade, maxMade = GetTradeSkillNumMade(i); if skillDB.recipes[name] then -- update the recipe info skillDB.recipes[name].index = i; skillDB.recipes[name].difficulty = difficulty; skillDB.recipes[name].available = avail; skillDB.recipes[name].minMade = minMade; skillDB.recipes[name].maxMade = maxMade; skillDB.recipes[name].numSkillUps = numSkillUps; -- update reagent skill index for _,r in ipairs(skillDB.recipes[name].reagents) do r.skillIndex = i; end end end end end function Cauldron:InitializeSkillData() local skillName, rank, maxRank = GetTradeSkillLine(); local baseSkillName = nil; skillName, baseSkillname = Cauldron:GetTradeSkillName(); if not skillName then return; end -- initialize the trade skill entry if not self.db.realm.userdata[self.vars.playername].skills[skillName] then self.db.realm.userdata[self.vars.playername].skills[skillName] = {}; end -- initialize the reagent map if not self.db.realm.userdata[self.vars.playername].reagentMap then self.db.realm.userdata[self.vars.playername].reagentMap = {}; end -- save the skill entry in a local var local skillDB = self.db.realm.userdata[self.vars.playername].skills[skillName]; if not skillDB.recipes then skillDB.recipes = {}; end -- record skill stats skillDB.skillLevel = rank; skillDB.skillCount = numTradeSkills; skillDB.lastScanDate = time(); -- initialize window information, if necessary if not skillDB.window then skillDB.window = { search = "", filter = { optimal = true, medium = true, easy = true, trivial = true, haveAllReagents = false, haveKeyReagents = false, haveAnyReagents = false, sortDefault = true, sortDifficulty = false, sortAlpha = false, sortBenefit = false, sortItemLevel = false, sortRequiredLevel = false, sortFavorites = false, favorites = false, achievements = false, }, skills = {}, slots = {}, categories = {}, selected = 1, }; end end --[==[ function Cauldron:NewUpdateSkills() local skillName, rank, maxRank = GetTradeSkillLine(); local baseSkillName = nil; skillName, baseSkillName = Cauldron:GetTradeSkillName(); if not skillName then Cauldron:info("no skill name"); return; end -- local numTradeSkills = GetNumTradeSkills(); -- Cauldron.vars.numSkills = numTradeSkills; -- make sure we're getting a full list SetTradeSkillItemNameFilter(nil); SetTradeSkillItemLevelFilter(0, 0); TradeSkillOnlyShowSkillUps(false); TradeSkillOnlyShowMakeable(false); -- make sure the list is fully expanded for i=GetNumTradeSkills(),1,-1 do local name = GetTradeSkillInfo(i); if name == "header" then ExpandTradeSkillSubClass(i); end end local category = ""; local skillDB = self.db.realm.userdata[self.vars.playername].skills[skillName]; for i=1,GetNumTradeSkills() do local name, difficulty, avail, expanded, verb, numSkillUps = GetTradeSkillInfo(i); if name and difficulty ~= "header" then local minMade, maxMade = GetTradeSkillNumMade(i); -- add the recipe info and other miscellaneous info local itemLink = GetTradeSkillItemLink(i); local recipeLink = GetTradeSkillRecipeLink(i); local _, _, _, _, _, itemType, itemSubType, _, slot, _ = GetItemInfo(itemLink); local keywords = name; -- create the db entry local recipe = { ['index'] = i, ['name'] = name, ['description'] = GetTradeSkillDescription(i), ['itemLink'] = itemLink, ['recipeLink'] = recipeLink, ['icon'] = GetTradeSkillIcon(i), ['tradeskill'] = baseSkillName, ['difficulty'] = difficulty, ['available'] = avail, ['minMade'] = minMade, ['maxMade'] = maxMade, ['numSkillUps'] = numSkillUps, ['verb'] = verb, -- filter information ['slot'] = _G[slot], ['defaultCategory'] = category, ['type'] = itemType, ['subtype'] = itemSubType, ['reagents'] = {}, }; -- check for items from the original that need to be preserved if skillDB.recipes[name] then Cauldron:info("doing replacements: "..name); -- preserve reagent list, if present and "sane" if skillDB.recipes[name].reagents then if #skillDB.recipes[name].reagents > 0 then local copyReagents = true; for _,ri in ipairs(skillDB.recipes[name].reagents) do if not ri.name then copyReagents = false; break; end end if copyReagents then -- copy the reagents list over recipe.reagents = skillDB.recipes[name].reagents; else Cauldron:LearnSkillReagents(recipe); end else Cauldron:LearnSkillReagents(recipe); end end --[[ -- preserve the old keywords, if present if skillDB.recipes[name].keywords then -- fill in the keywords db entry recipe.keywords = skillDB.recipes[name].keywords; end --]] end skillDB.recipes[name] = recipe; else -- save the header name if name then category = name; -- expand the header, so we get all the skills if not expanded then ExpandTradeSkillSubClass(i); end else category = "Uncategorized"; end end end local endTime = GetTime(); if Cauldron.vars.displayTimers then Cauldron:info("scan time: "..tostring(endTime-startTime).."ms"); end local numSkills = table.getn(skillDB.recipes) Cauldron:info("numSkills="..tostring(numSkills)); Cauldron.vars.numSkills = numSkills; skillDB.skillCount = numSkills; skillDB.actualSkillCount = GetNumTradeSkills(); end --]==] function Cauldron:LearnSkillReagents(skillInfo) -- sanity if not skillInfo then Cauldron:error("Can't learn reagents; no skill information!"); return; end if skillInfo.tradeskill ~= CURRENT_TRADESKILL then Cauldron:error("Can't learn reagents; skill's trade doesn't match current!"); return; end local skillName = skillInfo.tradeskill; -- don't clobber the previous list if table.getn(skillInfo.reagents) > 0 then -- Cauldron:warn("Not replacing current list of reagents."); return; end -- Cauldron:info("learning reagents for: "..skillInfo.name); local keywords = skillInfo.keywords or ""; local reagents = {}; -- populate the reagent list local num = GetTradeSkillNumReagents(skillInfo.index); for j=1,num,1 do local rName, rIcon, rCount, playerAmount = GetTradeSkillReagentInfo(skillInfo.index, j); local rLink = GetTradeSkillReagentItemLink(skillInfo.index, j); local rItemId = Cauldron:GetIdFromLink(rLink); local key = not Cauldron:IsVendorItem(rItemId); if (not rName) or (not rIcon) or (not rLink) then --Cauldron:error("Failed to retrieve reagent info; marking recipe for rescan: "..skillInfo.name); --Cauldron:warn("i="..tostring(skillInfo.index).."; j="..tostring(j)); else local r = { ["index"] = j, ["name"] = rName, ["numRequired"] = rCount, ["skillIndex"] = skillInfo.index, ["icon"] = rIcon, ["link"] = rLink, ["key"] = key, ["amount"] = playerAmount, }; table.insert(reagents, r); -- add the reagent to the reagent map if not self.db.realm.userdata[self.vars.playername].reagentMap[rName] then self.db.realm.userdata[self.vars.playername].reagentMap[rName] = {}; end table.insert(self.db.realm.userdata[self.vars.playername].reagentMap[rName], skillName..";"..skillInfo.recipeLink); keywords = keywords..","..rName; end end -- if the learning process succeeded (total reagents in table matches count), then store them if #reagents == num then skillInfo.reagents = reagents; -- fill in the keywords db entry skillInfo.keywords = keywords; -- else -- Cauldron:warn("Error while learning reagents; discarding."); end end function Cauldron:UpdateSkills() if not self.updatingSkills then self:debug("not updating skills; return"); return; end local skillName, rank, maxRank = GetTradeSkillLine(); local baseSkillName; skillName, baseSkillName = Cauldron:GetTradeSkillName(); if not skillName then return; end local numTradeSkills = GetNumTradeSkills(); Cauldron.vars.numSkills = numTradeSkills; -- Cauldron:info("scanningSkills="..tostring(self.scanningSkills)); if not Cauldron.scanningSkills then local startTime = GetTime(); Cauldron.scanningSkills = true; -- Cauldron:Print("Scanning recipes..."); -- TODO: remove -- make sure we're getting a full list SetTradeSkillItemNameFilter(nil); SetTradeSkillItemLevelFilter(0, 0); TradeSkillOnlyShowSkillUps(false); TradeSkillOnlyShowMakeable(false); -- make sure the list is fully expanded for i=GetNumTradeSkills(),1,-1 do local name = GetTradeSkillInfo(i); if name == "header" then ExpandTradeSkillSubClass(i); end end --[[ -- initialize the trade skill entry if not self.db.realm.userdata[self.vars.playername].skills[skillName] then self.db.realm.userdata[self.vars.playername].skills[skillName] = {}; end -- initialize the reagent map if not self.db.realm.userdata[self.vars.playername].reagentMap then self.db.realm.userdata[self.vars.playername].reagentMap = {}; end --]] -- save the skill entry in a local var local skillDB = self.db.realm.userdata[self.vars.playername].skills[skillName]; if not skillDB.recipes then skillDB.recipes = {}; end -- record skill stats skillDB.skillLevel = rank; skillDB.skillCount = numTradeSkills; skillDB.lastScanDate = time(); local rescanNotify = false; -- initialize window information, if necessary if not skillDB.window then skillDB.window = { search = "", filter = { optimal = true, medium = true, easy = true, trivial = true, haveAllReagents = false, haveKeyReagents = false, haveAnyReagents = false, sortDefault = true, sortDifficulty = false, sortAlpha = false, sortBenefit = false, sortItemLevel = false, sortRequiredLevel = false, sortFavorites = false, favorites = false, achievements = false, }, skills = {}, slots = {}, categories = {}, selected = 1, }; end --[[ local slots = { GetTradeSkillSubClassFilteredSlots(0) }; for i,slot in pairs(slots) do SetTradeSkillInvSlotFilter(i, 0, 0); end local subClasses = { GetTradeSkillSubClasses() }; for i,subClass in pairs(subClasses) do SetTradeSkillSubClassFilter(i, 0, 0); end --]] local category = ""; -- local rescanCount = 0; for i=1,GetNumTradeSkills() do local name, difficulty, avail, expanded, verb, numSkillUps = GetTradeSkillInfo(i); if name and difficulty ~= "header" then local minMade, maxMade = GetTradeSkillNumMade(i); -- adjust min/max made for specialities -- TODO --[[ -- check if we're rescanning, updating or adding local rescan = false; if skillDB.rescan then if skillDB.rescan.failedRecipes[name] then rescan = true; end end if skillDB.recipes[name] and not rescan then -- update the recipe info skillDB.recipes[name].index = i; skillDB.recipes[name].difficulty = difficulty; skillDB.recipes[name].available = avail; skillDB.recipes[name].minMade = minMade; skillDB.recipes[name].maxMade = maxMade; skillDB.recipes[name].numSkillUps = numSkillUps; -- update reagent skill index for _,r in ipairs(skillDB.recipes[name].reagents) do r.skillIndex = i; end else --]] -- add the recipe info and other miscellaneous info local itemLink = GetTradeSkillItemLink(i); local recipeLink = GetTradeSkillRecipeLink(i); local _, _, _, _, _, itemType, itemSubType, _, slot, _ = GetItemInfo(itemLink); local keywords = name; --[[ if rescan then -- local msg = string.format(L["Rescanning recipe: %1$s..."], name); -- Cauldron:Print(msg); -- remove it from the list skillDB.rescan.failedRecipes[name] = nil; -- populate the reagent list local num = GetTradeSkillNumReagents(i); for j=1,num do local rName, rIcon, rCount, _ = GetTradeSkillReagentInfo(i, j); local rLink = GetTradeSkillReagentItemLink(i, j); local rItemId = Cauldron:GetIdFromLink(rLink); local key = not Cauldron:IsVendorItem(rItemId); if not skillDB.recipes[name].reagents[j].name then if (not rName) or (not rIcon) or (not rLink) then -- Cauldron:MarkRecipeForRescan(skillDB, name); -- rescanCount = rescanCount + 1; else local r = { ["index"] = j, ["name"] = rName, ["numRequired"] = rCount, ["skillIndex"] = i, ["icon"] = rIcon, ["link"] = rLink, ["key"] = key, }; skillDB.recipes[name].reagents[j] = r; if not self.db.realm.userdata[self.vars.playername].reagentMap[rName] then self.db.realm.userdata[self.vars.playername].reagentMap[rName] = {}; end table.insert(self.db.realm.userdata[self.vars.playername].reagentMap[rName], skillName..";"..recipeLink); skillDB.recipes[name].keywords = skillDB.recipes[name].keywords..","..rName; end end end else --]] -- create the db entry local recipe = { ['index'] = i, ['name'] = name, ['description'] = GetTradeSkillDescription(i), ['itemLink'] = itemLink, ['recipeLink'] = recipeLink, ['icon'] = GetTradeSkillIcon(i), ['tradeskill'] = baseSkillName, ['difficulty'] = difficulty, ['available'] = avail, ['minMade'] = minMade, ['maxMade'] = maxMade, ['numSkillUps'] = numSkillUps, ['verb'] = verb, -- filter information ['slot'] = _G[slot], ['defaultCategory'] = category, ['type'] = itemType, ['subtype'] = itemSubType, ['reagents'] = {}, }; -- check the reagents list to see if it should be copied if skillDB.recipes[name] and skillDB.recipes[name].reagents then if #skillDB.recipes[name].reagents > 0 then local copyReagents = true; for _,ri in ipairs(skillDB.recipes[name].reagents) do if not ri.name then copyReagents = false; break; end end if copyReagents then -- copy the reagents list over recipe.reagents = skillDB.recipes[name].reagents; end end end skillDB.recipes[name] = recipe; -- set the action verb for this skill -- skillDB.recipes[name].verb = verb; -- make sure the skill window info is initialized if not skillDB.window.skills[name] then skillDB.window.skills[name] = { ['expanded'] = false, ['favorite'] = false, }; end -- make sure the category for the window is initialized if category ~= "" then if not skillDB.window.categories[category] then skillDB.window.categories[category] = { ['shown'] = true, ['expanded'] = true, }; end end --[[ -- populate the slot list Cauldron:debug("slot: "..tostring(slot)); if slot and (slot ~= "") then skillDB.window.slots[slot] = { checked = true, }; else -- special slot representing items that don't have a slot skillDB.window.slots.none = { checked = true, }; end --]] -- populate the reagent list Cauldron:LearnSkillReagents(recipe); --[==[ local num = GetTradeSkillNumReagents(i); for j=1,num,1 do local rName, rIcon, rCount, playerAmount = GetTradeSkillReagentInfo(i, j); local rLink = GetTradeSkillReagentItemLink(i, j); local rItemId = Cauldron:GetIdFromLink(rLink); local key = not Cauldron:IsVendorItem(rItemId); if (not rName) or (not rIcon) or (not rLink) then rescanNotify = true; Cauldron:error("Failed to retrieve reagent info; marking recipe for rescan: "..name); Cauldron:warn("i="..tostring(i).."; j="..tostring(j)); --[[ -- store the info if it's not already from rescanning if not rescan then -- Cauldron:error("Failed to retrieve reagent info; marking recipe for rescan: "..name); -- Cauldron:MarkRecipeForRescan(skillDB, name); -- rescanCount = rescanCount + 1; end --]] else local r = { ["index"] = j, ["name"] = rName, ["numRequired"] = rCount, ["skillIndex"] = i, ["icon"] = rIcon, ["link"] = rLink, ["key"] = key, ["amount"] = playerAmount, }; table.insert(skillDB.recipes[name].reagents, r); -- add the reagent to the reagent map if rName then if not self.db.realm.userdata[self.vars.playername].reagentMap[rName] then self.db.realm.userdata[self.vars.playername].reagentMap[rName] = {}; end table.insert(self.db.realm.userdata[self.vars.playername].reagentMap[rName], skillName..";"..recipeLink); keywords = keywords..","..rName; end end end --]==] -- fill in the keywords db entry skillDB.recipes[name].keywords = keywords; -- end -- end else -- save the header name if name then category = name; -- expand the header, so we get all the skills if not expanded then ExpandTradeSkillSubClass(i); end else category = "Uncategorized"; end end end Cauldron.scanningSkills = false; local endTime = GetTime(); if Cauldron.vars.displayTimers then Cauldron:info("scan time: "..tostring(endTime-startTime).."ms"); end local numSkills = table.getn(skillDB.recipes) -- Cauldron:info("numSkills="..tostring(numSkills)); Cauldron.vars.numSkills = numSkills; skillDB.skillCount = numSkills; skillDB.actualSkillCount = GetNumTradeSkills(); --[[ if rescanCount > 0 then Cauldron:Print(rescanCount.." recipes marked for rescan."); end --]] end --[[ if rescanNotify then Cauldron:error(L["Cauldron had issues with some recipes for this profession."]); local msg = string.format(L["Please close and re-open the %1$s window again to re-scan."], baseSkillName); Cauldron:info(msg); end --]] self.updatingSkills = false; end function Cauldron:GetDefaultCategories(player, skillName) local categories = {}; if self.db then for name, info in pairs(self.db.realm.userdata[player].skills[skillName].window.categories) do categories[name] = info.shown; end end -- table.sort(categories); return categories; end --[[ function Cauldron:GetCategories(skillList) self:debug("GetCategories enter"); local categories = {}; if not skillList then return categories; end for _, info in ipairs(skillList) do table.insert(categories, info.defaultCategory); end table.sort(categories); self:debug("GetCategories exit"); return categories; end --]] function Cauldron:GetSlots(player, skillName) local slots = {}; if self.db then for name, info in pairs(self.db.realm.userdata[player].skills[skillName].window.slots) do slots[name] = info; end end -- table.sort(slots); return slots; end function Cauldron:GetSkillCount(skillName) if not skillName then skillName = CURRENT_TRADESKILL; end if not skillName then -- still couldn't get a skill name, so return 0 return 0; end local skillCount = 0; if (Cauldron.db.realm.userdata[Cauldron.vars.playername]) and (Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName]) then for _, _ in pairs(Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].recipes) do skillCount = skillCount + 1; end end return skillCount; end function Cauldron:GetSkillNumAvailable(skillInfo) if not skillInfo then return 0; end if skillInfo.tradeskill ~= CURRENT_TRADESKILL then return 0; end local _, _, avail, _, _, _ = GetTradeSkillInfo(skillInfo.index); return avail or 0; end function Cauldron:LearnSkill() end function Cauldron:GetSkillList(playername, skillName) if (not playername) or (not skillName) then self:warn("GetSkillList: playername ("..tostring(playername)..") or skillName ("..tostring(skillName)..") not set!"); return {}; end if (not self.db.realm.userdata[playername]) or (not self.db.realm.userdata[playername].skills[skillName]) then return {}; end local skills = {}; local startTime = GetTime(); for name, recipe in pairs(self.db.realm.userdata[playername].skills[skillName].recipes) do local add = true; local filter = self.db.realm.userdata[playername].skills[skillName].window.filter; -- check the search text local search = self.db.realm.userdata[playername].skills[skillName].window.search or ""; if #search > 0 then -- check for numbers local minLevel, maxLevel; -- local matchItemLevel = false; local approxLevel, matchItemLevel = strmatch(search, "^~(%d+)(i?)"); -- self:debug("GetSkillList: approxLevel="..tostring(approxLevel)); if approxLevel then minLevel = approxLevel - 2; maxLevel = approxLevel + 2; else minLevel, maxLevel, matchItemLevel = strmatch(search, "^(%d+)%s*-*%s*(%d*)(i?)$"); -- self:debug("GetSkillList: minLevel="..tostring(minLevel).."; maxLevel="..tostring(maxLevel)); end if minLevel then if maxLevel == "" or maxLevel == "i" or maxLevel < minLevel then maxLevel = minLevel; end -- cleanse the level values minLevel = tonumber(minLevel) or 0; maxLevel = tonumber(maxLevel) or 0; local _,_,_,itemLevel,reqLevel,_,_,_,_,_ = GetItemInfo(recipe.itemLink); if itemLevel and (matchItemLevel == "i") then itemLevel = tonumber(itemLevel) or 0; if itemLevel < minLevel or itemLevel > maxLevel then add = false; end elseif reqLevel then reqLevel = tonumber(reqLevel) or 0; if reqLevel < minLevel or reqLevel > maxLevel then add = false; end end else -- match name or reagents if not string.find(string.lower(recipe.keywords or ""), string.lower(search)) then add = false; end end end -- check difficulty filter if not filter[recipe.difficulty] then add = false; end --[[ -- check categories local categories = self.db.realm.userdata[playername].skills[skillName].window.categories; local catInfo = categories[recipe.defaultCategory] or categories[recipe.type] or categories[recipe.subtype]; if catInfo and (not catInfo.shown) then add = false; end -- check slot local slotName = recipe.slot; if (not slotName) or (slotName == "") then slotName = "none"; end local slotInfo = self.db.realm.userdata[playername].skills[skillName].window.slots[slotName]; self:debug("slotInfo: "..tostring(slotInfo)); if slotInfo and not(slotInfo.checked) then add = false; end --]] -- check reagent filter if filter.haveAllReagents then -- check if the available count is 0 if recipe.available == 0 then add = false; end elseif filter.haveKeyReagents then -- check if the reagent count for key reagents is 0 for _, rinfo in ipairs(recipe.reagents) do -- check possession count if (GetItemCount(rinfo.link, false) < rinfo.numRequired) and (rinfo.key) then add = false; end end elseif filter.haveAnyReagents then -- check if the reagent count for any reagent is > 0 add = false; for _, rinfo in ipairs(recipe.reagents) do -- check possession count if GetItemCount(rinfo.link, false) > 0 then add = true; end end end -- check favorites filter if filter.favorites then if not self.db.realm.userdata[playername].skills[skillName].window.skills[recipe.name].favorite then add = false; end end -- check achievements filter if filter.achievements then local achievements = Cauldron:GetAchievementsForSkill(recipe); if (not achievements) or (#achievements == 0) then add = false; end end -- we got here, add the recipe to the list if add then table.insert(skills, recipe); end end local endTime = GetTime(); if Cauldron.vars.displayTimers then Cauldron:info("get skill list: "..tostring(endTime-startTime).."ms"); end startTime = GetTime(); -- sort the list table.sort(skills, function(r1, r2) if (not r1) or (not r2) then return true; end if not r1.name or not r2.name then return true; end local filter = self.db.realm.userdata[playername].skills[skillName].window.filter; local recipe1 = self.db.realm.userdata[playername].skills[skillName].recipes[r1.name]; local recipe2 = self.db.realm.userdata[playername].skills[skillName].recipes[r2.name]; if filter.sortDefault then local r1v = recipe1.index; local r2v = recipe2.index; return r1v < r2v; elseif filter.sortAlpha then return r1.name < r2.name; elseif filter.sortDifficulty then local difficulty = { optimal = 4, medium = 3, easy = 2, trivial = 1, }; local r1v = recipe1.difficulty; local r2v = recipe2.difficulty; return difficulty[r1v] > difficulty[r2v]; elseif filter.sortItemLevel then -- get item info from item link local _,_,_,r1iLevel,_,_,_,_,_,_ = GetItemInfo(r1.itemLink); local _,_,_,r2iLevel,_,_,_,_,_,_ = GetItemInfo(r2.itemLink); return (r2iLevel or 0) < (r1iLevel or 0); elseif filter.sortRequiredLevel then -- get item info from item link local _,_,_,_,r1Level,_,_,_,_,_ = GetItemInfo(r1.itemLink); local _,_,_,_,r2Level,_,_,_,_,_ = GetItemInfo(r2.itemLink); return (r2Level or 0) < (r1Level or 0); elseif filter.sortFavorites then local r1f = (self.db.realm.userdata[playername].skills[skillName].window.skills[r1.name].favorite and 100) or 1; local r2f = (self.db.realm.userdata[playername].skills[skillName].window.skills[r2.name].favorite and 100) or 1; return r2f < r1f; elseif filter.sortBenefit then return true; -- TODO end return true; end); endTime = GetTime(); if Cauldron.vars.displayTimers then Cauldron:info("sort skill list: "..tostring(endTime-startTime).."ms"); end return skills; end function Cauldron:GetSkillInfo(tradeskill, skill) -- sanity checks if (not tradeskill) or (not skill) then self:warn("GetSkillInfo: missing tradeskill ("..tostring(tradeskill)..") or skill ("..tostring(skill)..")!"); return nil; end if not self.db.realm.userdata[self.vars.playername].skills[tradeskill] then return nil; end local skillInfo = self.db.realm.userdata[self.vars.playername].skills[tradeskill].recipes[skill]; if not skillInfo then -- couldn't find a skill with the item name, so scan the list for skills that craft -- the item for _, recipe in pairs(self.db.realm.userdata[self.vars.playername].skills[tradeskill].recipes) do local name, _ = GetItemInfo(recipe.itemLink); if name == skill then return recipe; end end end return skillInfo; end function Cauldron:GetSkillInfoForItem(item) if not item then Cauldron:error("GetSkillInfoForItem: item is nil!"); return nil; end for tradeskill, list in pairs(self.db.realm.userdata[self.vars.playername].skills) do -- skip linked skills if not (string.find(tradeskill, "Linked-")) and not (string.find(tradeskill, "Guild-")) then for _, recipeInfo in pairs(list.recipes) do local name, _ = GetItemInfo(recipeInfo.itemLink); if name == item then return recipeInfo; end end end end return nil; end function Cauldron:GetSkillInfoForLink(recipeLink) if not recipeLink then Cauldron:error("GetSkillInfoForLink: recipeLink is nil!"); return nil; end for tradeskill, list in pairs(self.db.realm.userdata[self.vars.playername].skills) do -- skip linked skills if not (string.find(tradeskill, "Linked-")) and not (string.find(tradeskill, "Guild-")) then for _, recipeInfo in pairs(list.recipes) do local id = Cauldron:GetIdFromLink(recipeLink); local recipeId = Cauldron:GetIdFromLink(recipeInfo.recipeLink); if id == recipeId then return recipeInfo; end end end end return nil; end function Cauldron:GetSkillInfoByIndex(itemIndex) if not itemIndex then Cauldron:error("GetSkillInfoByIndex: itemIndex is nil!"); return nil; end for tradeskill, list in pairs(self.db.realm.userdata[self.vars.playername].skills) do -- skip linked skills if not (string.find(tradeskill, "Linked-")) and not (string.find(tradeskill, "Guild-")) then for _, recipeInfo in pairs(list.recipes) do if recipeInfo.index == itemIndex then return recipeInfo; end end end end return nil; end function Cauldron:GetReagentInfoByIndex(item, reagentIndex) local skillInfo = nil; if type(item) == "table" then skillInfo = item; elseif type(item) == "number" then skillInfo = self:GetSkillInfoByIndex(tonumber(item)); end -- learn reagents Cauldron:LearnSkillReagents(skillInfo); if skillInfo then for i, reagentInfo in ipairs(skillInfo.reagents) do if reagentInfo.index == reagentIndex then return reagentInfo; end end end return nil; end function Cauldron:GetRequiredItems(skillInfo, amount) local intermediates = {}; local reagents = {}; -- sanity checks if not skillInfo then Cauldron:error("GetRequiredItems: no skillInfo provided!"); return intermediates, reagents; end -- get a proper amount value amount = math.max(1, tonumber(amount) or 1); -- learn reagents Cauldron:LearnSkillReagents(skillInfo); -- find out what the reagents are for i, reagent in ipairs(skillInfo.reagents) do -- copy the reagent info so we can modify the amounts local r = CopyTable(reagent); r.numRequired = r.numRequired * amount; -- see if the character can make the item local si = Cauldron:GetSkillInfoForItem(r.name); if si then table.insert(intermediates, r); else table.insert(reagents, r); end end return intermediates, reagents; end local function split(sep, str) local result = {}; while str do local s1, rest = strsplit(sep, str, 2); table.insert(result, s1); str = rest; end return result; end function Cauldron:GetSkillsForReagent(id) if not id then return {}; end local itemName,itemInfo,_ = GetItemInfo(id); local skillList = {}; if not Cauldron.db.realm.userdata[Cauldron.vars.playername].reagentMap then return {}; end -- find the reagent in the map local reagentMap = Cauldron.db.realm.userdata[Cauldron.vars.playername].reagentMap[itemName]; if reagentMap then for _,skill in ipairs(reagentMap) do table.insert(skillList, skill); end end return skillList; end