| 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 |