| 
contrebasse@111
 | 
     1 local addonName, A = ...
 | 
| 
contrebasse@111
 | 
     2 
 | 
| 
contrebasse@111
 | 
     3 -- GLOBALS: SPELL_FAILED_ERROR, OpenStackSplitFrame, StackSplitFrame_OnChar, StackSplitFrame
 | 
| 
contrebasse@111
 | 
     4 
 | 
| 
contrebasse@111
 | 
     5 -- Lua functions
 | 
| 
contrebasse@111
 | 
     6 local tostring = tostring
 | 
| 
contrebasse@111
 | 
     7 local min = math.min
 | 
| 
contrebasse@111
 | 
     8 local max = math.max
 | 
| 
contrebasse@111
 | 
     9 local floor = math.floor
 | 
| 
contrebasse@111
 | 
    10 
 | 
| 
contrebasse@111
 | 
    11 -- Wow functions
 | 
| 
contrebasse@111
 | 
    12 local IsTradeSkillGuild = IsTradeSkillGuild
 | 
| 
contrebasse@111
 | 
    13 local IsTradeSkillLinked = IsTradeSkillLinked
 | 
| 
contrebasse@111
 | 
    14 local IsModifierKeyDown = IsModifierKeyDown
 | 
| 
contrebasse@111
 | 
    15 local IsShiftKeyDown = IsShiftKeyDown
 | 
| 
contrebasse@111
 | 
    16 local GetTradeSkillSelectionIndex = GetTradeSkillSelectionIndex
 | 
| 
contrebasse@111
 | 
    17 local GetTradeSkillReagentItemLink = GetTradeSkillReagentItemLink
 | 
| 
contrebasse@111
 | 
    18 local GetTradeSkillReagentInfo = GetTradeSkillReagentInfo
 | 
| 
contrebasse@111
 | 
    19 local GetTradeSkillLine = GetTradeSkillLine
 | 
| 
contrebasse@111
 | 
    20 local GetItemInfo = GetItemInfo
 | 
| 
contrebasse@111
 | 
    21 local DoTradeSkill = DoTradeSkill
 | 
| 
contrebasse@111
 | 
    22 
 | 
| 
contrebasse@111
 | 
    23 --SPELL_FAILED_REAGENTS = "Missing reagent: %s";
 | 
| 
contrebasse@111
 | 
    24 --ERR_SPELL_FAILED_REAGENTS_GENERIC = "Missing reagent";
 | 
| 
contrebasse@111
 | 
    25 --ERR_INTERNAL_BAG_ERROR = "Internal Bag Error";
 | 
| 
contrebasse@111
 | 
    26 --SPELL_FAILED_ERROR = "Internal error";
 | 
| 
contrebasse@111
 | 
    27 
 | 
| 
contrebasse@111
 | 
    28 ---------------------------------------------------
 | 
| 
contrebasse@111
 | 
    29 -- Craft items
 | 
| 
contrebasse@111
 | 
    30 ---------------------------------------------------
 | 
| 
contrebasse@111
 | 
    31 -- Function run after selecting a item in the tradeskill window
 | 
| 
contrebasse@111
 | 
    32 -- It only "prefilters" the possibilities
 | 
| 
contrebasse@111
 | 
    33 function A.ProcessReagent(btn)
 | 
| 
contrebasse@111
 | 
    34 	-- Do not manage guild or linked tradeskill
 | 
| 
contrebasse@111
 | 
    35 	if IsTradeSkillGuild() or IsTradeSkillLinked() then return end
 | 
| 
contrebasse@111
 | 
    36 
 | 
| 
contrebasse@111
 | 
    37 	-- We want no modifiers, or shift to choose the number of reagent to craft
 | 
| 
contrebasse@111
 | 
    38 	if IsModifierKeyDown() and not IsShiftKeyDown() then return end
 | 
| 
contrebasse@111
 | 
    39 	local chooseNumberToCraft = IsShiftKeyDown()
 | 
| 
contrebasse@111
 | 
    40 
 | 
| 
contrebasse@111
 | 
    41 	-- Index of the reagent in the recipe, taken from the button name
 | 
| 
contrebasse@111
 | 
    42 	local reagentIndexInRecipe = A.buttonNumber(btn)
 | 
| 
contrebasse@111
 | 
    43 
 | 
| 
contrebasse@111
 | 
    44 	-- ID of the reagent we want to craft
 | 
| 
contrebasse@111
 | 
    45 	local recipeIndex = GetTradeSkillSelectionIndex()
 | 
| 
contrebasse@111
 | 
    46 	local reagentID = A.link2ID(GetTradeSkillReagentItemLink(recipeIndex, reagentIndexInRecipe))
 | 
| 
contrebasse@111
 | 
    47 
 | 
| 
contrebasse@111
 | 
    48 	-- Continue only if the reagent is known
 | 
| 
contrebasse@111
 | 
    49 	if not reagentID or not A.data[reagentID] then return end
 | 
| 
contrebasse@111
 | 
    50 
 | 
| 
contrebasse@111
 | 
    51 	-- If only one recipe is known for the reagent and it is an actual recipe, use it
 | 
| 
contrebasse@111
 | 
    52 	if #(A.data[reagentID]) == 1 and not A.data[reagentID][1].macro then
 | 
| 
contrebasse@111
 | 
    53 		A.CraftItemWithRecipe(recipeIndex,reagentID,A.data[reagentID][1],reagentIndexInRecipe,chooseNumberToCraft,btn)
 | 
| 
contrebasse@111
 | 
    54 
 | 
| 
contrebasse@111
 | 
    55 	else -- Many recipes are known for this item, or it is not a standard tradeskill display them all
 | 
| 
contrebasse@111
 | 
    56 		A.externalCraftWindow(reagentID,reagentIndexInRecipe)
 | 
| 
contrebasse@111
 | 
    57 	end -- if
 | 
| 
contrebasse@111
 | 
    58 end -- function
 | 
| 
contrebasse@111
 | 
    59 
 | 
| 
contrebasse@111
 | 
    60 -- Launch the procedure for a standard recipe
 | 
| 
contrebasse@111
 | 
    61 -- Can be called from the external window
 | 
| 
contrebasse@111
 | 
    62 function A.CraftItemWithRecipe(recipeIndex,reagentID,recipeData,reagentIndexInRecipe,chooseNumberToCraft,btn)
 | 
| 
contrebasse@111
 | 
    63 	-- Check that it's the same tradeskill
 | 
| 
contrebasse@111
 | 
    64 	if recipeData.tradeskillName ~= GetTradeSkillLine() then
 | 
| 
contrebasse@111
 | 
    65 		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
 | 
    66 		return
 | 
| 
contrebasse@111
 | 
    67 	end
 | 
| 
contrebasse@111
 | 
    68 
 | 
| 
contrebasse@111
 | 
    69 	-- Check how many times the recipe is makable
 | 
| 
contrebasse@111
 | 
    70 	local numMakable = A.numRecipeMakable(recipeData[1],recipeData[2])
 | 
| 
contrebasse@111
 | 
    71 	if not numMakable then
 | 
| 
contrebasse@111
 | 
    72 		A.Error(SPELL_FAILED_ERROR)
 | 
| 
contrebasse@111
 | 
    73 		return
 | 
| 
contrebasse@111
 | 
    74 	end
 | 
| 
contrebasse@111
 | 
    75 
 | 
| 
contrebasse@111
 | 
    76 	if numMakable<=0 then
 | 
| 
contrebasse@111
 | 
    77 		-- If not makable, try a one-step recursion
 | 
| 
contrebasse@111
 | 
    78 		-- enables e.g. to mill to create an ink
 | 
| 
contrebasse@111
 | 
    79 		-- need a unique reagent
 | 
| 
contrebasse@111
 | 
    80 		if recipeData[1] and A.data[recipeData[1]] then
 | 
| 
contrebasse@111
 | 
    81 			if A.externalCraftWindow(recipeData[1],reagentIndexInRecipe,reagentID) ~= false then
 | 
| 
contrebasse@111
 | 
    82 				-- there was no problem opening the external window
 | 
| 
contrebasse@111
 | 
    83 				return
 | 
| 
contrebasse@111
 | 
    84 			end
 | 
| 
contrebasse@111
 | 
    85 		end
 | 
| 
contrebasse@111
 | 
    86 
 | 
| 
contrebasse@111
 | 
    87 		-- There isn't enough reagents
 | 
| 
contrebasse@111
 | 
    88 		--@todo include name of reagent if unique
 | 
| 
contrebasse@111
 | 
    89 		A.Error(A.L["You do not have enough reagents to craft [%s]"]:format(GetItemInfo(reagentID) or "item #"..reagentID))
 | 
| 
contrebasse@111
 | 
    90 		return
 | 
| 
contrebasse@111
 | 
    91 	end
 | 
| 
contrebasse@111
 | 
    92 
 | 
| 
contrebasse@111
 | 
    93 	-- Optimal number of items to craft
 | 
| 
contrebasse@111
 | 
    94 	local numToMake = A.numToMake(recipeIndex, reagentIndexInRecipe,numMakable, recipeData[3], recipeData[4])
 | 
| 
contrebasse@111
 | 
    95 
 | 
| 
contrebasse@111
 | 
    96 	-- Choose number or craft directly
 | 
| 
contrebasse@111
 | 
    97 	if chooseNumberToCraft then
 | 
| 
contrebasse@111
 | 
    98 		-- Store info to be able to run the function later
 | 
| 
contrebasse@111
 | 
    99 		btn.ReagentMaker_reagentID = reagentID
 | 
| 
contrebasse@111
 | 
   100 		btn.ReagentMaker_recipeData = recipeData
 | 
| 
contrebasse@111
 | 
   101 
 | 
| 
contrebasse@111
 | 
   102 		-- Open dialog
 | 
| 
contrebasse@111
 | 
   103 		OpenStackSplitFrame(numMakable, btn, "TOP", "BOTTOM")
 | 
| 
contrebasse@111
 | 
   104 
 | 
| 
contrebasse@111
 | 
   105 		-- Fill in the number to make
 | 
| 
contrebasse@111
 | 
   106 		numToMake = tostring(numToMake)
 | 
| 
contrebasse@111
 | 
   107 		for i = 1,numToMake:len() do
 | 
| 
contrebasse@111
 | 
   108 			StackSplitFrame_OnChar(StackSplitFrame,numToMake:gsub(i,i))
 | 
| 
contrebasse@111
 | 
   109 		end
 | 
| 
contrebasse@111
 | 
   110 		StackSplitFrame.typing = 0 -- reinit the frame so that the entered value will be erased on text entry
 | 
| 
contrebasse@111
 | 
   111 	else
 | 
| 
contrebasse@111
 | 
   112 		A.DoCraft(reagentID,recipeData,numToMake)
 | 
| 
contrebasse@111
 | 
   113 	end -- if
 | 
| 
contrebasse@111
 | 
   114 end
 | 
| 
contrebasse@111
 | 
   115 
 | 
| 
contrebasse@111
 | 
   116 -- Compute optimal number of items to craft
 | 
| 
contrebasse@111
 | 
   117 function A.numToMake(recipeIndex, reagentIndexInRecipe,numReagentMakable,minMade,maxMade)
 | 
| 
contrebasse@111
 | 
   118 	-- Look at how many we need to make one item for the selected recipe
 | 
| 
contrebasse@111
 | 
   119 	local numToMake = 1
 | 
| 
contrebasse@111
 | 
   120 	local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipeIndex, reagentIndexInRecipe)
 | 
| 
contrebasse@111
 | 
   121 	-- make enough reagents to craft one more item
 | 
| 
contrebasse@111
 | 
   122 	numToMake = min(floor(playerReagentCount/reagentCount+1)*reagentCount-playerReagentCount,numReagentMakable)
 | 
| 
contrebasse@111
 | 
   123 
 | 
| 
contrebasse@111
 | 
   124 	-- take into account that some recipe craft more than one item
 | 
| 
contrebasse@111
 | 
   125 	-- use the mean between min and max, but make at least one...
 | 
| 
contrebasse@111
 | 
   126 	if not minMade then
 | 
| 
contrebasse@111
 | 
   127 		minMade = 1
 | 
| 
contrebasse@111
 | 
   128 	elseif minMade<1 then
 | 
| 
contrebasse@111
 | 
   129 		-- from the percentage, compute the mean number of crafts to make
 | 
| 
contrebasse@111
 | 
   130 		minMade = 1/minMade
 | 
| 
contrebasse@111
 | 
   131 	end
 | 
| 
contrebasse@111
 | 
   132 	if not maxMade then
 | 
| 
contrebasse@111
 | 
   133 		maxMade = minMade
 | 
| 
contrebasse@111
 | 
   134 	end
 | 
| 
contrebasse@111
 | 
   135 	numToMake = max(floor(2*numToMake/(maxMade+minMade)),1)
 | 
| 
contrebasse@111
 | 
   136 	return numToMake
 | 
| 
contrebasse@111
 | 
   137 end
 | 
| 
contrebasse@111
 | 
   138 
 | 
| 
contrebasse@111
 | 
   139 -- function used after choosing the number of reagent to craft
 | 
| 
contrebasse@111
 | 
   140 function A.SplitStack(owner,split)
 | 
| 
contrebasse@111
 | 
   141 	A.DoCraft(owner.ReagentMaker_reagentID,owner.ReagentMaker_recipeData,split)
 | 
| 
contrebasse@111
 | 
   142 	owner.ReagentMaker_reagentID = nil
 | 
| 
contrebasse@111
 | 
   143 	owner.ReagentMaker_recipeData = nil
 | 
| 
contrebasse@111
 | 
   144 end
 | 
| 
contrebasse@111
 | 
   145 
 | 
| 
contrebasse@111
 | 
   146 -- Find the recipe and do the crafting
 | 
| 
contrebasse@111
 | 
   147 function A.DoCraft(reagentID,recipeData,numToMake)
 | 
| 
contrebasse@111
 | 
   148 	-- Remove filters
 | 
| 
contrebasse@111
 | 
   149 	A.SaveActiveFilters(recipeData.header)
 | 
| 
contrebasse@111
 | 
   150 
 | 
| 
contrebasse@111
 | 
   151 	-- Find recipe index
 | 
| 
contrebasse@119
 | 
   152 	local reagentIndex = A.findExactSkillIndex(reagentID,recipeData.spellLink)
 | 
| 
contrebasse@111
 | 
   153 
 | 
| 
contrebasse@111
 | 
   154 	-- Error if not found
 | 
| 
contrebasse@111
 | 
   155 	if not reagentIndex then
 | 
| 
contrebasse@111
 | 
   156 		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
 | 
   157 		A.RestoreActiveFilters()
 | 
| 
contrebasse@111
 | 
   158 		return
 | 
| 
contrebasse@111
 | 
   159 	end
 | 
| 
contrebasse@111
 | 
   160 
 | 
| 
contrebasse@111
 | 
   161 	-- Craft the item, finally !
 | 
| 
contrebasse@111
 | 
   162 	DoTradeSkill(reagentIndex,numToMake)
 | 
| 
contrebasse@111
 | 
   163 
 | 
| 
contrebasse@111
 | 
   164 	-- Restore Filters
 | 
| 
contrebasse@111
 | 
   165 	A.RestoreActiveFilters()
 | 
| 
contrebasse@111
 | 
   166 end
 |