| 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 	--A.RestoreActiveFilters() | 
| contrebasse@111 | 59 end -- function | 
| contrebasse@111 | 60 | 
| contrebasse@111 | 61 -- Launch the procedure for a standard recipe | 
| contrebasse@111 | 62 -- Can be called from the external window | 
| contrebasse@111 | 63 function A.CraftItemWithRecipe(recipeIndex,reagentID,recipeData,reagentIndexInRecipe,chooseNumberToCraft,btn) | 
| contrebasse@111 | 64 	-- Check that it's the same tradeskill | 
| contrebasse@111 | 65 	if recipeData.tradeskillName ~= GetTradeSkillLine() then | 
| contrebasse@111 | 66 		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 | 67 		return | 
| contrebasse@111 | 68 	end | 
| contrebasse@111 | 69 | 
| contrebasse@111 | 70 	-- Check how many times the recipe is makable | 
| contrebasse@111 | 71 	local numMakable = A.numRecipeMakable(recipeData[1],recipeData[2]) | 
| contrebasse@111 | 72 	if not numMakable then | 
| contrebasse@111 | 73 		A.Error(SPELL_FAILED_ERROR) | 
| contrebasse@111 | 74 		return | 
| contrebasse@111 | 75 	end | 
| contrebasse@111 | 76 | 
| contrebasse@111 | 77 	if numMakable<=0 then | 
| contrebasse@111 | 78 		-- If not makable, try a one-step recursion | 
| contrebasse@111 | 79 		-- enables e.g. to mill to create an ink | 
| contrebasse@111 | 80 		-- need a unique reagent | 
| contrebasse@111 | 81 		if recipeData[1] and A.data[recipeData[1]] then | 
| contrebasse@111 | 82 			if A.externalCraftWindow(recipeData[1],reagentIndexInRecipe,reagentID) ~= false then | 
| contrebasse@111 | 83 				-- there was no problem opening the external window | 
| contrebasse@111 | 84 				return | 
| contrebasse@111 | 85 			end | 
| contrebasse@111 | 86 		end | 
| contrebasse@111 | 87 | 
| contrebasse@111 | 88 		-- There isn't enough reagents | 
| contrebasse@111 | 89 		--@todo include name of reagent if unique | 
| contrebasse@111 | 90 		A.Error(A.L["You do not have enough reagents to craft [%s]"]:format(GetItemInfo(reagentID) or "item #"..reagentID)) | 
| contrebasse@111 | 91 		return | 
| contrebasse@111 | 92 	end | 
| contrebasse@111 | 93 | 
| contrebasse@111 | 94 	-- Optimal number of items to craft | 
| contrebasse@111 | 95 	local numToMake = A.numToMake(recipeIndex, reagentIndexInRecipe,numMakable, recipeData[3], recipeData[4]) | 
| contrebasse@111 | 96 | 
| contrebasse@111 | 97 	-- Choose number or craft directly | 
| contrebasse@111 | 98 	if chooseNumberToCraft then | 
| contrebasse@111 | 99 		-- Store info to be able to run the function later | 
| contrebasse@111 | 100 		btn.ReagentMaker_reagentID = reagentID | 
| contrebasse@111 | 101 		btn.ReagentMaker_recipeData = recipeData | 
| contrebasse@111 | 102 | 
| contrebasse@111 | 103 		-- Open dialog | 
| contrebasse@111 | 104 		OpenStackSplitFrame(numMakable, btn, "TOP", "BOTTOM") | 
| contrebasse@111 | 105 | 
| contrebasse@111 | 106 		-- Fill in the number to make | 
| contrebasse@111 | 107 		numToMake = tostring(numToMake) | 
| contrebasse@111 | 108 		for i = 1,numToMake:len() do | 
| contrebasse@111 | 109 			StackSplitFrame_OnChar(StackSplitFrame,numToMake:gsub(i,i)) | 
| contrebasse@111 | 110 		end | 
| contrebasse@111 | 111 		StackSplitFrame.typing = 0 -- reinit the frame so that the entered value will be erased on text entry | 
| contrebasse@111 | 112 	else | 
| contrebasse@111 | 113 		A.DoCraft(reagentID,recipeData,numToMake) | 
| contrebasse@111 | 114 	end -- if | 
| contrebasse@111 | 115 end | 
| contrebasse@111 | 116 | 
| contrebasse@111 | 117 -- Compute optimal number of items to craft | 
| contrebasse@111 | 118 function A.numToMake(recipeIndex, reagentIndexInRecipe,numReagentMakable,minMade,maxMade) | 
| contrebasse@111 | 119 	-- Look at how many we need to make one item for the selected recipe | 
| contrebasse@111 | 120 	local numToMake = 1 | 
| contrebasse@111 | 121 	local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipeIndex, reagentIndexInRecipe) | 
| contrebasse@111 | 122 	-- make enough reagents to craft one more item | 
| contrebasse@111 | 123 	numToMake = min(floor(playerReagentCount/reagentCount+1)*reagentCount-playerReagentCount,numReagentMakable) | 
| contrebasse@111 | 124 | 
| contrebasse@111 | 125 	-- take into account that some recipe craft more than one item | 
| contrebasse@111 | 126 	-- use the mean between min and max, but make at least one... | 
| contrebasse@111 | 127 	if not minMade then | 
| contrebasse@111 | 128 		minMade = 1 | 
| contrebasse@111 | 129 	elseif minMade<1 then | 
| contrebasse@111 | 130 		-- from the percentage, compute the mean number of crafts to make | 
| contrebasse@111 | 131 		minMade = 1/minMade | 
| contrebasse@111 | 132 	end | 
| contrebasse@111 | 133 	if not maxMade then | 
| contrebasse@111 | 134 		maxMade = minMade | 
| contrebasse@111 | 135 	end | 
| contrebasse@111 | 136 	numToMake = max(floor(2*numToMake/(maxMade+minMade)),1) | 
| contrebasse@111 | 137 	return numToMake | 
| contrebasse@111 | 138 end | 
| contrebasse@111 | 139 | 
| contrebasse@111 | 140 -- function used after choosing the number of reagent to craft | 
| contrebasse@111 | 141 function A.SplitStack(owner,split) | 
| contrebasse@111 | 142 	A.DoCraft(owner.ReagentMaker_reagentID,owner.ReagentMaker_recipeData,split) | 
| contrebasse@111 | 143 	owner.ReagentMaker_reagentID = nil | 
| contrebasse@111 | 144 	owner.ReagentMaker_recipeData = nil | 
| contrebasse@111 | 145 end | 
| contrebasse@111 | 146 | 
| contrebasse@111 | 147 -- Find the recipe and do the crafting | 
| contrebasse@111 | 148 function A.DoCraft(reagentID,recipeData,numToMake) | 
| contrebasse@111 | 149 	-- Remove filters | 
| contrebasse@111 | 150 	A.SaveActiveFilters(recipeData.header) | 
| contrebasse@111 | 151 | 
| contrebasse@111 | 152 	-- Find recipe index | 
| contrebasse@111 | 153 	local reagentIndex = A.findExactSkillIndex(reagentID,recipeData.spellLink) -- finds only the first recipe that creates the reagent, should check recipe name too | 
| contrebasse@111 | 154 | 
| contrebasse@111 | 155 	-- Error if not found | 
| contrebasse@111 | 156 	if not reagentIndex then | 
| contrebasse@111 | 157 		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 | 158 		A.RestoreActiveFilters() | 
| contrebasse@111 | 159 		return | 
| contrebasse@111 | 160 	end | 
| contrebasse@111 | 161 | 
| contrebasse@111 | 162 	-- Craft the item, finally ! | 
| contrebasse@111 | 163 	DoTradeSkill(reagentIndex,numToMake) | 
| contrebasse@111 | 164 | 
| contrebasse@111 | 165 	-- Restore Filters | 
| contrebasse@111 | 166 	A.RestoreActiveFilters() | 
| contrebasse@111 | 167 end |