cgc = AceLibrary("AceAddon-2.0"):new("AceDB-2.0", "AceConsole-2.0", "AceDebug-2.0", "AceEvent-2.0", "AceHook-2.0") -- Dewdrop: handles our dropdown local dewdrop = AceLibrary("Dewdrop-2.0") -- Our container for all frames. local frames = {} -- The search type should default to "by name" cgc:RegisterDB("cgCraftyDB") cgc:RegisterDefaults('profile', { searchType = {}, searchHistory = {}, }) function cgc:OnInitialize() self:SetDebugging(false) self:RegisterChatCommand({ "/cgcrafty", "/cgc" }, nil) -- Tradeskill frame references frames.trade = {} frames.trade.elements = { ["Main"] = "TradeSkillFrame", ["Title"] = "TradeSkillFrameTitleText", ["Scroll"] = "TradeSkillListScrollFrame", ["ScrollBar"] = "TradeSkillListScrollFrameScrollBar", ["Highlight"] = "TradeSkillHighlightFrame", ["CollapseAll"] = "TradeSkillCollapseAllButton", } frames.trade.anchor = "TradeSkillCreateAllButton" frames.trade.anchor_offset_x = -9 frames.trade.anchor_offset_y = -8 frames.trade.update = "TradeSkillFrame_Update" -- Crafting frame references frames.craft = {} frames.craft.elements = { ["Main"] = "CraftFrame", ["Title"] = "CraftFrameTitleText", ["Scroll"] = "CraftListScrollFrame", ["ScrollBar"] = "CraftListScrollFrameScrollBar", ["Highlight"] = "CraftHighlightFrame", } frames.craft.anchor = "CraftCancelButton" frames.craft.anchor_offset_x = 6 frames.craft.anchor_offset_y = -8 frames.craft.update = "CraftFrame_Update" -- Setup some closures for use later. -- History search text setting variable get/save self.getHistory = function(var) return self.db.profile.searchHistory[var] end self.setHistory = function(val) self.db.profile.searchHistory[self.lastSearchTrade or getglobal(self.currentFrame.elements.Title):GetText()] = val end self.clearHistory = function() self.db.profile.searchHistory = {} end -- History search type setting variable get/save self.getSearchType = function(val) return self.db.profile.searchType[getglobal(self.currentFrame.elements.Title):GetText()] or self.LOCALS.FRAME_SEARCH_TYPES[val] end self.setSearchType = function(val) self.db.profile.searchType[getglobal(self.currentFrame.elements.Title):GetText()] = val end -- Search Text self.searchText = nil -- Clear our the search history self.clearHistory() -- Handler for the currently opened frame. self.currentFrame = nil end function cgc:OnEnable() self:Debug("OnEnable called.") -- Tradeskill window -- self:RegisterEvent("TRADE_SKILL_SHOW") -- Enchanting window -- self:RegisterEvent("CRAFT_SHOW") if not self.frame then self:Debug("Creating cgcFrame.") -- Create main frame self.frame = CreateFrame("Frame", "cgcFrame", UIParent) self.frame:Hide() -- Set main frame properties self.frame:SetPoint("CENTER", "UIParent", "CENTER", 0, 0) self.frame:SetWidth(342) self.frame:SetHeight(45) self.frame:SetFrameStrata("MEDIUM") self.frame:SetMovable(false) self.frame:EnableMouse(true) -- Set the main frame backdrop self.frame:SetBackdrop({ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", tile = true, tileSize = 32, edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", edgeSize = 20, insets = {left = 5, right = 6, top = 6, bottom = 5}, }) self.frame:SetBackdropColor(1, 1, 1, 1) self.frame:SetBackdropBorderColor(0, .8, 0, 1) self.frame:SetScript("OnShow", function() self:OnShow() end) -- Create sub-frames -- Editbox for search text self.frame.SearchBox = CreateFrame("EditBox", nil, self.frame, "InputBoxTemplate") self.frame.SearchBox:SetAutoFocus(false) self.frame.SearchBox:SetWidth(110) self.frame.SearchBox:SetHeight(20) self.frame.SearchBox:SetPoint("LEFT", self.frame, "LEFT", 20, 0) self.frame.SearchBox:SetBackdropColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) self.frame.SearchBox:SetBackdropBorderColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) self.frame.SearchBox:SetScript("OnEnterPressed", function() self:Search(this:GetText()) end) -- Reset Button self.frame.ResetButton = CreateFrame("Button", nil, self.frame, "GameMenuButtonTemplate") self.frame.ResetButton:SetWidth(20) self.frame.ResetButton:SetHeight(25) self.frame.ResetButton:SetPoint("RIGHT", self.frame, "RIGHT", -15, 0) self.frame.ResetButton:SetText(self.LOCALS.FRAME_RESET_TEXT) self.frame.ResetButton:SetScript("OnClick", function() self:Reset() end) -- Submit Button self.frame.SubmitButton = CreateFrame("Button", nil, self.frame, "GameMenuButtonTemplate") self.frame.SubmitButton:SetWidth(20) self.frame.SubmitButton:SetHeight(25) self.frame.SubmitButton:SetPoint("RIGHT", self.frame.ResetButton, "LEFT", -10, 0) self.frame.SubmitButton:SetText(self.LOCALS.FRAME_SUBMIT_TEXT) self.frame.SubmitButton:SetScript("OnClick", function() self:Search(self.frame.SearchBox:GetText()) end) -- SearchType dropdown button to show the menu when clicked. self.frame.SearchTypeButton = CreateFrame("Button", nil, self.frame, "GameMenuButtonTemplate") self.frame.SearchTypeButton:SetWidth(70) self.frame.SearchTypeButton:SetHeight(25) self.frame.SearchTypeButton:SetPoint("LEFT", self.frame.SearchBox, "RIGHT", 8, 0) self.frame.SearchTypeButton:SetText("Type") self.frame.SearchTypeButton:SetScript("OnClick", function() if ( dewdrop:IsOpen(self.frame.SearchTypeButton) ) then dewdrop:Close() else dewdrop:Open(self.frame.SearchTypeButton) end end ) -- Create the SearchType dropdown menu dewdrop:Register(self.frame.SearchTypeButton, 'point', function (parent) return "TOPLEFT", "BOTTOMLEFT" end, 'dontHook', true, 'children', function () dewdrop:AddLine( 'text', cgc.LOCALS.FRAME_SEARCH_TYPE_TITLE, 'isTitle', true ) for i,type in self.LOCALS.FRAME_SEARCH_TYPES do dewdrop:AddLine( 'text', type, 'func', function(val) self.setSearchType(val) self.frame.SearchTypeButton:SetText(val) end, 'arg1', type, 'tooltipTitle', type, 'tooltipText', self.LOCALS.FRAME_SEARCH_TYPES_DESC[i], 'closeWhenClicked', true ) end end ) -- Link Reagents dropdown button to show the menu when clicked. self.frame.LinkReagentButton = CreateFrame("Button", nil, self.frame, "GameMenuButtonTemplate") self.frame.LinkReagentButton:SetWidth(50) self.frame.LinkReagentButton:SetHeight(25) self.frame.LinkReagentButton:SetPoint("LEFT", self.frame.SearchTypeButton, "RIGHT", 8, 0) self.frame.LinkReagentButton:SetText(self.LOCALS.FRAME_LINK_REAGENTS) self.frame.LinkReagentButton:SetScript("OnClick", function() if ( dewdrop:IsOpen(self.frame.LinkReagentButton) ) then dewdrop:Close() else dewdrop:Open(self.frame.LinkReagentButton) end end ) -- Create the LinkReagents dropdown menu dewdrop:Register(self.frame.LinkReagentButton, 'point', function (parent) return "TOPLEFT", "BOTTOMLEFT" end, 'dontHook', true, 'children', function () dewdrop:AddLine( 'text', cgc.LOCALS.FRAME_LINK_REAGENTS_TITLE, 'isTitle', true ) for i,channel in self.LOCALS.FRAME_LINK_TYPES do -- There are two types lines: -- 1. Those that are straightforward and do not require user input -- 2. Those that require the user to input information to take it a step further. -- channel[1] is the "common name" -- channel[2] is the "channel" -- channel[3] is the "desc" if ( channel[2] ~= "WHISPER" and channel[2] ~= "CHANNEL" ) then dewdrop:AddLine( 'text', channel[1], 'func', function(val) self:SendReagentsMessage(val, nil) end, 'arg1', channel[2], 'closeWhenClicked', true ) else dewdrop:AddLine( 'text', channel[1], 'hasArrow', true, 'hasEditBox', true, 'tooltipTitle', channel[1], 'tooltipText', channel[3], 'editBoxFunc', function(channel, text) self:SendReagentsMessage(channel, text) end, 'editBoxArg1', channel[2] ) end end end ) end -- If the mod was disabled when WoW loaded, then the main frame will not be visible. So we'll make it visible again. if ( getglobal(frames.trade.elements.Main) and getglobal(frames.trade.elements.Main):IsShown() ) then cgc:TRADE_SKILL_SHOW() elseif ( getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown() ) then cgc:CRAFT_SHOW() end end function cgc:OnDisable() if self.frame then self.frame:Hide() end -- Clear our search history and current search text. self.clearHistory() self.searchText = "" -- Finally, update the trade/craft windows just in case we have any lingering search results. if ( self.hooks and self.hooks[frames.trade.update] ) then getglobal(frames.trade.update)() end if ( self.hooks and self.hooks[frames.craft.update] ) then getglobal(frames.craft.update)() end end function cgc:OnShow() self:Debug("OnShow called.") -- Insert previous search text, if any. if self.searchText ~= nil then self.frame.SearchBox:SetText(self.searchText) end self:Debug("OnShowCurrentWindow:"..getglobal(self.currentFrame.elements.Title):GetText()) -- Update the "Type" dropdown so that it reflects the current searchType or "Name" by default. if ( self.getSearchType() ~= nil ) then self.frame.SearchTypeButton:SetText(self.getSearchType()) else self.frame.SearchTypeButton:SetText(self.getSearchType(1)) end end function cgc:CRAFT_SHOW() self:Debug("Crafting window open.") -- first time window has been opened if ( not self.hooks or not self.hooks[frames.craft.update] ) then self:Debug("First time crafting window has opened, register close and hooking the update.") self:RegisterEvent("CRAFT_CLOSE", "OnClose") self:Hook(frames.craft.update, function () self:Update(true) end) end -- Have to set our current frame for the widgets that load. self.currentFrame = frames.craft -- Is the tradeskill window open? If so we'll need to close it. if ( getglobal(frames.trade.elements.Main) and getglobal(frames.trade.elements.Main):IsShown() ) then getglobal(frames.trade.elements.Main):Hide() end -- We need to dynmically position the addon because the trade/craft anchors are different. self.frame:ClearAllPoints() self.frame:SetPoint("TOPRIGHT", frames.craft.anchor, "BOTTOMRIGHT" , frames.craft.anchor_offset_x, frames.craft.anchor_offset_y) -- Check if the frame was already shown, which means they just changed tradeskills and no update with the OnShow. -- Otherwise, lets just show the frame. if ( self.frame:IsShown() ) then self:OnShow() else self.frame:Show() end -- Run our update. self:Update(true) end function cgc:TRADE_SKILL_SHOW() self:Debug("Tradeskill window open.") -- first time window has been opened if ( not self.hooks or not self.hooks[frames.trade.update] ) then self:Debug("First time trade skill window has opened, register close and hooking the update.") self:RegisterEvent("TRADE_SKILL_CLOSE", "OnClose") self:Hook(frames.trade.update, function () self:Update() end) -- Check if AutoCraft exists, if it does we're going to have to anchor to something different. if ( AutoCraftFrame ) then frames.trade.anchor = "AutoCraftRunAutomatically" frames.trade.anchor_offset_x = -7 end end -- Have to set our current frame for the widgets that load. self.currentFrame = frames.trade -- Is the crafting window open? If so we'll need to close it. if ( getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown() ) then getglobal(frames.craft.elements.Main):Hide() end -- We need to dynmically position the addon because the trade/craft anchors are different. self.frame:ClearAllPoints() self.frame:SetPoint("TOPLEFT", getglobal(frames.trade.anchor), "BOTTOMLEFT" , frames.trade.anchor_offset_x, frames.trade.anchor_offset_y) -- Check if the frame was already shown, which means they just changed tradeskills and no update with the OnShow. -- Otherwise, lets just show the frame. if ( self.frame:IsShown() ) then self:OnShow() else self.frame:Show() end -- Run the update. self:Update() end function cgc:OnClose() self:Debug("Tradeskill/Craft window close.") self.frame:Hide() end function cgc:Update(craft) self:Debug("cgc:Update called.") -- Update the search history and searh type dropdown self.setHistory(self.searchText) -- The user has changed their trade window, reset the search text if they haven't searched before if ( not self.lastSearchTrade or self.lastSearchTrade ~= getglobal(self.currentFrame.elements.Title):GetText() ) then -- Now we update last searched to the current trade/craft type/window name self.lastSearchTrade = getglobal(self.currentFrame.elements.Title):GetText() -- Does old text for the current window exist? if ( self.getHistory(self.lastSearchTrade) ) then self:Debug("Found history: "..self.lastSearchTrade) self.searchText = self.getHistory(self.lastSearchTrade) else self:Debug("No history, searchText=''") self.searchText = "" end -- Finally, update the actual searchbox. self.frame.SearchBox:SetText(self.searchText) end -- The user has decided to search for if ( self:GetSearchText() and getglobal(self.currentFrame.elements.Main):IsShown() ) then local searchType = self.getSearchType() local skillOffset = FauxScrollFrame_GetOffset(getglobal(self.currentFrame.elements.Scroll)) local skillButton = nil -- Keeps the list from being rebuilt unncessarily when the user is scrolling through search results. if ( self.found and getn(self.found) == 0 ) then if ( searchType == "Reagent" ) then -- search by reagent results self:BuildListByReagent(self:GetSearchText(), craft) elseif ( searchType == "Requires" ) then -- search by requires results self:BuildListByRequire(self:GetSearchText(), craft) else -- search by name results self:BuildListByName(self:GetSearchText(), craft) end end -- If we're doing tradeskills, we don't have categories, so we don't need a collapse. if ( not craft ) then getglobal(frames.trade.elements.CollapseAll):Disable(); end -- Update the scroll frame. FauxScrollFrame_Update(getglobal(self.currentFrame.elements.Scroll), getn(self.found), (craft and CRAFTS_DISPLAYED or TRADE_SKILLS_DISPLAYED), (craft and CRAFT_SKILL_HEIGHT or TRADE_SKILL_HEIGHT), nil, nil, nil, getglobal(self.currentFrame.elements.Highlight), 293, 316 ) getglobal(self.currentFrame.elements.Highlight):Hide() if ( getn(self.found) > 0 ) then -- Do the actual display of the list now. for i=1, (craft and CRAFTS_DISPLAYED or TRADE_SKILLS_DISPLAYED), 1 do local skillIndex = i + skillOffset skillButton = getglobal((craft and "Craft" or "TradeSkillSkill")..i) if ( i <= getn(self.found) ) then -- Set button widths if scrollbar is shown or hidden if ( getglobal(self.currentFrame.elements.Scroll):IsVisible() ) then skillButton:SetWidth(293) else skillButton:SetWidth(323) end self:Debug("self.found["..skillIndex.."].type="..self.found[skillIndex].type) local color = (craft and CraftTypeColor[self.found[skillIndex].type] or TradeSkillTypeColor[self.found[skillIndex].type]) if ( color ) then skillButton:SetTextColor(color.r, color.g, color.b) end skillButton:SetID(self.found[skillIndex].index) skillButton:Show() if ( self.found[skillIndex].name == "" ) then return end skillButton:SetNormalTexture("") getglobal((craft and "Craft" or "TradeSkillSkill")..i.."Highlight"):SetTexture("") if ( self.found[skillIndex].available == 0 ) then skillButton:SetText(" "..self.found[skillIndex].name) else skillButton:SetText(" ".. self.found[skillIndex].name .." [".. self.found[skillIndex].available .."]") end -- Place the highlight and lock the highlight state if ( (craft and GetCraftSelectionIndex() or GetTradeSkillSelectionIndex()) == self.found[skillIndex].index ) then getglobal(self.currentFrame.elements.Highlight):SetPoint("TOPLEFT", skillButton, "TOPLEFT", 0, 0) getglobal(self.currentFrame.elements.Highlight):Show() skillButton:LockHighlight() -- Setting the num avail so the create all button works for tradeskills if (not craft and getglobal(frames.trade.elements.Main)) then getglobal(self.currentFrame.elements.Main).numAvailable = self.found[skillIndex].available end else -- The highlight is shown, but it's on an entry that we haven't selected. Probably a remnant from a selection before we did our search, -- so we'll go ahead and hide the frame. if ( not self:SelectionInList(skillOffset, craft) ) then getglobal(self.currentFrame.elements.Highlight):Hide() end skillButton:UnlockHighlight() end else skillButton:Hide() end end else getglobal(self.currentFrame.elements.Scroll):Hide() for i=1, (craft and CRAFTS_DISPLAYED or TRADE_SKILLS_DISPLAYED), 1 do skillButton = getglobal((craft and "Craft" or "TradeSkillSkill")..i) skillButton:SetWidth(323) skillButton:SetTextColor(1, 1, 1) skillButton:SetID(1) skillButton:SetNormalTexture("") getglobal((craft and "Craft" or "TradeSkillSkill")..i.."Highlight"):Hide() skillButton:UnlockHighlight(); skillButton:Show() if ( i == 1 ) then getglobal(self.currentFrame.elements.Highlight):Hide() skillButton:SetText(self.LOCALS.FRAME_NO_RESULTS) else skillButton:SetText("") end end end else cgc:Debug("Calling original update functions:"..(craft and frames.craft.update or frames.trade.update)) self.hooks[ craft and frames.craft.update or frames.trade.update ].orig() end end ---------------------------------------- -- Retrieve the current searchText. function cgc:GetSearchText() -- The second argument is a search with only spaces. if ( self.searchText ~= nil and string.len(string.gsub(self.searchText, "%s", "")) > 0 ) then return self.searchText else return false end end ---------------------------------------- -- Begin the search and clear out the scrolling frame so it's not out of position. function cgc:Search(searchText) self:Debug("Search called; currentFrame="..self.currentFrame.elements.Main) self.searchText = self.frame.SearchBox:GetText() -- Need to reset / create our self.found array. self.found = {} self.frame.SearchBox:ClearFocus() -- We have to clear the offset on the scroll frame, otherwise we error out and it's misscrolled. -- self.currentFrame = (getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown() and "CraftListScrollFrame" or getglobal(frames.trade.elements.Main) and getglobal(frames.trade.elements.Main):IsShown() and "TradeSkillListScrollFrame" FauxScrollFrame_SetOffset(getglobal(self.currentFrame.elements.Main), 0) getglobal(self.currentFrame.elements.ScrollBar):SetValue(0) -- Finally, do the update. self:Update(getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown()) end ---------------------------------------- -- Reset the skill frames. function cgc:Reset() self.searchText = "" self.frame.SearchBox:ClearFocus(); self.frame.SearchBox:SetText(self.searchText); self.clearHistory() self:Update(getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown()) end --[[ ---------------------------------------------------------------------------------------------------- ]]-- -- Building functions which do the bulk work of this mod. They traverse through the current skill opened -- and check for any matches against the users requested searchText, or build chat links to be sent -- through SendChatMessage() --[[ ---------------------------------------------------------------------------------------------------- ]]-- ---------------------------------------- -- Build search list by item name. function cgc:BuildListByName(searchText, craft) local foundIndex = 0 self.found = {} if ( craft ) then self:Debug("BuildingListByName for crafting.") end local skillName, skillType, numAvailable, isExpanded for i=1, (craft and GetNumCrafts() or GetNumTradeSkills()), 1 do if ( craft ) then skillName, _, skillType, numAvailable, isExpanded = GetCraftInfo(i) else skillName, skillType, numAvailable, isExpanded = GetTradeSkillInfo(i) end if ( strfind(string.lower(skillName), string.lower(searchText)) and skillType ~= "header" ) then cgc:Debug("Match #"..foundIndex..": skillType="..skillType) foundIndex = foundIndex + 1 self.found[foundIndex] = {} self.found[foundIndex] = { name = skillName, type = skillType, available = numAvailable, index = i } elseif ( skillType == "header" and not isExpanded ) then -- We need to expand any unexpanded header types, otherwise we can't parse their sub data. ExpandTradeSkillSubClass(i) end end self:Debug("We found ".. foundIndex .." matches.") end ---------------------------------------- -- Build search list by required. function cgc:BuildListByRequire(searchText, craft) local foundIndex = 0 self.found = {} local skillName, skillType, numAvailable, isExpanded local requires for i=1, (craft and GetNumCrafts() or GetNumTradeSkills()), 1 do if ( craft ) then skillName, _, skillType, numAvailable, isExpanded = GetCraftInfo(i) requires = GetCraftSpellFocus(i) else skillName, skillType, numAvailable, isExpanded = GetTradeSkillInfo(i) requires = GetTradeSkillTools(i) end if ( requires and strfind(string.lower(BuildColoredListString(requires)), string.lower(searchText)) and skillType ~= "header" ) then self:Debug("Found matching require for '"..searchText.."': "..requires.." ") foundIndex = foundIndex + 1 self.found[foundIndex] = {} self.found[foundIndex] = { name = skillName, type = skillType, available = numAvailable, index = i } elseif ( skillType == "header" and not isExpanded ) then -- We need to expand any unexpanded header types, otherwise we can't parse their sub data. ExpandTradeSkillSubClass(i) end end end ---------------------------------------- -- Build search list reagent name. function cgc:BuildListByReagent(searchText, craft) local foundIndex = 0 self.found = {} local skillName, skillType, numAvailable, isExpanded, reagentName for i=1, (craft and GetNumCrafts() or GetNumTradeSkills()), 1 do if ( craft ) then skillName, _, skillType, numAvailable, isExpanded = GetCraftInfo(i) else skillName, skillType, numAvailable, isExpanded = GetTradeSkillInfo(i) end if ( skillType ~= "header" ) then for e=1, (craft and GetCraftNumReagents(i) or GetTradeSkillNumReagents(i)), 1 do if ( craft ) then reagentName, _, _, _ = GetCraftReagentInfo(i, e) else reagentName, _, _, _ = GetTradeSkillReagentInfo(i, e) end if ( reagentName and strfind(string.lower(reagentName), string.lower(searchText)) ) then foundIndex = foundIndex + 1 self.found[foundIndex] = {} self.found[foundIndex] = { name = skillName, type = skillType, available = numAvailable, index = i } -- Some reagents can share a similar name so if we already matched one, we can break here. break end end elseif ( skillType == "header" and not isExpanded ) then -- We need to expand any unexpanded header types, otherwise we can't parse their sub data. ExpandTradeSkillSubClass(i) end end end ---------------------------------------- -- Utility function to reagent information to chat. function cgc:SendReagentsMessage(channel, who) local sIndex, itemString local tempString = "" local reagentLinks = {} local reagentCounts = {} local craft = getglobal(frames.craft.elements.Main) and getglobal(frames.craft.elements.Main):IsShown() -- Figure out which window is open or exit function if ( getglobal(self.currentFrame.elements.Main):IsShown() ) then sIndex = craft and GetCraftSelectionIndex() or GetTradeSkillSelectionIndex() self:Debug("SRM: GetTradeSkillSelectionIndex="..GetTradeSkillSelectionIndex()) else return end self:Debug("SRM: sIndex = "..sIndex) -- Double check the user has a skill selected. if ( sIndex > 0 ) then -- Insert the name first. itemString = craft and GetCraftItemLink(sIndex) or GetTradeSkillItemLink(sIndex) -- Cycle through all the reagents and get the required amounts for each into two nice arrays for rIndex=1, (craft and GetCraftNumReagents(sIndex) or GetTradeSkillNumReagents(sIndex)), 1 do if ( craft ) then reagentLinks[rIndex] = GetCraftReagentItemLink(sIndex, rIndex) _, _, reagentCounts[rIndex], _ = GetCraftReagentInfo(sIndex, rIndex) else reagentLinks[rIndex] = GetTradeSkillReagentItemLink(sIndex, rIndex) _, _, reagentCounts[rIndex], _ = GetTradeSkillReagentInfo(sIndex, rIndex) end end -- Now we'll make strings out of them, 4 reagent links at a time and print them out when we reach our limit. for i=1, getn(reagentLinks) do tempString = tostring(tempString) .. reagentLinks[i] .. "x" .. reagentCounts[i] .. " " if ( mod(i,3) == 0 or i == getn(reagentLinks) ) then -- Combine the item name, add (cont) if this is the second go round. tempString = itemString .. (i > 3 and " (cont) = " or " = ") .. tempString SendChatMessage(tempString, channel, GetDefaultLanguage("player"), who) tempString = "" end end end end ---------------------------------------- -- Utility function for Update(): checks to see if the selected item is currently visible in the scrolling frame. function cgc:SelectionInList(skillOffset, craft) for i=skillOffset+1, skillOffset+(craft and CRAFTS_DISPLAYED or TRADE_SKILLS_DISPLAYED), 1 do if ( self.found[i] and self.found[i].index == (craft and GetCraftSelectionIndex() or GetTradeSkillSelectionIndex()) ) then return true end end return false end