Quantcast

Made some changes to the skill scanning code to get closer to not having missing reagents.

Paul Schifferer [12-24-10 - 18:39]
Made some changes to the skill scanning code to get closer to not having missing reagents.
Re-enabled the achievement mapper.
Filename
CauldronMain.lua
CauldronMainUI.lua
CauldronQueue.lua
CauldronTradeskill.lua
CauldronUtil.lua
diff --git a/CauldronMain.lua b/CauldronMain.lua
index 368bd4f..55ca494 100644
--- a/CauldronMain.lua
+++ b/CauldronMain.lua
@@ -347,12 +347,16 @@ end
 function Cauldron:OnTradeShow()

 	TradeSkillFrame_Update(); -- seems to fix the early bailout of trade skill iterations
+
+	Cauldron:InitializeSkillData();

 	-- update our known skills
-	if not Cauldron.updatingSkills then
+--	if not Cauldron.updatingSkills then
 		Cauldron.updatingSkills = true; -- Cauldron:NeedsSkillUpdate();
 		Cauldron:UpdateSkills();
-	end
+--		Cauldron:NewUpdateSkills();
+-- Cauldron:info("on trade show: skills="..tostring(Cauldron:GetSkillCount()));
+--	end

 	-- register for events that are needed when the window is open
 	self:RegisterEvent("UPDATE_TRADESKILL_RECAST", "OnTradeSkillRecast");
@@ -411,7 +415,7 @@ function Cauldron:OnSkillUpdate(event)
 			self:Frame_Update();
 		end
 	end
-	--]]
+--]]
 end

 function Cauldron:OnTradeSkillRecast()
diff --git a/CauldronMainUI.lua b/CauldronMainUI.lua
index 51ca9b9..113a1d2 100644
--- a/CauldronMainUI.lua
+++ b/CauldronMainUI.lua
@@ -284,16 +284,10 @@ function Cauldron:UpdateSkillList()
 		return;
 	end

-	local skillName = CURRENT_TRADESKILL;
-	if skillName == "UNKNOWN" then
+	skillName = Cauldron:GetTradeSkillName(skillName);
+	if not skillName then
 		return;
 	end
-	if IsTradeSkillLinked() then
-		skillName = "Linked-"..skillName;
-	end
-	if IsTradeSkillGuild() then
-		skillName = "Guild-"..skillName;
-	end

 	local skillList = Cauldron:GetSkillList(self.vars.playername, skillName);
 	if not skillList then
@@ -317,6 +311,13 @@ function Cauldron:UpdateSkillList()
 			break;
 		end

+		if not self.db.realm.userdata[self.vars.playername].skills[skillName].window.skills[skillInfo.name] then
+			self.db.realm.userdata[self.vars.playername].skills[skillName].window.skills[skillInfo.name] = {
+				favorite = false,
+				expanded = false,
+			};
+		end
+
 		local skillFrame = _G["CauldronSkillItem"..i];

 		-- check if we have a frame for this position
@@ -333,40 +334,8 @@ function Cauldron:UpdateSkillList()
 									 "CauldronSkillItemFrameTemplate");
 		end

-		--[[
-		if self.db.realm.userdata[self.vars.playername].options.compactView then
-			-- set the height of frame
-			skillFrame:SetHeight(25);
-			_G["CauldronSkillItem"..i.."SkillCooldown"]:SetHeight(25);
-
-			-- rescale the icon frame
-			_G["CauldronSkillItem"..i.."SkillIcon"]:SetWidth(18);
-			_G["CauldronSkillItem"..i.."SkillIcon"]:SetHeight(18);
-
-			-- reposition the name
-			_G["CauldronSkillItem"..i.."SkillName"]:SetPoint("TOPLEFT", 43, -4);
-
-			-- hide the category info
-			_G["CauldronSkillItem"..i.."SkillCategory"]:Hide();
-		else
-		--]]
-			-- set the height of frame
-			skillFrame:SetHeight(CAULDRON_SKILLITEM_COLLAPSED_HEIGHT);
-			-- TODO: set height if expanded
-		--[[
-			_G["CauldronSkillItem"..i.."SkillCooldown"]:SetHeight(50);
-
-			-- rescale the icon frame
-			_G["CauldronSkillItem"..i.."SkillIcon"]:SetWidth(37);
-			_G["CauldronSkillItem"..i.."SkillIcon"]:SetHeight(37);
-
-			-- reposition the name
-			_G["CauldronSkillItem"..i.."SkillName"]:SetPoint("TOPLEFT", 62, -4);
-
-			-- show the category info
-			_G["CauldronSkillItem"..i.."SkillCategory"]:Show();
-		end
-		--]]
+		-- set the height of frame
+		skillFrame:SetHeight(CAULDRON_SKILLITEM_COLLAPSED_HEIGHT);

 		skillFrame:SetID(i);
 		skillFrame.skillIndex = skillInfo.index;
@@ -494,6 +463,9 @@ function Cauldron:UpdateSkillList()
 				-- fill in the reagents
 				-- _G["CauldronSkillItem"..i.."Reagents"]:SetScale(0.86);

+				-- learn reagents
+				Cauldron:LearnSkillReagents(skillInfo);
+
 				-- get reagents table
 				local reagents = skillInfo.reagents;
 				local reagentCount = #reagents;
@@ -502,6 +474,7 @@ function Cauldron:UpdateSkillList()
 				local reagentDetailsFrame = _G["CauldronSkillItem"..i.."ItemDetails"];

 				if reagentsExpanded then
+
 					reagentDetailsFrame:Show();
 					smallReagentsFrame:Hide();

@@ -543,7 +516,7 @@ function Cauldron:UpdateSkillList()
 					local reagentFrame = _G["CauldronSkillItem"..i.."ReagentsItemDetail"..j];
 					local reagentDetailFrame = _G["CauldronSkillItem"..i.."ItemDetailsReagent"..j];

-					if reagentFrame then
+					if reagentFrame or reagentDetailFrame then
 						if j > reagentCount then
 							reagentFrame:Hide();
 							reagentDetailFrame:Hide();
diff --git a/CauldronQueue.lua b/CauldronQueue.lua
index d1c8f40..1a94b0d 100644
--- a/CauldronQueue.lua
+++ b/CauldronQueue.lua
@@ -105,13 +105,13 @@ function CauldronQueue:GetIntermediates(queue)
 --				table.insert(items, item);
 --			end
 --		else
-			local t = CopyTable(item);
-			local skillInfo = Cauldron:GetSkillInfo(t.tradeskill, t.name);
-			if skillInfo and (skillInfo.available > 0) then
-				-- increase the priority of items that can be crafted, so that they appear at the top of the list
-				t.priority = t.priority + 1000;
-			end
-			table.insert(items, t);
+		local t = CopyTable(item);
+		local skillInfo = Cauldron:GetSkillInfo(t.tradeskill, t.name);
+		if skillInfo and (skillInfo.available > 0) then
+			-- increase the priority of items that can be crafted, so that they appear at the top of the list
+			t.priority = t.priority + 1000;
+		end
+		table.insert(items, t);
 --		end
 	end

diff --git a/CauldronTradeskill.lua b/CauldronTradeskill.lua
index b2bf10f..39a2593 100644
--- a/CauldronTradeskill.lua
+++ b/CauldronTradeskill.lua
@@ -3,15 +3,14 @@

 local L = LibStub("AceLocale-3.0"):GetLocale("Cauldron")

-function Cauldron:NeedsSkillUpdate()
+function Cauldron:GetTradeSkillName()

---	Cauldron:info("checking for skill update");
-
-	if CURRENT_TRADESKILL == "UNKNOWN" or CURRENT_TRADESKILL == "" then
---		Cauldron:info("no current tradeskill; no update needed");
-		return false;
+	local skillName = GetTradeSkillLine();
+	if not skillName then
+		return nil;
 	end
-	local skillName = CURRENT_TRADESKILL;
+
+	CURRENT_TRADESKILL = skillName;
 	if IsTradeSkillLinked() then
 		skillName = "Linked-"..skillName;
 	end
@@ -19,6 +18,18 @@ function Cauldron:NeedsSkillUpdate()
 		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] = {};
@@ -46,7 +57,7 @@ function Cauldron:NeedsSkillUpdate()
 		return true;
 	end

-	if (tonumber(numTradeSkills) ~= tonumber(skillDB.skillCount)) then
+	if (tonumber(numTradeSkills) ~= tonumber(skillDB.actualSkillCount)) then
 		return true;
 	end
 	if (tonumber(rank) ~= tonumber(skillDB.skillLevel)) then
@@ -62,15 +73,10 @@ function Cauldron:UpdateSkillItemCounts()

 	local skillName, rank, maxRank = GetTradeSkillLine();

-	if skillName == "UNKNOWN" then
-		return;
-	end
-	-- check for linked or guild lists
-	if IsTradeSkillLinked() then
-		skillName = "Linked-"..skillName;
-	end
-	if IsTradeSkillGuild() then
-		skillName = "Guild-"..skillName;
+	local baseSkillName = nil;
+	skillName, baseSkillName = Cauldron:GetTradeSkillName();
+	if not skillName then
+		return;
 	end

 	local skillDB = self.db.realm.userdata[self.vars.playername].skills[skillName];
@@ -104,7 +110,277 @@ function Cauldron:UpdateSkillItemCounts()

 end

-function Cauldron:UpdateSkills(firstIndex, lastIndex)
+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");
@@ -112,14 +388,15 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 	end

 	local skillName, rank, maxRank = GetTradeSkillLine();
+	local baseSkillName;

-	if skillName == "UNKNOWN" then
-		return;
+	skillName, baseSkillName = Cauldron:GetTradeSkillName();
+	if not skillName then
+		return;
 	end

 	local numTradeSkills = GetNumTradeSkills();
 	Cauldron.vars.numSkills = numTradeSkills;
-	local baseSkillName = skillName;

 --	Cauldron:info("scanningSkills="..tostring(self.scanningSkills));
 	if not Cauldron.scanningSkills then
@@ -143,14 +420,7 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 			end
 		end

-		-- check for linked or guild lists
-		if IsTradeSkillLinked() then
-			skillName = "Linked-"..skillName;
-		end
-		if IsTradeSkillGuild() then
-			skillName = "Guild-"..skillName;
-		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] = {};
@@ -160,6 +430,7 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 		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];
@@ -215,7 +486,7 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 		--]]

 		local category = "";
-		local rescanCount = 0;
+--		local rescanCount = 0;

 		for i=1,GetNumTradeSkills() do
 			local name, difficulty, avail, expanded, verb, numSkillUps = GetTradeSkillInfo(i);
@@ -302,8 +573,8 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 					end
 				else
 --]]
-					-- fill in the db entry
-					skillDB.recipes[name] = {
+					-- create the db entry
+					local recipe = {
 						['index'] = i,
 						['name'] = name,
 						['description'] = GetTradeSkillDescription(i),
@@ -326,6 +597,26 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)

 						['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;
@@ -364,6 +655,8 @@ function Cauldron:UpdateSkills(firstIndex, lastIndex)
 					--]]

 					-- 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);
@@ -408,6 +701,7 @@ Cauldron:warn("i="..tostring(i).."; j="..tostring(j));
 							end
 						end
 					end
+					--]==]

 					-- fill in the keywords db entry
 					skillDB.recipes[name].keywords = keywords;
@@ -435,6 +729,12 @@ Cauldron:warn("i="..tostring(i).."; j="..tostring(j));
 			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.");
@@ -564,6 +864,8 @@ function Cauldron:GetSkillList(playername, skillName)

 		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
@@ -609,10 +911,11 @@ function Cauldron:GetSkillList(playername, skillName)
 		end

 		-- check difficulty filter
-		if not self.db.realm.userdata[playername].skills[skillName].window.filter[recipe.difficulty] then
+		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];
@@ -630,14 +933,15 @@ function Cauldron:GetSkillList(playername, skillName)
 		if slotInfo and not(slotInfo.checked) then
 			add = false;
 		end
+		--]]

 		-- check reagent filter
-		if self.db.realm.userdata[playername].skills[skillName].window.filter.haveAllReagents then
+		if filter.haveAllReagents then
 			-- check if the available count is 0
 			if recipe.available == 0 then
 				add = false;
 			end
-		elseif self.db.realm.userdata[playername].skills[skillName].window.filter.haveKeyReagents then
+		elseif filter.haveKeyReagents then
 			-- check if the reagent count for key reagents is 0
 			for _, rinfo in ipairs(recipe.reagents) do
 				-- check possession count
@@ -645,7 +949,7 @@ function Cauldron:GetSkillList(playername, skillName)
 					add = false;
 				end
 			end
-		elseif self.db.realm.userdata[playername].skills[skillName].window.filter.haveAnyReagents then
+		elseif filter.haveAnyReagents then
 			-- check if the reagent count for any reagent is > 0
 			add = false;
 			for _, rinfo in ipairs(recipe.reagents) do
@@ -657,14 +961,14 @@ function Cauldron:GetSkillList(playername, skillName)
 		end

 		-- check favorites filter
-		if self.db.realm.userdata[playername].skills[skillName].window.filter.favorites then
+		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 self.db.realm.userdata[playername].skills[skillName].window.filter.achievements then
+		if filter.achievements then
 			local achievements = Cauldron:GetAchievementsForSkill(recipe);
 			if (not achievements) or (#achievements == 0) then
 				add = false;
@@ -693,13 +997,17 @@ function Cauldron:GetSkillList(playername, skillName)
 				return true;
 			end

-			if self.db.realm.userdata[playername].skills[skillName].window.filter.sortDefault then
-				local r1v = self.db.realm.userdata[playername].skills[skillName].recipes[r1.name].index;
-				local r2v = self.db.realm.userdata[playername].skills[skillName].recipes[r2.name].index;
+			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 self.db.realm.userdata[playername].skills[skillName].window.filter.sortAlpha then
+			elseif filter.sortAlpha then
 				return r1.name < r2.name;
-			elseif self.db.realm.userdata[playername].skills[skillName].window.filter.sortDifficulty then
+			elseif filter.sortDifficulty then
 				local difficulty = {
 					optimal = 4,
 					medium = 3,
@@ -707,27 +1015,27 @@ function Cauldron:GetSkillList(playername, skillName)
 					trivial = 1,
 				};

-				local r1v = self.db.realm.userdata[playername].skills[skillName].recipes[r1.name].difficulty;
-				local r2v = self.db.realm.userdata[playername].skills[skillName].recipes[r2.name].difficulty;
+				local r1v = recipe1.difficulty;
+				local r2v = recipe2.difficulty;
 				return difficulty[r1v] > difficulty[r2v];
-			elseif self.db.realm.userdata[playername].skills[skillName].window.filter.sortItemLevel then
+			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 self.db.realm.userdata[playername].skills[skillName].window.filter.sortRequiredLevel then
+			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 self.db.realm.userdata[playername].skills[skillName].window.filter.sortFavorites then
+			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 self.db.realm.userdata[playername].skills[skillName].window.filter.sortBenefit then
+			elseif filter.sortBenefit then
 				return true; -- TODO
 			end

@@ -845,6 +1153,9 @@ function Cauldron:GetReagentInfoByIndex(item, reagentIndex)
 		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
@@ -869,6 +1180,9 @@ function Cauldron:GetRequiredItems(skillInfo, amount)

 	-- 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
@@ -901,105 +1215,6 @@ local function split(sep, str)
 	return result;
 end

---[==[
-function Cauldron:GetReagentsForSkill(skillInfo)
-
-	if not skillInfo then
-		self:error("No skill info provided!");
-		return {};
-	end
-
-	local reagents = {};
-
-	local itemId = self:GetIdFromLink(skillInfo.itemLink);
-
-	local skillName = CURRENT_TRADESKILL;
-	local baseSkillName = CURRENT_TRADESKILL;
-	if IsTradeSkillLinked() then
-		skillName = "Linked-"..skillName;
-	end
-	if IsTradeSkillGuild() then
-		skillName = "Guild-"..skillName;
-	end
-
-	-- check if the reagents are already populated
-	if #skillInfo.reagents > 0 then
-		return skillInfo.reagents;
-	end
-
-	-- check for the proper trade skill context
-	if CURRENT_TRADESKILL == skillInfo.tradeskill then
-
-		for i=1,GetTradeSkillNumReagents(skillInfo.index) do
-			local name, icon, count, _ = GetTradeSkillReagentInfo(skillInfo.index, i);
-			local link = GetTradeSkillReagentItemLink(skillInfo.index, i);
-			local itemId = Cauldron:GetIdFromLink(link);
-			local value, set = self.libs.PT:ItemInSet(itemId, "Tradeskill.Mat.BySource.Vendor");
-			local key = true;
-			if value then
-				key = false;
-			end
-
-			local r = {
---				["toonHas"] = GetItemCount(link),
-				["name"] = name,
-				["numRequired"] = count,
-				["skillIndex"] = skillInfo.index,
-				["icon"] = icon,
-				["link"] = link,
-				["key"] = key,
-			};
-
-			table.insert(reagents, r);
-		end
-
-		-- save the reagent list
-		skillInfo.reagents = reagents;
-	else
-		self:warn("No tradeskill context found; using PeriodicTable for reagent info!");
-
-		-- check the standard skill
-		local reagentStr = self.libs.PT:ItemInSet(itemId, "TradeskillResultMats.Forward."..skillInfo.tradeskill);
-		if not reagentStr then
-			-- lookup the mapped skill
-			local skillMap = {
-				['Mining'] = 'Smelting',
-	--			['Inscription'] = 'Milling',
-	--			['Jewelcrafting'] = 'Prospecting',
-			};
-			if skillMap[skillInfo.tradeskill] then
-				reagentStr = self.libs.PT:ItemInSet(itemId, "TradeskillResultMats.Forward."..skillMap[skillInfo.tradeskill]);
-			end
-		end
-		if not reagentStr then
-			self:error("No reagents found for skill: "..skillInfo.name);
-			return {};
-		end
-
-		-- split the reagent info
-		for _, reagent in ipairs(split(";", reagentStr)) do
-			local id, numRequired = strsplit("x", reagent);
-
-			-- get item details for the reagent
-			local name, link, _, _, _, _, _, _, _, icon = GetItemInfo(id);
-
-			local r = {
---				["toonHas"] = GetItemCount(id),
-				["name"] = name,
-				["numRequired"] = tonumber(numRequired),
-				["skillIndex"] = skillInfo.index,
-				["icon"] = icon,
-				["link"] = link,
-			};
-
-			table.insert(reagents, r);
-		end
-	end
-
-	return reagents;
-end
---]==]
-
 function Cauldron:GetSkillsForReagent(id)
 	if not id then
 		return {};
diff --git a/CauldronUtil.lua b/CauldronUtil.lua
index b1cfe0b..74cdbeb 100644
--- a/CauldronUtil.lua
+++ b/CauldronUtil.lua
@@ -263,7 +263,6 @@ function Cauldron:CreateAchievementSkillMap()

 	Cauldron.vars.achievementMap = {};

---[[
 	-- TODO: get all achievement categories that have 169 (Professions) as parent
 	-- currently: 171 (Fishing), 170 (Cooking), 172 (First Aid)
 	local categories = { 170, 171, 172 };
@@ -295,7 +294,6 @@ function Cauldron:CreateAchievementSkillMap()
 			end
 		end
 	end
---]]

 end