view ReagentMaker.lua @ 96:e3147b41ea9d v1.0beta9

Correct display, tooltips and error message when there are actual tradeskill spells in the SecureMenu. Still not sure that it works with enough reagents...
author contrebasse
date Fri, 20 May 2011 00:53:42 +0200
parents c369a2e16ab6
children b980c00affcd
line wrap: on
line source
local addonName, A = ...

-- @todo clean the A table
-- @todo check local copy of globals functions
-- @todo add support for dez ?
-- @todo add support for hidden recipes, removing filtering
-- @todo add support for cross tradeskill, like mining + forge/ingé
-- @todo when a reagent can not be crafted and the recipe has many reagents, do like ReverseEngeneering and go to this recipe (with a one step return button)
-- @todo scroll to the selected recipe on opening (usefull also for the previous todo)
-- @todo shift+clic on a reagent name while the serachbar is focused fills the serachbar with the reagent name (idem with the crafted item)
-- @todo add a button to clear search
-- @todo add a button to cast a campfire when coocking

---------------------------------------------------
-- Variables
---------------------------------------------------
-- Used by findglobals
-- GLOBALS: _G, CreateFrame, DEFAULT_CHAT_FRAME

-- Lua functions

-- Wow functions

-- constant vars

---------------------------------------------------
-- Manage events
---------------------------------------------------
A.EventsFrame = CreateFrame("Frame")

local SCAN_DELAY = 0.2
local t_throttle = SCAN_DELAY
local function throttleScan(self, t_elapsed)
	t_throttle = t_throttle - t_elapsed
	if t_throttle<0 then
		self:SetScript("OnUpdate", nil)

		-- Close the external window if the tradeskill changed
		if A.currentTradeSkill ~= GetTradeSkillLine() then
			A.MenuFrame:Hide()
		end
		if IsTradeSkillGuild() or IsTradeSkillLinked() then
			A.MenuFrame:Hide()
			return
		end

		-- Scan availabe recipes
		-- Rescan in case of problem
		if not A:ScanSimpleRecipes() then
			t_throttle = SCAN_DELAY
			self:SetScript("OnUpdate", throttleScan)
		end

		-- Show makables reagents
		A.updateCounts(GetTradeSkillSelectionIndex())
	end
end
A.EventsFrame:SetScript("OnEvent", function(self, event)
	if event == "TRADE_SKILL_UPDATE" then
		t_throttle = SCAN_DELAY
		self:SetScript("OnUpdate", throttleScan)

	elseif event == "TRADE_SKILL_SHOW" then
		A:Initialize()
		A.EventsFrame:UnregisterEvent("TRADE_SKILL_SHOW")
	end -- if
end) -- function
A.EventsFrame:RegisterEvent("TRADE_SKILL_SHOW")
A.EventsFrame:RegisterEvent("TRADE_SKILL_UPDATE")

---------------------------------------------------
-- Initialize
---------------------------------------------------
function A:Initialize()

	-- Register clics on reagent's buttons
	for i=1,7 do
		local btn = _G["TradeSkillReagent"..i]
		btn:HookScript("OnDoubleClick", A.ProcessReagent)
		btn:HookScript("OnEnter", A.btnEntered)
		btn:HookScript("OnLeave", A.btnLeft)
		btn.SplitStack = A.SplitStack

		local textureHighlight = btn:CreateTexture()
		textureHighlight:Hide()
		textureHighlight:SetTexture("Interface\\BUTTONS\\CheckButtonHilight")
		textureHighlight:SetBlendMode("ADD")
		textureHighlight:SetAllPoints("TradeSkillReagent"..i.."IconTexture")
		btn.textureHighlight = textureHighlight

		local label = btn:CreateFontString(nil,"ARTWORK","GameFontHighlight")
		label:SetSize(100,20)
		label:SetPoint("TOPLEFT",btn,"TOPLEFT",4,-4)
		label:SetJustifyH("LEFT")
		label:SetJustifyV("TOP")
		label:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE")
		btn.label = label
	end -- for

	-- Secondary Tooltip
	A.tooltipRecipe = CreateFrame("GameTooltip", "ReagentMaker_tooltipRecipe",UIParent, "GameTooltipTemplate")
	A.tooltipRecipe:SetFrameStrata("TOOLTIP")
	A.tooltipRecipe:Hide()
	
	-- Button for enchanting directy on a scroll
	A.LoadEnchantOnScroll()
end -- function

-- Function run after selecting a item in the tradeskill window
function A.ProcessReagent(btn, ...)

	-- Do not manage guild 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 reagentRecipeIndex = A.buttonNumber(btn)

	-- ID of the reagent we want to craft
	local recipeIndex = GetTradeSkillSelectionIndex()
	local reagentID = A.link2ID(GetTradeSkillReagentItemLink(recipeIndex, reagentRecipeIndex))

	-- 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, use it
	if #(A.data[reagentID]) == 1 and not A.data[reagentID][1].macro then
		if A.data[reagentID][1].spellName and A.data[reagentID][1].spellName ~= 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

		local numMakable, reagentIndex = A.numMakable(reagentID)

		-- Try to show the recipe by removing filters once if it was not found
		if not reagentIndex then
			A.SaveActiveFilters(A.data[reagentID][1].header)
			numMakable, reagentIndex = A.numMakable(reagentID)
		end

		if not numMakable 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."])
			return
		end
		if numMakable>0 then
			A.craft(recipeIndex,reagentRecipeIndex,reagentIndex,numMakable,chooseNumberToCraft)
			return
		end

		-- If we can make the item needed to make the reagent, open a window to make it
		-- one step recursion, enables to mill to create an ink
		if A.data[reagentID][1][1] and A.data[A.data[reagentID][1][1]] then
			if A.externalCraftWindow(A.data[reagentID][1][1],reagentID) ~= false then
				return
			end
		end

		A.Error(A.L["You do not have enough reagents to craft [%s]"]:format(GetItemInfo(reagentID) or "item #"..reagentID))
		return
	else
		A.externalCraftWindow(reagentID)
	end -- if
	--A.RestoreActiveFilters()
end -- function


---------------------------------------------------
-- Craft items
---------------------------------------------------
-- function used after choosing the number of reagent to craft
function A.SplitStack(owner,split)
	DoTradeSkill(owner.ReagentMaker_reagentIndex,tonumber(split))
	owner.ReagentMaker_reagentIndex = nil
end

-- Craft the reagent of an item, given it's position in the recipe
function A.craft(recipeIndex,reagentRecipeIndex,reagentIndex,numReagentMakable,chooseNumber)
	-- Look at how many we need to make one item for the selected recipe
	local numToMake = 1
	local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipeIndex, reagentRecipeIndex)
	-- make enough reagents to craft one more item
	numToMake = math.min(math.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...
	local minMade, maxMade = GetTradeSkillNumMade(reagentIndex)
	numToMake = math.max(math.floor(2*numToMake/(maxMade+minMade)),1)
	
	-- Choose number or craft directly
	if chooseNumber then
		-- the dialog window is linked to the reagent button
		local btn = _G["TradeSkillReagent"..reagentRecipeIndex]

		-- Store info to be able to run the function later
		btn.ReagentMaker_reagentIndex = reagentIndex

		-- Open dialog
		OpenStackSplitFrame(numReagentMakable, 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 tha the entered value will be erased on text entry
	else
		DoTradeSkill(reagentIndex,numToMake)
	end -- if
end -- function


-- Button hovering
function A.btnEntered(btn)
	-- Do not manage guild tradeskill
	if IsTradeSkillGuild() or IsTradeSkillLinked() then return end

	-- Index of the reagent in the recipe, taken from the button name
	local reagentRecipeIndex = A.buttonNumber(btn)

	-- ID of the reagent we want to craft
	local reagentLink = GetTradeSkillReagentItemLink(GetTradeSkillSelectionIndex(), reagentRecipeIndex)
	local reagentID = A.link2ID(reagentLink)

	-- Continue only if the reagent is known
	if not reagentID or not A.data[reagentID] then return end

	btn.textureHighlight:Show()

	-- Check if the item is made by only one recipe. If not, return
	if not A.isRecipeUnique(A.data[reagentID]) then return end

	-- Tooltips
	local link = A.data[reagentID][1].spellLink
	if link then
		A.tooltipRecipe:SetOwner(btn)
		A.tooltipRecipe:SetHyperlink(link)
		A.tooltipRecipe:Show()
		A.tooltipRecipe:ClearAllPoints()
		A.tooltipRecipe:SetPoint("BOTTOMLEFT",GameTooltip,"BOTTOMRIGHT")
	end
end

function A.btnLeft(btn)
	btn.textureHighlight:Hide()
	A.tooltipRecipe:Hide()
end -- function

function A.updateCounts(recipeIndex)
	-- Needs an argument
	if not recipeIndex then return end

	-- Do not manage guild tradeskill
	if IsTradeSkillGuild() or IsTradeSkillLinked() then
		for reagentRecipeIndex = 1,GetTradeSkillNumReagents(recipeIndex) do
			-- If the normal tradeskill hasn't been opened yet, the field 'label' doesn't exists yet
			local label = _G["TradeSkillReagent"..reagentRecipeIndex].label
			if label then
				label:Hide()
			end
		end
		return
	end

	-- Count makable items and show it
	for reagentRecipeIndex = 1,GetTradeSkillNumReagents(recipeIndex) do
		-- ID of the reagent we want to craft
		local reagentLink = GetTradeSkillReagentItemLink(recipeIndex, reagentRecipeIndex)
		local reagentID = A.link2ID(reagentLink)

		local label = _G["TradeSkillReagent"..reagentRecipeIndex].label
		if not label then break end -- Shouldn't happen...

		-- Continue only if the reagent is known
		if not reagentID or not A.data[reagentID] then
			label:Hide()
		else
			-- Count and show
			local numMakable = A.numMakable(reagentID)
			if not numMakable or #(A.data[reagentID]) ~= 1 or A.data[reagentID][1].macro then
				label:SetText("?")
				label:SetTextColor(0, 0.5, 1, 1) -- blue
			else
				label:SetText(numMakable)
				if numMakable==0 then
					label:SetTextColor(1, 0, 0, 1) -- red
				else
					label:SetTextColor(0, 1, 0, 1) -- green
				end
			end -- if
			label:Show()
		end -- if
	end -- for
end -- function
hooksecurefunc("SelectTradeSkill",A.updateCounts)