--[[------------------------------------------------------------------ --SousChef.lua --Author: Wobin inspired by ingeniousclown's Research Assistant ------------------------------------------------------------------]]-- SousChef = {} SousChef.Utility = {} SousChef.Media = {} local SousChef = SousChef local u = SousChef.Utility local LAM = LibStub:GetLibrary("LibAddonMenu-1.0") local BACKPACK = ZO_PlayerInventoryBackpack local BANK = ZO_PlayerBankBackpack local GUILD_BANK = ZO_GuildBankBackpack SousChef.Pantry = {} SousChef.Cookbook = {} SousChef.CookbookIndex = {} SousChef.ReverseCookbook = {} SousChef.settings = nil SousChef.slotLines = {} SousChef.hookedFunctions = {} SousChef.hookedDataFunction = nil local rowHandler = {} local function AddRecipe(Cookbook, link) for _,v in pairs(Cookbook) do if v == link then return end end table.insert(Cookbook, link) end local typeIconLookup = { ["Grilled"] = 9, ["Bread and Pies"] = 10, ["Soup and Stew"] = 11, ["Beer"] = 12, ["Spirits"] = 13, ["Wine"] = 14 } function SousChef:RefreshViews() ZO_ScrollList_RefreshVisible(BACKPACK) ZO_ScrollList_RefreshVisible(BANK) ZO_ScrollList_RefreshVisible(GUILD_BANK) end function SousChef:ParseRecipes() local lists = GetNumRecipeLists() for listIndex = 1, lists do local name, count = GetRecipeListInfo(listIndex) for recipeIndex = 1, count do if GetRecipeInfo(listIndex, recipeIndex) then -- Store the recipes known local recipeName = u.CleanString((GetRecipeResultItemInfo(listIndex, recipeIndex))) SousChef.Cookbook[recipeName] = true if not SousChef.settings.Cookbook[recipeName] then SousChef.settings.Cookbook[recipeName] = {} end SousChef.settings.Cookbook[recipeName][GetUnitName("player")] = true local _, _, ingredientCount, level, _, specialType = GetRecipeInfo(listIndex, recipeIndex) -- Lookup for the recipe result count SousChef.CookbookIndex[zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))] = {listIndex = listIndex, recipeIndex = recipeIndex, numIngredients = ingredientCount} for ingredientIndex = 1, ingredientCount do local link = u.GetItemID(GetRecipeIngredientItemLink(listIndex, recipeIndex, ingredientIndex, LINK_STYLE_DEFAULT)) -- Store the fact that the ingredient is used if ingredientIndex < 3 or not SousChef.settings.showSpecialIngredients then SousChef.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) SousChef.settings.Pantry[link] = math.max(level, SousChef.Pantry[link] or 0) else SousChef.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 SousChef.settings.Pantry[link] = SousChef.settings.typeIcon and typeIconLookup[name] or specialType == PROVISIONER_SPECIAL_INGREDIENT_TYPE_FLAVORING and 7 or 8 end -- Store the recipe it's used in if not SousChef.ReverseCookbook[link] then SousChef.ReverseCookbook[link] = {} end AddRecipe(SousChef.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) -- Store the global reference if not SousChef.settings.ReverseCookbook[link] then SousChef.settings.ReverseCookbook[link] = {} end AddRecipe(SousChef.settings.ReverseCookbook[link], zo_strformat(SI_TOOLTIP_ITEM_NAME, GetRecipeResultItemLink(listIndex, recipeIndex, LINK_STYLE_BRACKETS))) end end end end SousChef:RefreshViews() end local function SousChefCreateSettings() local panel = LAM:CreateControlPanel("SousChefMenu", "Sous Chef") LAM:AddHeader(panel, "SousChef_General", "Recipe Options") LAM:AddCheckbox(panel, "processRecipes", "Have Sous Chef check for recipes", "Non English clients may want to untick this if the experimental matching isn't sufficient", function() return SousChef.settings.processRecipes end, function(value) SousChef.settings.processRecipes = not SousChef.settings.processRecipes if not SousChef.settings.processRecipes then ZO_Options_SetOptionInactive(markLearnt) ZO_Options_SetOptionInactive(markAltKnows) ZO_Options_SetOptionInactive(showAltKnows) ZO_Options_SetOptionInactive(experimental) else ZO_Options_SetOptionActive(markLearnt) ZO_Options_SetOptionActive(markAltKnows) ZO_Options_SetOptionActive(showAltKnows) ZO_Options_SetOptionActive(experimental) end end) LAM:AddDropdown(panel, "markLearnt", "Mark if recipes are ", "How do you want Sous Chef to indicate your knowledge of a recipe?", {"known", "unknown"}, function() return SousChef.settings.checkKnown end, function(valueString) SousChef.settings.checkKnown = valueString end) LAM:AddCheckbox(panel, "markAltKnows", "Alternate Character Check", "Indicate if an alt knows the recipe on unknown recipes. Will only work if the above setting is set to 'unknown'", function() return SousChef.settings.markAlt end, function(value) SousChef.settings.markAlt = not SousChef.settings.markAlt SousChef:RefreshViews() end) LAM:AddCheckbox(panel, "showAltKnows", "Alternate Character Recipe Knowledge", "Show rank indicators on alts for all recipe knowledge of all alternate characters", function() return SousChef.settings.showAltKnowledge end, function(value) SousChef.settings.showAltKnowledge = not SousChef.settings.showAltKnowledge SousChef:RefreshViews() end) LAM:AddCheckbox(panel, "experimental", "Use the experimental recipe matcher", [[Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipes that don't match the results exactly, with the recipe/result names)]], function() return SousChef.settings.experimentalMatch end, function(value) SousChef.settings.experimentalMatch = not SousChef.settings.experimentalMatch end) LAM:AddCheckbox(panel, "sortProvisioning", "Sort the Provisioning Table", "Will sort the provisioning table by Rank, Quality, then Name", function() return SousChef.settings.sortProvisioningTable end, function(value) SousChef.settings.sortProvisioningTable = not SousChef.settings.sortProvisioningTable end, true, "Will not sort within ranks, eg 1-20 will be somewhat jumbled") LAM:AddHeader(panel, "SousChef_Tooltip", "Tooltip Options") LAM:AddCheckbox(panel, "showOnClickOnly", "Show in Tooltip only on click", "Only show details on a left click to save space (requires /reloadui)", function() return SousChef.settings.showOnClick end, function(value) SousChef.settings.showOnClick = not SousChef.settings.showOnClick end, true, "Requires /reloadui") LAM:AddCheckbox(panel, "showResultCount", "Show recipe result counts", "Show how many of a particular recipe can be made next to the link in the Ingredient tooltip", function() return SousChef.settings.showCounts end, function(value) SousChef.settings.showCounts = not SousChef.settings.showCounts end) LAM:AddCheckbox(panel, "markAltIngKnows", "Alternate Character Ingredient Knowledge", "Indicate if an alt uses the ingredients", function() return SousChef.settings.showAltIngredientKnowledge end, function(value) SousChef.settings.showAltIngredientKnowledge = not SousChef.settings.showAltIngredientKnowledge SousChef:RefreshViews() end) LAM:AddHeader(panel, "SousChef_Indicator", "Indicator Options") LAM:AddCheckbox(panel, "useBold", "Use bolder icons", "Swap out rank icon to a more flat display", function() return SousChef.settings.boldIcon end, function(value) SousChef.settings.boldIcon = not SousChef.settings.boldIcon SousChef:RefreshViews() end) LAM:AddCheckbox(panel, "specialIngredients", "Show special ingredients", "Indicate if an ingredient is considered a Spice/Flavour rather than the tier of the max ranked recipe you have that uses it", function() return SousChef.settings.showSpecialIngredients end, function(value) SousChef.settings.showSpecialIngredients = not SousChef.settings.showSpecialIngredients if SousChef.settings.showSpecialIngredients then ZO_Options_SetOptionActive(typeIcons) else ZO_Options_SetOptionInactive(typeIcons) end SousChef.ParseRecipes() end) LAM:AddCheckbox(panel, "typeIcons", "Show special ingredients as types", "Use the icon for the type of food it's a special ingredient for, eg Grilled", function() return SousChef.settings.typeIcon end, function(value) SousChef.settings.typeIcon = not SousChef.settings.typeIcon SousChef.ParseRecipes() SousChef:RefreshViews() end) LAM:AddColorPicker(panel, "setColour", "Indicator colour", "Allows you to set the colour of the indicator", function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end, function(r,g,b) SousChef.settings.colour[1] = r; SousChef.settings.colour[2] = g; SousChef.settings.colour[3] = b SousChef:RefreshViews() end) LAM:AddColorPicker(panel, "setShoppingListColour", "Shopping List indicator colour", "Allows you to set the colour of the indicator for ingredients in your Shopping List", function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end, function(r,g,b) SousChef.settings.shoppingColour[1] = r; SousChef.settings.shoppingColour[2] = g; SousChef.settings.shoppingColour[3] = b SousChef:RefreshViews() end) LAM:AddCheckbox(panel, "onlyShoppingList", "Only show Shopping List ingredients", "Only mark ingredients on your Shopping List", function() return SousChef.settings.onlyShowShopping end, function(value) SousChef.settings.onlyShowShopping = not SousChef.settings.onlyShowShopping SousChef:RefreshViews() end) LAM:AddCheckbox(panel, "sortKnownInventoryIngredients", "Sort ingredients in the inventory", "Will sort known ingredients by rank", function() return SousChef.settings.sortKnownIngredients end, function(value) SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients if not SousChef.settings.sortKnownIngredients then SousChef.UnregisterSort() else SousChef.SetupSort() end end) ZO_CreateStringId("SI_BINDING_NAME_SC_MARK_RECIPE", "Mark Recipe") if not SousChef.settings.processRecipes then ZO_Options_SetOptionInactive(markLearnt) ZO_Options_SetOptionInactive(markAltKnows) ZO_Options_SetOptionInactive(showAltKnows) ZO_Options_SetOptionInactive(experimental) else ZO_Options_SetOptionActive(markLearnt) ZO_Options_SetOptionActive(markAltKnows) ZO_Options_SetOptionActive(showAltKnows) ZO_Options_SetOptionActive(experimental) end if SousChef.settings.showSpecialIngredients then ZO_Options_SetOptionActive(typeIcons) else ZO_Options_SetOptionInactive(typeIcons) end end local function SousChef_Loaded(eventCode, addOnName) if(addOnName ~= "SousChef") then return end local defaults = { watching = true, checkKnown = "unknown", markAlt = false, colour = {1, 1, 1}, shoppingColour = {0,1,1}, Cookbook = {}, Pantry = {}, ReverseCookbook = {}, showAltKnowledge = false, showAltIngredientKnowledge = false, boldIcon = false, typeIcon = true, experimentalMatch = false, processRecipes = true, showSpecialIngredients = false, ignoredRecipes = {}, showOnClick = false, showCounts = true, shoppingList = {}, onlyShowShopping = false, qualityChecked = false, sortProvisioningTable = true, sortKnownIngredients = false } SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 9, GetCVar("Language.2"), defaults) local function tablelength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end SLASH_COMMANDS['/scstats'] = function() d("Number of recipes known: ".. tablelength(SousChef.settings.Cookbook)) d("Number of ingredients tracked: "..tablelength(SousChef.settings.Pantry)) end SousChefCreateSettings() zo_callLater(SousChef.ParseRecipes, 1000) SLASH_COMMANDS['/sciadd'] = SousChef.AddRecipeToIgnoreList SLASH_COMMANDS['/sciremove'] = SousChef.RemoveRecipeFromIgnoreList SLASH_COMMANDS['/scilist'] = SousChef.ListIgnoredRecipes SousChef:UpdateProvisioningTable() SousChef:HookGetRecipeInfo() if SousChef.settings.sortKnownIngredients then SousChef.SetupSort() end -- Now we want to hook into the function that sets the details on the inventory slot zo_callLater(SousChef.HookEvents, 3000) end function SousChef.HookEvents() EVENT_MANAGER:RegisterForEvent("SousChefTrading", EVENT_TRADING_HOUSE_RESPONSE_RECEIVED, SousChef.HookTrading) EVENT_MANAGER:RegisterForEvent("SousChefLearnt", EVENT_RECIPE_LEARNED, SousChef.ParseRecipes) EVENT_MANAGER:RegisterForEvent("SousChefProvi", EVENT_CRAFTING_STATION_INTERACT, function(...) SousChef:HookRecipeTree(...) end) EVENT_MANAGER:RegisterForEvent("SousChefProviEnd", EVENT_END_CRAFTING_STATION_INTERACT, function() SousChef:UnhookRecipeTree() end) SousChef.HookInventory() end EVENT_MANAGER:RegisterForEvent("SousChefLoaded", EVENT_ADD_ON_LOADED, SousChef_Loaded)