contrebasse@98: local addonName, A = ... contrebasse@98: contrebasse@98: -- @todo clean the A table contrebasse@98: -- @todo check local copy of globals functions contrebasse@98: -- @todo add support for dez ? contrebasse@98: -- @todo add support for hidden recipes, removing filtering contrebasse@98: -- @todo add support for cross tradeskill, like mining + forge/ingé contrebasse@98: -- @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) contrebasse@98: -- @todo scroll to the selected recipe on opening (usefull also for the previous todo) contrebasse@98: -- @todo shift+clic on a reagent name while the serachbar is focused fills the serachbar with the reagent name (idem with the crafted item) contrebasse@98: -- @todo add a button to clear search contrebasse@98: -- @todo add a button to cast a campfire when coocking contrebasse@98: contrebasse@98: --------------------------------------------------- contrebasse@98: -- Variables contrebasse@98: --------------------------------------------------- contrebasse@98: -- Used by findglobals contrebasse@98: -- GLOBALS: _G, CreateFrame, DEFAULT_CHAT_FRAME contrebasse@98: contrebasse@98: -- Lua functions contrebasse@98: contrebasse@98: -- Wow functions contrebasse@98: contrebasse@98: -- constant vars contrebasse@98: contrebasse@98: --------------------------------------------------- contrebasse@98: -- Manage events contrebasse@98: --------------------------------------------------- contrebasse@98: A.EventsFrame = CreateFrame("Frame") contrebasse@98: contrebasse@98: local SCAN_DELAY = 0.2 contrebasse@98: local t_throttle = SCAN_DELAY contrebasse@98: local function throttleScan(self, t_elapsed) contrebasse@98: t_throttle = t_throttle - t_elapsed contrebasse@98: if t_throttle<0 then contrebasse@98: self:SetScript("OnUpdate", nil) contrebasse@98: contrebasse@98: -- Close the external window if the tradeskill changed contrebasse@98: if A.currentTradeSkill ~= GetTradeSkillLine() then contrebasse@98: A.MenuFrame:Hide() contrebasse@98: end contrebasse@98: if IsTradeSkillGuild() or IsTradeSkillLinked() then contrebasse@98: A.MenuFrame:Hide() contrebasse@98: return contrebasse@98: end contrebasse@98: contrebasse@98: -- Scan availabe recipes contrebasse@98: -- Rescan in case of problem contrebasse@98: if not A:ScanSimpleRecipes() then contrebasse@98: t_throttle = SCAN_DELAY contrebasse@98: self:SetScript("OnUpdate", throttleScan) contrebasse@98: end contrebasse@98: contrebasse@98: -- Show makables reagents contrebasse@98: A.updateCounts(GetTradeSkillSelectionIndex()) contrebasse@98: end contrebasse@98: end contrebasse@98: A.EventsFrame:SetScript("OnEvent", function(self, event) contrebasse@98: A.ManageCampFireBtn() contrebasse@98: if event == "TRADE_SKILL_UPDATE" then contrebasse@98: t_throttle = SCAN_DELAY contrebasse@98: self:SetScript("OnUpdate", throttleScan) contrebasse@98: contrebasse@98: elseif event == "TRADE_SKILL_SHOW" then contrebasse@98: A:Initialize() contrebasse@98: A.EventsFrame:UnregisterEvent("TRADE_SKILL_SHOW") contrebasse@98: end -- if contrebasse@98: end) -- function contrebasse@98: A.EventsFrame:RegisterEvent("TRADE_SKILL_SHOW") contrebasse@98: A.EventsFrame:RegisterEvent("TRADE_SKILL_UPDATE") contrebasse@98: A.EventsFrame:RegisterEvent("PLAYER_REGEN_ENABLED") contrebasse@98: A.EventsFrame:RegisterEvent("PLAYER_REGEN_DISABLED") contrebasse@98: contrebasse@98: --------------------------------------------------- contrebasse@98: -- Initialize contrebasse@98: --------------------------------------------------- contrebasse@98: function A:Initialize() contrebasse@98: contrebasse@98: -- Register clics on reagent's buttons contrebasse@98: for i=1,7 do contrebasse@98: local btn = _G["TradeSkillReagent"..i] contrebasse@98: btn:HookScript("OnDoubleClick", A.ProcessReagent) contrebasse@98: btn:HookScript("OnEnter", A.btnEntered) contrebasse@98: btn:HookScript("OnLeave", A.btnLeft) contrebasse@98: btn.SplitStack = A.SplitStack contrebasse@98: contrebasse@98: local textureHighlight = btn:CreateTexture() contrebasse@98: textureHighlight:Hide() contrebasse@98: textureHighlight:SetTexture("Interface\\BUTTONS\\CheckButtonHilight") contrebasse@98: textureHighlight:SetBlendMode("ADD") contrebasse@98: textureHighlight:SetAllPoints("TradeSkillReagent"..i.."IconTexture") contrebasse@98: btn.textureHighlight = textureHighlight contrebasse@98: contrebasse@98: local label = btn:CreateFontString(nil,"ARTWORK","GameFontHighlight") contrebasse@98: label:SetSize(100,20) contrebasse@98: label:SetPoint("TOPLEFT",btn,"TOPLEFT",4,-4) contrebasse@98: label:SetJustifyH("LEFT") contrebasse@98: label:SetJustifyV("TOP") contrebasse@98: label:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE") contrebasse@98: btn.label = label contrebasse@98: end -- for contrebasse@98: contrebasse@98: -- Secondary Tooltip contrebasse@98: A.tooltipRecipe = CreateFrame("GameTooltip", "ReagentMaker_tooltipRecipe",UIParent, "GameTooltipTemplate") contrebasse@98: A.tooltipRecipe:SetFrameStrata("TOOLTIP") contrebasse@98: A.tooltipRecipe:Hide() contrebasse@98: contrebasse@98: -- Button for enchanting directy on a scroll contrebasse@98: A.LoadEnchantOnScroll() contrebasse@98: contrebasse@98: -- Button to cast a campfire contrebasse@98: A.InitialiseCampFireBtn() contrebasse@98: end -- function contrebasse@98: contrebasse@98: -- Function run after selecting a item in the tradeskill window contrebasse@98: function A.ProcessReagent(btn, ...) contrebasse@98: contrebasse@98: -- Do not manage guild tradeskill contrebasse@98: if IsTradeSkillGuild() or IsTradeSkillLinked() then return end contrebasse@98: contrebasse@98: -- We want no modifiers, or shift to choose the number of reagent to craft contrebasse@98: if IsModifierKeyDown() and not IsShiftKeyDown() then return end contrebasse@98: local chooseNumberToCraft = IsShiftKeyDown() contrebasse@98: contrebasse@98: -- Index of the reagent in the recipe, taken from the button name contrebasse@98: local reagentRecipeIndex = A.buttonNumber(btn) contrebasse@98: contrebasse@98: -- ID of the reagent we want to craft contrebasse@98: local recipeIndex = GetTradeSkillSelectionIndex() contrebasse@98: local reagentID = A.link2ID(GetTradeSkillReagentItemLink(recipeIndex, reagentRecipeIndex)) contrebasse@98: contrebasse@98: -- Continue only if the reagent is known contrebasse@98: if not reagentID or not A.data[reagentID] then return end contrebasse@98: contrebasse@98: -- If only one recipe is known for the reagent, use it contrebasse@98: if #(A.data[reagentID]) == 1 and not A.data[reagentID][1].macro then contrebasse@98: if A.data[reagentID][1].spellName and A.data[reagentID][1].spellName ~= GetTradeSkillLine() then contrebasse@98: A.Error(A.L["The recipe to make this reagent is in another tradeskill. Currently ReagentMaker can not manage such a case, sorry."]) contrebasse@98: return contrebasse@98: end contrebasse@98: contrebasse@98: local numMakable, reagentIndex = A.numMakable(reagentID) contrebasse@98: contrebasse@98: -- Try to show the recipe by removing filters once if it was not found contrebasse@98: if not reagentIndex then contrebasse@98: A.SaveActiveFilters(A.data[reagentID][1].header) contrebasse@98: numMakable, reagentIndex = A.numMakable(reagentID) contrebasse@98: end contrebasse@98: contrebasse@98: if not numMakable then contrebasse@98: 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@98: return contrebasse@98: end contrebasse@98: if numMakable>0 then contrebasse@98: A.craft(recipeIndex,reagentRecipeIndex,reagentIndex,numMakable,chooseNumberToCraft) contrebasse@98: return contrebasse@98: end contrebasse@98: contrebasse@98: -- If we can make the item needed to make the reagent, open a window to make it contrebasse@98: -- one step recursion, enables to mill to create an ink contrebasse@98: if A.data[reagentID][1][1] and A.data[A.data[reagentID][1][1]] then contrebasse@98: if A.externalCraftWindow(A.data[reagentID][1][1],reagentID) ~= false then contrebasse@98: return contrebasse@98: end contrebasse@98: end contrebasse@98: contrebasse@98: A.Error(A.L["You do not have enough reagents to craft [%s]"]:format(GetItemInfo(reagentID) or "item #"..reagentID)) contrebasse@98: return contrebasse@98: else contrebasse@98: A.externalCraftWindow(reagentID) contrebasse@98: end -- if contrebasse@98: --A.RestoreActiveFilters() contrebasse@98: end -- function contrebasse@98: contrebasse@98: contrebasse@98: --------------------------------------------------- contrebasse@98: -- Craft items contrebasse@98: --------------------------------------------------- contrebasse@98: -- function used after choosing the number of reagent to craft contrebasse@98: function A.SplitStack(owner,split) contrebasse@98: DoTradeSkill(owner.ReagentMaker_reagentIndex,tonumber(split)) contrebasse@98: owner.ReagentMaker_reagentIndex = nil contrebasse@98: end contrebasse@98: contrebasse@98: -- Craft the reagent of an item, given it's position in the recipe contrebasse@98: function A.craft(recipeIndex,reagentRecipeIndex,reagentIndex,numReagentMakable,chooseNumber) contrebasse@98: -- Look at how many we need to make one item for the selected recipe contrebasse@98: local numToMake = 1 contrebasse@98: local _, _, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipeIndex, reagentRecipeIndex) contrebasse@98: -- make enough reagents to craft one more item contrebasse@98: numToMake = math.min(math.floor(playerReagentCount/reagentCount+1)*reagentCount-playerReagentCount,numReagentMakable) contrebasse@98: contrebasse@98: -- take into account that some recipe craft more than one item contrebasse@98: -- use the mean between min and max, but make at least one... contrebasse@98: local minMade, maxMade = GetTradeSkillNumMade(reagentIndex) contrebasse@98: numToMake = math.max(math.floor(2*numToMake/(maxMade+minMade)),1) contrebasse@98: contrebasse@98: -- Choose number or craft directly contrebasse@98: if chooseNumber then contrebasse@98: -- the dialog window is linked to the reagent button contrebasse@98: local btn = _G["TradeSkillReagent"..reagentRecipeIndex] contrebasse@98: contrebasse@98: -- Store info to be able to run the function later contrebasse@98: btn.ReagentMaker_reagentIndex = reagentIndex contrebasse@98: contrebasse@98: -- Open dialog contrebasse@98: OpenStackSplitFrame(numReagentMakable, btn, "TOP", "BOTTOM") contrebasse@98: contrebasse@98: -- Fill in the number to make contrebasse@98: numToMake = tostring(numToMake) contrebasse@98: for i = 1,numToMake:len() do contrebasse@98: StackSplitFrame_OnChar(StackSplitFrame,numToMake:gsub(i,i)) contrebasse@98: end contrebasse@98: StackSplitFrame.typing = 0 -- reinit the frame so tha the entered value will be erased on text entry contrebasse@98: else contrebasse@98: DoTradeSkill(reagentIndex,numToMake) contrebasse@98: end -- if contrebasse@98: end -- function contrebasse@98: contrebasse@98: contrebasse@98: -- Button hovering contrebasse@98: function A.btnEntered(btn) contrebasse@98: -- Do not manage guild tradeskill contrebasse@98: if IsTradeSkillGuild() or IsTradeSkillLinked() then return end contrebasse@98: contrebasse@98: -- Index of the reagent in the recipe, taken from the button name contrebasse@98: local reagentRecipeIndex = A.buttonNumber(btn) contrebasse@98: contrebasse@98: -- ID of the reagent we want to craft contrebasse@98: local reagentLink = GetTradeSkillReagentItemLink(GetTradeSkillSelectionIndex(), reagentRecipeIndex) contrebasse@98: local reagentID = A.link2ID(reagentLink) contrebasse@98: contrebasse@98: -- Continue only if the reagent is known contrebasse@98: if not reagentID or not A.data[reagentID] then return end contrebasse@98: contrebasse@98: btn.textureHighlight:Show() contrebasse@98: contrebasse@98: -- Check if the item is made by only one recipe. If not, return contrebasse@98: if not A.isRecipeUnique(A.data[reagentID]) then return end contrebasse@98: contrebasse@98: -- Tooltips contrebasse@98: local link = A.data[reagentID][1].spellLink contrebasse@98: if link then contrebasse@98: A.tooltipRecipe:SetOwner(btn) contrebasse@98: A.tooltipRecipe:SetHyperlink(link) contrebasse@98: A.tooltipRecipe:Show() contrebasse@98: A.tooltipRecipe:ClearAllPoints() contrebasse@98: A.tooltipRecipe:SetPoint("BOTTOMLEFT",GameTooltip,"BOTTOMRIGHT") contrebasse@98: end contrebasse@98: end contrebasse@98: contrebasse@98: function A.btnLeft(btn) contrebasse@98: btn.textureHighlight:Hide() contrebasse@98: A.tooltipRecipe:Hide() contrebasse@98: end -- function contrebasse@98: contrebasse@98: function A.updateCounts(recipeIndex) contrebasse@98: -- Needs an argument contrebasse@98: if not recipeIndex then return end contrebasse@98: contrebasse@98: -- Do not manage guild tradeskill contrebasse@98: if IsTradeSkillGuild() or IsTradeSkillLinked() then contrebasse@98: for reagentRecipeIndex = 1,GetTradeSkillNumReagents(recipeIndex) do contrebasse@98: -- If the normal tradeskill hasn't been opened yet, the field 'label' doesn't exists yet contrebasse@98: local label = _G["TradeSkillReagent"..reagentRecipeIndex].label contrebasse@98: if label then contrebasse@98: label:Hide() contrebasse@98: end contrebasse@98: end contrebasse@98: return contrebasse@98: end contrebasse@98: contrebasse@98: -- Count makable items and show it contrebasse@98: for reagentRecipeIndex = 1,GetTradeSkillNumReagents(recipeIndex) do contrebasse@98: -- ID of the reagent we want to craft contrebasse@98: local reagentLink = GetTradeSkillReagentItemLink(recipeIndex, reagentRecipeIndex) contrebasse@98: local reagentID = A.link2ID(reagentLink) contrebasse@98: contrebasse@98: local label = _G["TradeSkillReagent"..reagentRecipeIndex].label contrebasse@98: if not label then break end -- Shouldn't happen... contrebasse@98: contrebasse@98: -- Continue only if the reagent is known contrebasse@98: if not reagentID or not A.data[reagentID] then contrebasse@98: label:Hide() contrebasse@98: else contrebasse@98: -- Count and show contrebasse@98: local numMakable = A.numMakable(reagentID) contrebasse@98: if not numMakable or #(A.data[reagentID]) ~= 1 or A.data[reagentID][1].macro then contrebasse@98: label:SetText("?") contrebasse@98: label:SetTextColor(0, 0.5, 1, 1) -- blue contrebasse@98: else contrebasse@98: label:SetText(numMakable) contrebasse@98: if numMakable==0 then contrebasse@98: label:SetTextColor(1, 0, 0, 1) -- red contrebasse@98: else contrebasse@98: label:SetTextColor(0, 1, 0, 1) -- green contrebasse@98: end contrebasse@98: end -- if contrebasse@98: label:Show() contrebasse@98: end -- if contrebasse@98: end -- for contrebasse@98: end -- function contrebasse@98: hooksecurefunc("SelectTradeSkill",A.updateCounts)