-- ============================================================================ -- TTCraftAddict.lua -- -- Copyright (c) Matthew Johnson. All rights reserved. -- -- This work may be freely adapted and distributed as long as this notice remains intact. -- This work may NOT be (re)sold or included in any compilations that are (re)sold. -- -- ============================================================================ -- ============================================================================ -- Object definitions. -- ============================================================================ TTCA_Item = { Name = nil, Type = nil, Level = nil, Id = nil, ReagentId = nil, Texture = nil, NumAvailable = nil, NumRequired = nil, New = function (self) obj = {}; setmetatable(obj, self); self.__index = self; return obj; end, }; -- ============================================================================ -- Global variables. -- ============================================================================ local Pre_TTCA_TradeSkillFrame_SetSelection = nil; local Pre_TTCA_CraftFrame_SetSelection = nil; -- The list of items in the build tree. local vTTCA_BuildTree = nil; -- The list of raw materials needed to build the selected item. local vTTCA_MaterialList = nil; -- The list of items need to be made to build the selected item. local vTTCA_ConstructionList = nil; -- The list of tools needed to build the selected item. local vTTCA_ToolList = nil; -- The currently active tab. local vTTCA_ActiveTab = nil -- Flag to determine if we are currently building the tree. local vfTTCA_BuildingTree = false; -- Flag to determine if we should watch for a bag update so we know when to -- build the next item. local vfTTCA_WatchForBagUpdate = false; -- ============================================================================ -- Global defines. -- ============================================================================ TTCA_LISTITEMS_VISIBLE = 15; TTCA_LISTITEM_HEIGHT = 22; TTCA_LISTITEM_WIDTH = 300; TTCA_LISTITEM_INDENT = 15; TTCA_TAB_BUILDTREE = 1; TTCA_TAB_MATERIALS = 2; local TTCA_TypeColor = { ["optimal"] = { r = 1.00, g = 0.50, b = 0.25 }, ["medium"] = { r = 1.00, g = 1.00, b = 0.00 }, ["easy"] = { r = 0.25, g = 0.75, b = 0.25 }, ["trivial"] = { r = 0.50, g = 0.50, b = 0.50 }, ["reagent"] = { r = 0.50, g = 0.50, b = 0.50 }, ["selected"] = { r = 1.00, g = 1.00, b = 1.00 }, ["unavailable"] = { r = 1.00, g = 0.00, b = 0.00 }, ["header"] = { r = 0.30, g = 0.30, b = 1.00 }, }; -- ============================================================================ -- OnLoad -- -- Called when this addon is first loaded. -- ============================================================================ function TTCA_OnLoad() -- Register events this:RegisterEvent("BAG_UPDATE"); this:RegisterEvent("CRAFT_CLOSE"); this:RegisterEvent("CRAFT_SHOW"); this:RegisterEvent("CRAFT_UPDATE"); this:RegisterEvent("SPELLCAST_INTERRUPTED"); this:RegisterEvent("SPELLCAST_STOP"); this:RegisterEvent("TRADE_SKILL_CLOSE"); this:RegisterEvent("TRADE_SKILL_SHOW"); this:RegisterEvent("TRADE_SKILL_UPDATE"); --TradeSkillFrame_LoadUI(); -- Hook Pre_TTCA_TradeSkillFrame_SetSelection = TradeSkillFrame_SetSelection; TradeSkillFrame_SetSelection = TTCA_Override_TradeSkillFrame_OnSetSelection; Pre_TTCA_CraftFrame_SetSelection = CraftFrame_SetSelection; CraftFrame_SetSelection = TTCA_Override_CraftFrame_OnSetSelection; end -- ============================================================================ -- OnEvent -- -- Called to handle the events registered for this addon. -- ============================================================================ function TTCA_OnEvent() if (vfTTCA_BuildingTree) then if ((vfTTCA_WatchForBagUpdate) and (event == "BAG_UPDATE")) then vfTTCA_WatchForBagUpdate = false; TTCA_Update(); TTCA_BuildNextItem(vTTCA_ConstructionList); elseif (event == "SPELLCAST_INTERRUPTED") then -- Building was interrupted, reset the building flag. vfTTCA_BuildingTree = false; vfTTCA_WatchForBagUpdate = false; elseif (event == "SPELLCAST_STOP") then -- Finished building the current item, so build the next item in -- the construction list when the current item appears in the -- character's bag. vfTTCA_WatchForBagUpdate = true; end end if ((event == "CRAFT_CLOSE") or (event == "TRADE_SKILL_CLOSE")) then TTCA_OnTradeSkillClose(); elseif ((event == "CRAFT_SHOW") or (event == "TRADE_SKILL_SHOW")) then TTCA_OnTradeSkillShow(); elseif ((event == "CRAFT_UPDATE") or (event == "TRADE_SKILL_UPDATE")) then TTCA_OnTradeSkillUpdate(); end end -- ============================================================================ -- Override_TradeSkillFrame_OnSetSelection -- -- This event occurs every time a selection is set within the built in craft -- skill window. This function is hooked into the built in function so that -- this addon can catch the selection change events. -- ============================================================================ function TTCA_Override_CraftFrame_OnSetSelection(id) Pre_TTCA_CraftFrame_SetSelection(id); end -- ============================================================================ -- Override_TradeSkillFrame_OnSetSelection -- -- This event occurs every time a selection is set within the built in trade -- skill window. This function is hooked into the built in function so that -- this addon can catch the selection change events. -- ============================================================================ function TTCA_Override_TradeSkillFrame_OnSetSelection(id) Pre_TTCA_TradeSkillFrame_SetSelection(id); -- If the id is the currently selected item, don't bother reseting stuff. if ((vTTCA_BuildTree ~= nil) and (id ~= vTTCA_BuildTree[1].Id)) then -- Reset the build tree scroll frame. TTCA_Reset(); -- Reset the quantity. TTCA_InputBox_Quantity:SetNumber(1); end -- The selection may have changed, so update the trade skill build tree. TTCA_Update(); end -- ============================================================================ -- OnTradeSkillClose -- -- This event occurs when the user closes the built in trade skill window. -- ============================================================================ function TTCA_OnTradeSkillClose() -- Hide the trade skill build tree. TTCA_ShowBuildTree(false); -- Hide the trade skill show button. HideUIPanel(TTCA_Button_ShowBuildTree); end -- ============================================================================ -- OnTradeSkillShow -- -- This event occurs when the users opens the built in trade skill window. -- ============================================================================ function TTCA_OnTradeSkillShow() -- Show the trade skill tree expand button. TTCA_Button_ShowBuildTree:SetPoint("TOPLEFT", TTCA_GetTradeSkillOrCraftFrameName(), "TOPRIGHT", -37, -9); ShowUIPanel(TTCA_Button_ShowBuildTree); -- Reset the selected build tree item. TTCA_SetSelection(1); -- Reset the quantity. TTCA_InputBox_Quantity:SetNumber(1); end -- ============================================================================ -- OnTradeSkillUpdate -- -- This event occurs every time the built in trade skill window fires an update -- event. -- ============================================================================ function TTCA_OnTradeSkillUpdate() -- Update the build tree frame. TTCA_Update(); end -- ============================================================================ -- ShowBuildTree -- -- Shows/Hides the trade skill build tree window. -- ============================================================================ function TTCA_ShowBuildTree(show) -- If the active tab is not yet set, make it the first tab. if (vTTCA_ActiveTab == nil) then vTTCA_ActiveTab = TTCA_TAB_BUILDTREE; PanelTemplates_SelectTab(TTCA_Tab_BuildTree); end if (show) then -- Hide the expand button and show the skill tree frame. HideUIPanel(TTCA_Button_ShowBuildTree); ShowUIPanel(TTCA_MainFrame); TTCA_MainFrame:SetPoint("TOPLEFT", TTCA_GetTradeSkillOrCraftFrameName(), "TOPRIGHT", -35, -13); TTCA_Update(); PlaySound("igCharacterInfoOpen"); else -- Hide the trade skill expand frame and show the expand button. HideUIPanel(TTCA_MainFrame); ShowUIPanel(TTCA_Button_ShowBuildTree); PlaySound("igCharacterInfoClose"); end end -- ============================================================================ -- Reset -- -- Resets the scroll frame to its initial values. -- ============================================================================ function TTCA_Reset() -- Reset the scroll frame. FauxScrollFrame_SetOffset(TTCA_List_ScrollFrame, 0); TTCA_List_ScrollFrameScrollBar:SetValue(0); -- Reset the buttons. TTCA_Button_CreateTree:Disable(); TTCA_Button_CreateAllTree:Disable(); end -- ============================================================================ -- Update -- -- Calculate the build tree, required raw materials, tools, and a construction -- list for the currently selected item. -- ============================================================================ function TTCA_Update() -- If the build tree window isn't visible, don't bother updating. if (not TTCA_MainFrame:IsVisible()) then return; end -- Create the build tree. vTTCA_BuildTree = {}; TTCA_CreateBuildTree(TTCA_GetSkillSelectionIndex(), vTTCA_BuildTree, nil, TTCA_InputBox_Quantity:GetNumber()); -- Compute raw material requirements and the construction list for the currently -- selected item. vTTCA_MaterialList, vTTCA_ConstructionList, vTTCA_ToolList = TTCA_CreateMaterialConstructionToolLists(vTTCA_BuildTree, TTCA_GetSelection()); -- Disable the create tree button. TTCA_Button_CreateTree:Disable(); TTCA_Button_CreateAllTree:Disable(); -- Update the list of items with the build tree or the material summary, -- depending on which tab is active. if (vTTCA_ActiveTab == TTCA_TAB_BUILDTREE) then TTCA_UpdateBuildTree(vTTCA_BuildTree); if (TTCA_IsItemBuildable(vTTCA_BuildTree, TTCA_GetSelection()) and (vTTCA_BuildTree[TTCA_GetSelection()].Type ~= "reagent")) then TTCA_Button_CreateTree:Enable(); TTCA_Button_CreateAllTree:Enable(); end elseif (vTTCA_ActiveTab == TTCA_TAB_MATERIALS) then TTCA_UpdateMaterials(vTTCA_MaterialList); end end -- ============================================================================ -- UpdateBuildTree -- ============================================================================ function TTCA_UpdateBuildTree(buildTree) -- Find the total number of items in the build tree. local cBuildTreeItems = getn(buildTree); -- Find the scroll offset for the faux scroll frame. local iListItemOffset = FauxScrollFrame_GetOffset(TTCA_List_ScrollFrame); -- Update the scroll frame. FauxScrollFrame_Update(TTCA_List_ScrollFrame, cBuildTreeItems, TTCA_LISTITEMS_VISIBLE, TTCA_LISTITEM_HEIGHT, nil, nil, nil, TTCA_ListItem_HighlightFrame, 300, 300); -- Hide the highlight frame until we know where it is appearing. TTCA_ListItem_HighlightFrame:Hide(); -- Loop through our visible list items and update each one. for i=1, TTCA_LISTITEMS_VISIBLE, 1 do local listItem = getglobal("TTCA_ListItem" .. i); local listItemIndent = getglobal("TTCA_ListItem" .. i .. "_Indent"); local listItemTexture = getglobal("TTCA_ListItem" .. i .. "_Texture"); local listItemTooltipTriggerFrame = getglobal("TTCA_ListItem" .. i .. "_TooltipTriggerFrame"); local iBuildTreeIndex = i + iListItemOffset; if (iBuildTreeIndex <= cBuildTreeItems) then local buildTreeItem = buildTree[iBuildTreeIndex]; if (buildTreeItem.Name ~= nil) then -- Indent the item by its level. listItemIndent:SetWidth(TTCA_LISTITEM_INDENT * (buildTreeItem.Level-1) + 1); -- Set the texture. listItemTexture:SetTexture(buildTreeItem.Texture); listItemTexture:SetWidth(20); listItemTexture:Show(); -- Set the name, number required, and number available. local itemText = buildTreeItem.Name .. " "; local itemNumText = "(" .. buildTreeItem.NumAvailable .. "/" .. buildTreeItem.NumRequired .. ")"; local itemNumBuildableText = ""; local itemNumTextColor; -- If this item is not a reagent, compute how many we can build based on the num available. if (buildTreeItem.Type ~= "reagent") then itemNumBuildableText = " [" .. floor(buildTreeItem.NumAvailable / buildTreeItem.NumRequired) .. "]"; end -- If the number available is >= the number required, then color the text differently. if (buildTreeItem.NumAvailable >= buildTreeItem.NumRequired) then itemNumTextColor = HIGHLIGHT_FONT_COLOR_CODE; else itemNumTextColor = GRAY_FONT_COLOR_CODE; end listItem:SetText(itemText .. itemNumTextColor .. itemNumText .. itemNumBuildableText .. FONT_COLOR_CODE_CLOSE); -- Set the color of the text. local listItemColor = TTCA_TypeColor[buildTreeItem.Type]; listItem:SetTextColor(listItemColor.r, listItemColor.g, listItemColor.b); -- Set the Id so we know which button gets selected on clicks. listItem.Index = iBuildTreeIndex; -- Set some values on the texture so we can show tooltips for each item. listItemTooltipTriggerFrame.Id = buildTreeItem.Id; listItemTooltipTriggerFrame.ReagentId = buildTreeItem.ReagentId; listItemTooltipTriggerFrame:Show(); -- Set some values on the item so we can link it when shift-clicked. listItem.Id = buildTreeItem.Id; listItem.ReagentId = buildTreeItem.ReagentId; -- Update the highlight frame. if (TTCA_GetSelection() == iBuildTreeIndex) then -- Set the selected item's text color. local listItemTextColor = TTCA_TypeColor["selected"]; listItem:SetTextColor(listItemTextColor.r, listItemTextColor.g, listItemTextColor.b); -- Set the color and location of the highlight frame. TTCA_ListItem_Highlight:SetVertexColor(listItemColor.r, listItemColor.g, listItemColor.b); TTCA_ListItem_HighlightFrame:SetPoint("TOPLEFT", "TTCA_ListItem" .. i, "TOPLEFT", -3, 0); TTCA_ListItem_HighlightFrame:Show(); end -- Show the button. listItem:Show(); end else -- Hide the button since it is unused. listItem:Hide(); end end end -- ============================================================================ -- UpdateMaterials -- ============================================================================ function TTCA_UpdateMaterials(materialList) -- Find the total number of items in the material list. local cMaterialItems = getn(materialList); -- Find the scroll offset for the faux scroll frame. local iListItemOffset = FauxScrollFrame_GetOffset(TTCA_List_ScrollFrame); -- Update the scroll frame. FauxScrollFrame_Update(TTCA_List_ScrollFrame, cMaterialItems, TTCA_LISTITEMS_VISIBLE, TTCA_LISTITEM_HEIGHT, nil, nil, nil, TTCA_ListItem_HighlightFrame, 300, 300); -- Hide the highlight frame since it isn't used for this view. TTCA_ListItem_HighlightFrame:Hide(); -- Loop through our material list. for i=1, TTCA_LISTITEMS_VISIBLE, 1 do local listItem = getglobal("TTCA_ListItem" .. i); local listItemIndent = getglobal("TTCA_ListItem" .. i .. "_Indent"); local listItemTexture = getglobal("TTCA_ListItem" .. i .. "_Texture"); local listItemTooltipTriggerFrame = getglobal("TTCA_ListItem" .. i .. "_TooltipTriggerFrame"); local iMaterialListIndex = i + iListItemOffset; if (iMaterialListIndex <= cMaterialItems) then local materialListItem = materialList[iMaterialListIndex]; if (materialListItem.Name ~= nil) then -- Indent the item by its level. listItemIndent:SetWidth(TTCA_LISTITEM_INDENT * (materialListItem.Level-1) + 1); -- Set the texture, if one exists. if (materialListItem.Texture) then listItemTexture:SetTexture(materialListItem.Texture); listItemTexture:SetWidth(20); listItemTexture:Show(); else listItemTexture:SetWidth(1); listItemTexture:Hide(); end -- Set the name. local wzName = materialListItem.Name; -- Set the number required and available, if they exist. if (materialListItem.NumAvailable and materialListItem.NumRequired) then wzName = wzName .. " (" .. materialListItem.NumAvailable .. "/" .. materialListItem.NumRequired .. ")"; end -- Set the text on the list item. listItem:SetText(wzName); -- Set the color of the text. local listItemColor = TTCA_TypeColor["reagent"]; -- If the number required and available exists, then color the item if we have enough. if (materialListItem.NumAvailable and materialListItem.NumRequired) then if (materialListItem.NumAvailable >= materialListItem.NumRequired) then listItemColor = TTCA_TypeColor["selected"]; end elseif (materialListItem.Type) then listItemColor = TTCA_TypeColor[materialListItem.Type]; end listItem:SetTextColor(listItemColor.r, listItemColor.g, listItemColor.b); -- Set some values on the texture so we can show tooltips for each item. But if the -- texture isn't set, don't bother doing this. if (materialListItem.Texture) then listItemTooltipTriggerFrame.Id = materialListItem.Id; listItemTooltipTriggerFrame.ReagentId = materialListItem.ReagentId; listItemTooltipTriggerFrame:Show(); else listItemTooltipTriggerFrame:Hide(); end -- Set some values on the item so we can link it when shift-clicked. listItem.Id = materialListItem.Id; listItem.ReagentId = materialListItem.ReagentId; -- Show the button. listItem:Show(); end else -- Hide the button since it is unused. listItem:Hide(); end end end -- ============================================================================ -- GetSelection -- -- Returns the item currently selected in the build tree tab. -- ============================================================================ function TTCA_GetSelection() return TTCA_MainFrame.SelectionIndex; end -- ============================================================================ -- SetSelection -- -- Makes the item at the given build tree index the currently selected item. -- ============================================================================ function TTCA_SetSelection(index) TTCA_MainFrame.SelectionIndex = index; TTCA_Update(); end -- ============================================================================ -- FindTradeSkillIdByName -- -- Iterates through all of the player's trade skills and returns the index of -- the first trade skill that matches the given name. If no match is found -- then nil is returned. -- ============================================================================ function TTCA_FindTradeSkillIdByName(tradeSkillName) local cTradeSkills = TTCA_GetNumSkills(); for i=1, cTradeSkills, 1 do local name = TTCA_GetSkillInfo(i); if (tradeSkillName == name) then return i; end end return nil; end -- ============================================================================ -- CreateMaterialConstructionToolLists -- -- Generates a list of raw materials required in order to create the selected -- item. If no item is selected, it creates a summary for the first item. -- ============================================================================ function TTCA_CreateMaterialConstructionToolLists(buildTree, index) if ((index <= 0) or (index > getn(buildTree))) then index = 1; end local materialList = {}; local constructionList = {}; local toolList = {}; local finalizedMaterialList = {}; TTCA_CreateMaterialConstructionToolListsSub(materialList, constructionList, toolList, buildTree, index, buildTree[index].NumRequired); -- Sort the material list alphabetically. materialList = TTCA_Sort(materialList); -- Sort the tool list alphabetically. toolList = TTCA_Sort(toolList); -- Construct the final version of the material list. -- Format: selected item, tools, materials. -- Add the selected item as the first item in the material list. local selectedItem = TTCA_Item:New(); selectedItem.Name = buildTree[index].Name; selectedItem.Type = buildTree[index].Type; selectedItem.Texture = buildTree[index].Texture; selectedItem.Id = buildTree[index].Id; selectedItem.ReagentId = buildTree[index].ReagentId; selectedItem.Level = 1; tinsert(finalizedMaterialList, selectedItem); -- Add the tools to the material list. if (getn(toolList) > 0) then -- Add a tool header if there is at least one tool. local toolHeaderItem = TTCA_Item:New(); toolHeaderItem.Name = TTCA_TEXT_REQUIREDTOOLS; toolHeaderItem.Type = "header"; toolHeaderItem.Level = 2; tinsert(finalizedMaterialList, toolHeaderItem); -- Now add the tools. for i=1, getn(toolList), 1 do local toolItem = TTCA_Item:New() toolItem.Name = toolList[i].Name; toolItem.Type = toolList[i].Type; toolItem.Level = 3; tinsert(finalizedMaterialList, toolItem); end end -- Add the materials to the material list. if (getn(materialList) > 0) then -- Add a material header if there is at least on material. local materialHeaderItem = TTCA_Item:New(); materialHeaderItem.Name = TTCA_TEXT_REQUIREDMATERIALS; materialHeaderItem.Type = "header"; materialHeaderItem.Level = 2; tinsert(finalizedMaterialList, materialHeaderItem); -- Now add the materials. for i=1, getn(materialList), 1 do local materialItem = materialList[i]; materialItem.Level = 3; tinsert(finalizedMaterialList, materialItem); end end return finalizedMaterialList, constructionList, toolList; end -- ============================================================================ -- CreateMaterialConstructionToolListsSub -- ============================================================================ function TTCA_CreateMaterialConstructionToolListsSub(materialList, constructionList, toolList, buildTree, index, iNumRequired) local currentItem = buildTree[index]; -- If this item is a reagent, add it to the summary. if (currentItem.Type == "reagent") then if (currentItem.Name == nil) then return; end -- Initialize this reagent information if it hasn't been in the summary -- before. if (materialList[currentItem.Name] == nil) then materialList[currentItem.Name] = {}; materialList[currentItem.Name].NumRequired = 0; end -- Add this reagent's information to the summary. materialList[currentItem.Name].Name = currentItem.Name; materialList[currentItem.Name].Type = currentItem.Type; materialList[currentItem.Name].NumAvailable = currentItem.NumAvailable; materialList[currentItem.Name].NumRequired = materialList[currentItem.Name].NumRequired + currentItem.NumRequired; materialList[currentItem.Name].Texture = currentItem.Texture; materialList[currentItem.Name].Id = currentItem.Id; materialList[currentItem.Name].ReagentId = currentItem.ReagentId; else -- This is not a reagent, so add it to the construction list. tinsert(constructionList, currentItem); -- Get the tools required for this item. TTCA_AppendToolsToList(toolList, GetTradeSkillTools(currentItem.Id)); -- This is not a reagent, so recurse over its reagents. local cBuildItems = getn(buildTree); for i=index+1, cBuildItems, 1 do if (i <= cBuildItems) then if (currentItem.Level + 1 == buildTree[i].Level) then TTCA_CreateMaterialConstructionToolListsSub(materialList, constructionList, toolList, buildTree, i, iNumRequired); elseif (currentItem.Level == buildTree[i].Level) then return; end end end end end -- ============================================================================ -- AppendToolsToList -- ============================================================================ function TTCA_AppendToolsToList(list, ...) if (not list) then return; end -- Loop over the tools and add each one to the tool list. for i=1, arg.n, 2 do local toolDetails = {}; if (arg[i+1] == 1) then toolDetails.Type = "selected"; else toolDetails.Type = "unavailable"; end toolDetails.Name = arg[i]; list[toolDetails.Name] = toolDetails; end end -- ============================================================================ -- CreateBuildTree -- ============================================================================ function TTCA_CreateBuildTree(tradeSkillId, buildTree, level, numRequired) if ((tradeSkillId <= 0) or (buildTree == nil)) then return nil; end if (level == nil) then level = 1; end if (numRequired == nil) then numRequired = 1; end -- Create a new trade skill item. local tradeSkillItem = TTCA_Item:New(); tradeSkillItem.Name, tradeSkillItem.Type, tradeSkillItem.NumAvailable = TTCA_GetSkillInfo(tradeSkillId); tradeSkillItem.Level = level; tradeSkillItem.Id = tradeSkillId; tradeSkillItem.Texture = TTCA_GetSkillIcon(tradeSkillId); tradeSkillItem.NumRequired = numRequired; -- Add this item to the trade skill tree. tinsert(buildTree, tradeSkillItem); -- Create the reagent information for this trade skill. local cReagents = TTCA_GetSkillNumReagents(tradeSkillId); for i=1, cReagents, 1 do -- Get the reagent name. local reagentName = TTCA_GetSkillReagentInfo(tradeSkillId, i); -- Figure out if the reagent is craftable as a trade skill item. local iReagentTradeSkillId = TTCA_FindTradeSkillIdByName(reagentName); if (not (iReagentTradeSkillId == nil)) then -- Figure out how many are required. local name, texture, reagentNumRequired = TTCA_GetSkillReagentInfo(tradeSkillId, i); -- The reagent is a craftable item, so create a trade skill item for it. local tradeSkillReagentItem = TTCA_CreateBuildTree(iReagentTradeSkillId, buildTree, level + 1, reagentNumRequired * tradeSkillItem.NumRequired); -- Initialize some other reagent information. tradeSkillReagentItem.Name, tradeSkillReagentItem.Texture, tradeSkillReagentItem.NumRequired, tradeSkillReagentItem.NumAvailable = TTCA_GetSkillReagentInfo(tradeSkillId, i); -- Modify the number required by the quantity entered. tradeSkillReagentItem.NumRequired = tradeSkillReagentItem.NumRequired * tradeSkillItem.NumRequired; else -- The reagent is not a craftable item, so get the reagent info for it. -- Create a new trade skill item for this reagent. local tradeSkillReagentItem = TTCA_Item:New(); tradeSkillReagentItem.Name, tradeSkillReagentItem.Texture, tradeSkillReagentItem.NumRequired, tradeSkillReagentItem.NumAvailable = TTCA_GetSkillReagentInfo(tradeSkillId, i); tradeSkillReagentItem.Level = level + 1; tradeSkillReagentItem.Id = tradeSkillId; tradeSkillReagentItem.ReagentId = i; tradeSkillReagentItem.Type = "reagent"; -- Sometimes NumAvailable can be nil. Not yet sure why or how, but let's add some code for when it does. if (tradeSkillReagentItem.NumAvailable == nil) then DEFAULT_CHAT_FRAME:AddMessage("Congrats! You've encountered a bug that I'm trying to track down. Please go to www.wowinterface.com and send a message to twig314159 with the following information:"); DEFAULT_CHAT_FRAME:AddMessage("ItemName = " .. tradeSkillItem.Name); DEFAULT_CHAT_FRAME:AddMessage("ReagentName = " .. tradeSkillReagentItem.Name); DEFAULT_CHAT_FRAME:AddMessage("ReagentNumAvailable = " .. tradeSkillReagentItem.NumAvailable); -- Fix up NumAvailable if it does happen to be nil. tradeSkillReagentItem.NumAvailable = 0; end -- Modify the number required by the quantity entered. tradeSkillReagentItem.NumRequired = tradeSkillReagentItem.NumRequired * tradeSkillItem.NumRequired; -- Add this item to the trade skill tree. tinsert(buildTree, tradeSkillReagentItem); end end return tradeSkillItem; end -- ============================================================================ -- ListItem_OnClick -- ============================================================================ function TTCA_ListItem_OnClick(button) if (button == "LeftButton") then local fShift = IsShiftKeyDown(); local fAlt = IsAltKeyDown(); -- If the user shift-clicked the item, insert a link to it. if (fShift and not fAlt) then if (ChatFrameEditBox:IsVisible()) then ChatFrameEditBox:Insert(TTCA_GetItemLink(this.Id, this.ReagentId)); end -- If the user alt-clicked the item, link the entire dependency tree. -- If the build tree is active, then link all dependencies of the alt-clicked item. -- If the materials tree is active, then link only the materials listed in that view. elseif (fAlt and not fShift) then -- If the chat edit box is not visible, just bail so we don't waste time -- iterating only to do nothing. if (not ChatFrameEditBox:IsVisible()) then return; end -- The chat box is visible, so figure out who/what we're chatting with -- so we can send each item as a seperate message and make sure it goes -- to the right destination. ChatEdit_ParseText(ChatFrameEditBox, 0); local chatType = ChatFrameEditBox.chatType; local chatLanguage = ChatFrameEditBox.language; local chatTarget = nil; -- Set the chat target. if (chatType == "WHISPER") then chatTarget = ChatFrameEditBox.tellTarget; elseif (chatType == "CHANNEL") then chatTarget = ChatFrameEditBox.channelTarget; end -- Link the dependency tree. if (vTTCA_ActiveTab == TTCA_TAB_BUILDTREE) then local cBuildItems = getn(vTTCA_BuildTree); -- Loop through the build tree so we can link each item that this item depends on. for i=this.Index, cBuildItems, 1 do local buildTreeItem = vTTCA_BuildTree[i]; if (buildTreeItem ~= nil) then local text = ""; -- Generate a nice little header first. if (i == this.Index) then text = TTCA_TEXT_MATERIALSFOR .. TTCA_GetItemLink(buildTreeItem.Id, buildTreeItem.ReagentId); else -- If we arrive back at the same level we started, then we're done! if (buildTreeItem.Level == vTTCA_BuildTree[this.Index].Level) then return; end -- Otherwise, ident the item and dump it to the chat window. for n=vTTCA_BuildTree[this.Index].Level, buildTreeItem.Level, 1 do text = text .. " "; end text = text .. TTCA_GetItemLink(buildTreeItem.Id, buildTreeItem.ReagentId) .. " x" .. buildTreeItem.NumRequired; end if (text ~= nil) then -- Now send the text and add it to the chat history. SendChatMessage(text, chatType, chatLanguage, chatTarget); ChatFrameEditBox:AddHistoryLine(text); end end end -- Link all the raw materials. elseif (vTTCA_ActiveTab == TTCA_TAB_MATERIALS) then -- Find the total number of materials. local cMaterialItems = getn(vTTCA_MaterialList); -- Loop through the material list so we can link each one. for i=1, cMaterialItems, 1 do local materialListItem = vTTCA_MaterialList[i]; if (materialListItem.Name ~= nil) then local text = nil; -- Generate a nice little header first. if (i == 1) then text = TTCA_TEXT_MATERIALSFOR .. TTCA_GetItemLink(materialListItem.Id, materialListItem.ReagentId); end -- We want to link only reagents (not headers, tools, etc). if (materialListItem.Type == "reagent") then text = " " .. TTCA_GetItemLink(materialListItem.Id, materialListItem.ReagentId) .. " x" .. materialListItem.NumRequired; end if (text ~= nil) then -- Now send the text and add it to the chat history. SendChatMessage(text, chatType, chatLanguage, chatTarget); ChatFrameEditBox:AddHistoryLine(text); end end end end -- Otherwise, just make the item the currently selected item. else if (vTTCA_ActiveTab == TTCA_TAB_BUILDTREE) then TTCA_SetSelection(this.Index); TTCA_Update(); end end end end -- ============================================================================ -- ListItem_OnEnter -- ============================================================================ function TTCA_ListItem_OnEnter() if (this.Id) then GameTooltip:SetOwner(this, "ANCHOR_UPPERLEFT"); if (TTCA_IsCraftFrameVisible()) then GameTooltip:SetCraftItem(this.Id, this.ReagentId); else GameTooltip:SetTradeSkillItem(this.Id, this.ReagentId); end end end -- ============================================================================ -- ListItem_OnLeave -- ============================================================================ function TTCA_ListItem_OnLeave() GameTooltip:Hide(); end -- ============================================================================ -- CreateTree_OnClick -- ============================================================================ function TTCA_CreateTree_OnClick(createAll) -- Set the building tree flag. vfTTCA_BuildingTree = true; -- Set the flag that says we're trying to build as many as we can. vfTTCA_BuildingAll = createAll; TTCA_BuildNextItem(vTTCA_ConstructionList); end -- ============================================================================ -- Tab_OnClick -- ============================================================================ function TTCA_Tab_OnClick(activateTab) if (vTTCA_ActiveTab ~= activateTab) then -- Reset the scroll frame. TTCA_Reset(); -- Deselect all of the tabs. PanelTemplates_DeselectTab(TTCA_Tab_BuildTree); PanelTemplates_DeselectTab(TTCA_Tab_Materials); -- Select the tab the user clicked. vTTCA_ActiveTab = activateTab; PanelTemplates_SelectTab(this); -- Update the frame list. TTCA_Update(); end end -- ============================================================================ -- IncrementQuantity_OnClick -- ============================================================================ function TTCA_IncrementQuantity_OnClick(delta) local iNewNumber = TTCA_InputBox_Quantity:GetNumber() + delta; if ((iNewNumber > 0) and (iNewNumber < 100)) then TTCA_InputBox_Quantity:SetNumber(iNewNumber); -- Since the number has changed, we need to update our build tree. TTCA_Update(); end end -- ============================================================================ -- BuildNextItem -- ============================================================================ function TTCA_BuildNextItem(constructionList) local cItems = getn(constructionList); -- Loop through each item in the list and build it if we have all the -- reagents available. for i=1, cItems, 1 do local currentItem = constructionList[i]; local tradeSkillDetails = {}; tradeSkillDetails.Name, tradeSkillDetails.Type, tradeSkillDetails.NumAvailable = TTCA_GetSkillInfo(currentItem.Id); if ((tradeSkillDetails.NumAvailable > 0) and (currentItem.NumAvailable <= currentItem.NumRequired) and (i==1)) then -- If we built the first item in the list and not building as many as -- we can, then we're done! if (not vfTTCA_BuildingAll) then vfTTCA_BuildingTree = false; end TTCA_DoSkill(currentItem.Id, 1); -- This means we built our intended target. So, decrement the quantity by 1. -- If it would be zero, then we really are done. If not, keep building. if (TTCA_InputBox_Quantity:GetNumber() - 1 > 0) then TTCA_IncrementQuantity_OnClick(-1); vfTTCA_BuildingTree = true; end return; elseif ((tradeSkillDetails.NumAvailable > 0) and (currentItem.NumAvailable < currentItem.NumRequired)) then TTCA_DoSkill(currentItem.Id, 1); return; end end -- If we made it here, then we went through the whole build list and found -- nothing to build, so stop trying. vfTTCA_BuildingTree = false; vfTTCA_BuildingAll = false; end -- ============================================================================ -- IsItemBuildable -- ============================================================================ function TTCA_IsItemBuildable(buildTree, index, iNumRequired) if (iNumRequired == nil) then iNumRequired = 1; end local currentItem = buildTree[index]; if (currentItem == nil) then return false; end -- If this item is a reagent, report that it is buildable as long as we -- have enough. if (currentItem.Type == "reagent") then if (currentItem.NumAvailable >= currentItem.NumRequired) then return true; end else -- This item is not a regeant, so only report it is buildable if all of -- its children are buildable or we already have enough of them. local fIsBuildable = true; if (currentItem.NumAvailable >= currentItem.NumRequired) then return fIsBuildable; end local cBuildItems = getn(buildTree); for i=index+1, cBuildItems, 1 do if (i <= cBuildItems) then if (currentItem.Level + 1 == buildTree[i].Level) then if (not TTCA_IsItemBuildable(buildTree, i, currentItem.NumRequired)) then fIsBuildable = false; end elseif (currentItem.Level == buildTree[i].Level) then return fIsBuildable; end end end return fIsBuildable; end return false; end -- ============================================================================ -- Sort -- ============================================================================ function TTCA_Sort(dictionary) local sortedList = {}; -- Convert out dictionary list into an array. for key, value in dictionary do tinsert(sortedList, value); end -- Sort the array by the .Name property. sort(sortedList, function(a, b) return a.Name < b.Name end); return sortedList; end -- ============================================================================ -- LinkItem -- -- Returns a link to the given item. This link can then be used in a chat box. -- ============================================================================ function TTCA_GetItemLink(itemId, reagentId) if (itemId and reagentId == nil) then return TTCA_GetSkillItemLink(itemId); elseif (itemId and reagentId) then return TTCA_GetSkillReagentItemLink(itemId, reagentId); end return nil; end function TTCA_IsCraftFrameVisible() return (CraftFrame ~= nil and CraftFrame:IsVisible()); end function TTCA_GetTradeSkillOrCraftFrameName() if (TradeSkillFrame ~= nil and TradeSkillFrame:IsVisible()) then return TradeSkillFrame:GetName(); elseif (CraftFrame ~= nil and CraftFrame:IsVisible()) then return CraftFrame:GetName(); else return nil; end end function TTCA_GetSkillSelectionIndex() if (TTCA_IsCraftFrameVisible()) then return GetCraftSelectionIndex(); else return GetTradeSkillSelectionIndex(); end end function TTCA_GetNumSkills() if (TTCA_IsCraftFrameVisible()) then return GetNumCrafts(); else return GetNumTradeSkills(); end end function TTCA_GetSkillInfo(i) local name, subName, type, numAvailable, isExpanded; if (TTCA_IsCraftFrameVisible()) then name, subName, type, numAvailable, isExpanded = GetCraftInfo(i); else name, type, numAvailable, isExpanded = GetTradeSkillInfo(i); end return name, type, numAvailable, isExpanded; end function TTCA_GetSkillIcon(i) if (TTCA_IsCraftFrameVisible()) then return GetCraftIcon(i); else return GetTradeSkillIcon(i); end end function TTCA_GetSkillNumReagents(i) if (TTCA_IsCraftFrameVisible()) then return GetCraftNumReagents(i); else return GetTradeSkillNumReagents(i); end end function TTCA_GetSkillReagentInfo(index, reagentIndex) if (TTCA_IsCraftFrameVisible()) then return GetCraftReagentInfo(index, reagentIndex); else return GetTradeSkillReagentInfo(index, reagentIndex); end end function TTCA_DoSkill(i, n) if (TTCA_IsCraftFrameVisible()) then return DoCraft(i); else return DoTradeSkill(i, n); end end function TTCA_GetSkillItemLink(itemId) if (TTCA_IsCraftFrameVisible()) then return GetCraftItemLink(itemId); else return GetTradeSkillItemLink(itemId); end end function TTCA_GetSkillReagentItemLink(itemId, reagentId) if (TTCA_IsCraftFrameVisible()) then return GetCraftReagentItemLink(itemId, reagentId); else return GetTradeSkillReagentItemLink(itemId, reagentId); end end