contrebasse@111: local addonName, A = ... contrebasse@111: contrebasse@111: -- GLOBALS: SPELL_FAILED_ERROR, OpenStackSplitFrame, StackSplitFrame_OnChar, StackSplitFrame contrebasse@111: contrebasse@111: -- Lua functions contrebasse@111: local tostring = tostring contrebasse@111: local min = math.min contrebasse@111: local max = math.max contrebasse@111: local floor = math.floor contrebasse@111: contrebasse@111: -- Wow functions contrebasse@111: local IsTradeSkillGuild = IsTradeSkillGuild contrebasse@111: local IsTradeSkillLinked = IsTradeSkillLinked contrebasse@111: local IsModifierKeyDown = IsModifierKeyDown contrebasse@111: local IsShiftKeyDown = IsShiftKeyDown contrebasse@111: local GetTradeSkillSelectionIndex = GetTradeSkillSelectionIndex contrebasse@111: local GetTradeSkillReagentItemLink = GetTradeSkillReagentItemLink contrebasse@111: local GetTradeSkillReagentInfo = GetTradeSkillReagentInfo contrebasse@111: local GetTradeSkillLine = GetTradeSkillLine contrebasse@111: local GetItemInfo = GetItemInfo contrebasse@111: local DoTradeSkill = DoTradeSkill contrebasse@111: contrebasse@111: --SPELL_FAILED_REAGENTS = "Missing reagent: %s"; contrebasse@111: --ERR_SPELL_FAILED_REAGENTS_GENERIC = "Missing reagent"; contrebasse@111: --ERR_INTERNAL_BAG_ERROR = "Internal Bag Error"; contrebasse@111: --SPELL_FAILED_ERROR = "Internal error"; contrebasse@111: contrebasse@111: --------------------------------------------------- contrebasse@111: -- Craft items contrebasse@111: --------------------------------------------------- contrebasse@111: -- Function run after selecting a item in the tradeskill window contrebasse@111: -- It only "prefilters" the possibilities contrebasse@111: function A.ProcessReagent(btn) contrebasse@111: -- Do not manage guild or linked tradeskill contrebasse@111: if IsTradeSkillGuild() or IsTradeSkillLinked() then return end contrebasse@111: contrebasse@111: -- We want no modifiers, or shift to choose the number of reagent to craft contrebasse@111: if IsModifierKeyDown() and not IsShiftKeyDown() then return end contrebasse@111: local chooseNumberToCraft = IsShiftKeyDown() contrebasse@111: contrebasse@111: -- Index of the reagent in the recipe, taken from the button name contrebasse@111: local reagentIndexInRecipe = A.buttonNumber(btn) contrebasse@111: contrebasse@111: -- ID of the reagent we want to craft contrebasse@111: local recipeIndex = GetTradeSkillSelectionIndex() contrebasse@111: local reagentID = A.link2ID(GetTradeSkillReagentItemLink(recipeIndex, reagentIndexInRecipe)) contrebasse@111: contrebasse@111: -- Continue only if the reagent is known contrebasse@111: if not reagentID or not A.data[reagentID] then return end contrebasse@111: contrebasse@111: -- If only one recipe is known for the reagent and it is an actual recipe, use it contrebasse@111: if #(A.data[reagentID]) == 1 and not A.data[reagentID][1].macro then contrebasse@111: A.CraftItemWithRecipe(recipeIndex,reagentID,A.data[reagentID][1],reagentIndexInRecipe,chooseNumberToCraft,btn) contrebasse@111: contrebasse@111: else -- Many recipes are known for this item, or it is not a standard tradeskill display them all contrebasse@111: A.externalCraftWindow(reagentID,reagentIndexInRecipe) contrebasse@111: end -- if contrebasse@111: --A.RestoreActiveFilters() contrebasse@111: end -- function contrebasse@111: contrebasse@111: -- Launch the procedure for a standard recipe contrebasse@111: -- Can be called from the external window contrebasse@111: function A.CraftItemWithRecipe(recipeIndex,reagentID,recipeData,reagentIndexInRecipe,chooseNumberToCraft,btn) contrebasse@111: -- Check that it's the same tradeskill contrebasse@111: if recipeData.tradeskillName ~= GetTradeSkillLine() then contrebasse@111: A.Error(A.L["The recipe to make this reagent is in another tradeskill. Currently ReagentMaker can not manage such a case, sorry."]) contrebasse@111: return contrebasse@111: end contrebasse@111: contrebasse@111: -- Check how many times the recipe is makable contrebasse@111: local numMakable = A.numRecipeMakable(recipeData[1],recipeData[2]) contrebasse@111: if not numMakable then contrebasse@111: A.Error(SPELL_FAILED_ERROR) contrebasse@111: return contrebasse@111: end contrebasse@111: contrebasse@111: if numMakable<=0 then contrebasse@111: -- If not makable, try a one-step recursion contrebasse@111: -- enables e.g. to mill to create an ink contrebasse@111: -- need a unique reagent contrebasse@111: if recipeData[1] and A.data[recipeData[1]] then contrebasse@111: if A.externalCraftWindow(recipeData[1],reagentIndexInRecipe,reagentID) ~= false then contrebasse@111: -- there was no problem opening the external window contrebasse@111: return contrebasse@111: end contrebasse@111: end contrebasse@111: contrebasse@111: -- There isn't enough reagents contrebasse@111: --@todo include name of reagent if unique contrebasse@111: A.Error(A.L["You do not have enough reagents to craft [%s]"]:format(GetItemInfo(reagentID) or "item #"..reagentID)) contrebasse@111: return contrebasse@111: end contrebasse@111: contrebasse@111: -- Optimal number of items to craft contrebasse@111: local numToMake = A.numToMake(recipeIndex, reagentIndexInRecipe,numMakable, recipeData[3], recipeData[4]) contrebasse@111: contrebasse@111: -- Choose number or craft directly contrebasse@111: if chooseNumberToCraft then contrebasse@111: -- Store info to be able to run the function later contrebasse@111: btn.ReagentMaker_reagentID = reagentID contrebasse@111: btn.ReagentMaker_recipeData = recipeData contrebasse@111: contrebasse@111: -- Open dialog contrebasse@111: OpenStackSplitFrame(numMakable, btn, "TOP", "BOTTOM") contrebasse@111: contrebasse@111: -- Fill in the number to make contrebasse@111: numToMake = tostring(numToMake) contrebasse@111: for i = 1,numToMake:len() do contrebasse@111: StackSplitFrame_OnChar(StackSplitFrame,numToMake:gsub(i,i)) contrebasse@111: end contrebasse@111: StackSplitFrame.typing = 0 -- reinit the frame so that the entered value will be erased on text entry contrebasse@111: else contrebasse@111: A.DoCraft(reagentID,recipeData,numToMake) contrebasse@111: end -- if contrebasse@111: end contrebasse@111: contrebasse@111: -- Compute optimal number of items to craft contrebasse@111: function A.numToMake(recipeIndex, reagentIndexInRecipe,numReagentMakable,minMade,maxMade) contrebasse@111: -- Look at how many we need to make one item for the selected recipe contrebasse@111: local numToMake = 1 contrebasse@111: local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipeIndex, reagentIndexInRecipe) contrebasse@111: -- make enough reagents to craft one more item contrebasse@111: numToMake = min(floor(playerReagentCount/reagentCount+1)*reagentCount-playerReagentCount,numReagentMakable) contrebasse@111: contrebasse@111: -- take into account that some recipe craft more than one item contrebasse@111: -- use the mean between min and max, but make at least one... contrebasse@111: if not minMade then contrebasse@111: minMade = 1 contrebasse@111: elseif minMade<1 then contrebasse@111: -- from the percentage, compute the mean number of crafts to make contrebasse@111: minMade = 1/minMade contrebasse@111: end contrebasse@111: if not maxMade then contrebasse@111: maxMade = minMade contrebasse@111: end contrebasse@111: numToMake = max(floor(2*numToMake/(maxMade+minMade)),1) contrebasse@111: return numToMake contrebasse@111: end contrebasse@111: contrebasse@111: -- function used after choosing the number of reagent to craft contrebasse@111: function A.SplitStack(owner,split) contrebasse@111: A.DoCraft(owner.ReagentMaker_reagentID,owner.ReagentMaker_recipeData,split) contrebasse@111: owner.ReagentMaker_reagentID = nil contrebasse@111: owner.ReagentMaker_recipeData = nil contrebasse@111: end contrebasse@111: contrebasse@111: -- Find the recipe and do the crafting contrebasse@111: function A.DoCraft(reagentID,recipeData,numToMake) contrebasse@111: -- Remove filters contrebasse@111: A.SaveActiveFilters(recipeData.header) contrebasse@111: contrebasse@111: -- Find recipe index contrebasse@111: local reagentIndex = A.findExactSkillIndex(reagentID,recipeData.spellLink) -- finds only the first recipe that creates the reagent, should check recipe name too contrebasse@111: contrebasse@111: -- Error if not found contrebasse@111: if not reagentIndex then contrebasse@111: A.Error(A.L["The recipe to make the reagent seems to be hidden, it is not makable. Try to remove the filters on the recipes."]) contrebasse@111: A.RestoreActiveFilters() contrebasse@111: return contrebasse@111: end contrebasse@111: contrebasse@111: -- Craft the item, finally ! contrebasse@111: DoTradeSkill(reagentIndex,numToMake) contrebasse@111: contrebasse@111: -- Restore Filters contrebasse@111: A.RestoreActiveFilters() contrebasse@111: end