diff Craft.lua @ 111:af23986010ef v1.1beta0

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