--[[--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) RecipeProfit by -[@project-author@]- Rev: @project-revision@ Updated: @file-date-iso@ --))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) URL: http://www.wrathguides.com/ License: This file is a part of "RecipeProfit for GatherMate." This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see . Note: This program's source code is specifically designed to work with World of Warcraft's interpreted AddOn system. You have an implicit license to use this program with these facilities since that is it's designated purpose as per: http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat --]]--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) local RecipeProfit = LibStub("AceAddon-3.0"):NewAddon("RecipeProfit", "AceEvent-3.0", "AceConsole-3.0") local GatherMate = LibStub("AceAddon-3.0"):GetAddon("GatherMate") local tabletest = {} local db = {} local safeRecipes = {} local ids = {} local nodeLookup = {} local profile RecipeProfit.db = db; --[[ Forward Definitions (for local functions) ]] local get_faction_db, add_note, button_update, find_good_id, safe_cache_vendor, get_note_title, get_next_texture_id, set_node_constants, get_colored_note_name, inject_options; --[[ Deep table inspection for debugging ]] function debugprint(val, indent) indent = indent or ""; if not(type(val) == "table") then print("Not table: " .. val) return end for k,v in pairs(val) do if(type(k) == "table" and type(v) == "table") then print(indent .. "table key: {") debugprint(k, indent .. " ") print(indent .. "} = {") debugprint(v, indent .. " ") print(indent .. "}") elseif(type(v) == "table") then print(indent .. k .. " = {") debugprint(v, indent .. " ") print(indent .. "}") else if(type(v) ~= "boolean") then print(indent .. k .. " = " .. v) else print(indent .. k .. " = " .. (v and "true" or "false")) end end end end local defaultProfile = { ["show"] = { ["RecipeProfit"] = "always", ["Herb Gathering"] = "never", ["Extract Gas"] = "never", ["Fishing"] = "never", ["Mining"] = "never", ["Treasure"] = "never", }, ["trackShow"] = "active", } local options = { type = "group", name = "RecipeProfit", -- addon name to import from, don't localize handler = {}, disabled = false, args = { opt = { order = 1, name = "Select Database", desc = "Show a different database", type = "group", guiInline = true, args = { faction = { order = 0, name = "Faction", desc = "Show a different database.", type = "select", values = { ["Alliance"] = "Alliance", ["Horde"] = "Horde", ["default"] = "Default", }, arg = "faction", }, safeBuy = { order = 1, name = "Safe Recipe Buy", desc = "Warn when buying a recipe not on the RecipeProfit list.", type = "select", values = { --["on"] = "On", ["off"]= "Off", }, arg = "safebuy", }, }, get = function(k) return db.profile[k.arg]; end, set = function(k, v) db.profile[k.arg] = v; RecipeProfit:DoMerge(); end, }, loadData = { order = 8, name = "Import Data", desc = "Load RecipeProfit and import the data to your database.", type = "execute", func = function() RecipeProfit:DoMerge() end }, loadProfile = { order = 9, name = "Load RecipeProfit Profile", desc = "Loads the RecipeProfit Profile into Gathermate for easy recipe tracking.", type = "execute", func = function() GatherMate.db.profiles["RecipeProfit"] = GatherMate.db.profiles["RecipeProfit"] or {} gmdb = GatherMate.db.profiles["RecipeProfit"] for k, v in pairs(defaultProfile) do gmdb[k] = v; end GatherMate:SendMessage("OnProfileChanged"); GatherMate:GetModule("Config"):UpdateConfig() GatherMate:SendMessage("GatherMateConfigChanged") GatherMate.db:SetProfile("RecipeProfit") end }, } } local defaults = { faction = "default", safebuy = "on", --submitting cached data not yet implemented enable_cache = false, location_cache = {}, } function RecipeProfit:OnInitialize() profile = RECIPEPROFIT_profile or defaults for k, v in pairs(defaults) do profile[k] = profile[k] or v; end self:RegisterChatCommand("recipeprofit", "ShowOptions") self:RegisterChatCommand("rp", "ShowOptions") self:RegisterChatCommand("profit", "ShowOptions") db.profile = profile db.storage = {} GatherMate:GetModule("Config"):RegisterModule("RecipeProfit", options) GatherMate:RegisterDBType("RecipeProfit", db.storage) GatherMate.db.profile.show["RecipeProfit"] = GatherMate.db.profile.show["RecipeProfit"] or "always" set_node_constants() inject_options() GatherMate:GetModule("Config"):UpdateConfig() GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged") --[[ hook GetNameForNode for custom highlighting ]] local oldFunction = GatherMate.GetNameForNode GatherMate.GetNameForNode = function(lself, type, nodeID) if(type == "RecipeProfit") then return get_colored_note_name(lself, nodeID) else return oldFunction(lself, type, nodeID) end end end function RecipeProfit:OnEnable() _G["MerchantPrevPageButton"]:HookScript("OnClick", self.UpdateButtons) _G["MerchantNextPageButton"]:HookScript("OnClick", self.UpdateButtons) self:RegisterEvent("MERCHANT_SHOW", "UpdateButtons") self:RegisterEvent("MERCHANT_UPDATE", "UpdateButtons") self:RegisterEvent("BAG_UPDATE", "UpdateButtons") RecipeProfit:DoMerge() end function RecipeProfit:ShowOptions() LibStub("AceConfigDialog-3.0"):Open("GatherMate") LibStub("AceConfigDialog-3.0"):SelectGroup("GatherMate", "RecipeProfit") end function RecipeProfit:UpdateButtons(event, ...) --print("UpdateButtons", event) if(not MerchantFrame:IsVisible()) then --print("UpdateButtons - (Event: ", event, ") - MerchantFrame not visible."); return; end for i=1, MERCHANT_ITEMS_PER_PAGE, 1 do local buttonframe = _G["MerchantItem"..i]; local index = (((MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE) + i); --print(index) if index <= GetMerchantNumItems() then button_update(buttonframe) end end end function RecipeProfit:DoMerge() ids = {} local selectedDB = get_faction_db(); GatherMate:ClearDB("RecipeProfit") for id, note in pairs(selectedDB) do x, y = find_good_id(note.x, note.y) add_note(x, y, note) end GatherMate:SendMessage("GatherMateDataImport") GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged") end function get_note_title(note, factionTag) if(not factionTag) then _, factionTag = get_faction_db(); end return note.item.." - ("..note.vendor.." ".. factionTag ..")"; end function add_note(x, y, note) GatherMate:AddNode(note.map, x / 100, y / 100, "RecipeProfit", get_note_title(note)); end function get_faction_db() local factionAlliance = db.profile.faction == "Alliance" or db.profile.faction == "default" and UnitFactionGroup("player") == "Alliance"; if(factionAlliance) then return RECIPEPROFIT_alliance, "A"; else return RECIPEPROFIT_horde, "H"; end end function safe_cache_vendor() if(not profile.enable_cache) then return end if(not profile.location_cache[UnitName("NPC")]) then SetMapToCurrentZone() local pos = {} pos.x, pos.y = GetPlayerMapPosition("player") profile.location_cache[UnitName("NPC")] = pos end end function button_update(self) local buttonName = _G[self:GetName().."Name"]; local link = GetMerchantItemLink(_G[self:GetName().."ItemButton"]:GetID()); if(not link) then return; end local sName, sLink, iRarity, iLevel, iMinLevel, sType, sSubType, iStackCount = GetItemInfo(link) if(sType == "Recipe" and safeRecipes[sName]) then safe_cache_vendor(); SetItemButtonNameFrameVertexColor(self, 0, 0, 1.0); SetItemButtonSlotVertexColor(self, 0, 0, 0.5); buttonName:SetText("* " .. sName) if(GetItemCount(link, true) == 0) then buttonName:SetTextColor(0,1,1); elseif(GetItemCount(link, true) < 5) then buttonName:SetTextColor(1,0,1); else buttonName:SetTextColor(1,0,0); end else buttonName:SetTextColor(GameFontNormalSmall:GetTextColor()); end end function find_good_id(x, y) if ids[x.." "..y] then return find_good_id(x + .01, y) end ids[x.." "..y] = true return x, y end local lastNodeTextureId = 0; function get_next_texture_id() lastNodeTextureId = lastNodeTextureId + 1; return lastNodeTextureId; end function set_node_constants() GatherMate.nodeIDs["RecipeProfit"] = {} GatherMate.nodeTextures["RecipeProfit"] = {} GatherMate.nodeMinHarvest["RecipeProfit"] = {} local nodes = GatherMate.nodeIDs["RecipeProfit"] for id, note in pairs(RECIPEPROFIT_alliance) do safeRecipes[note.item] = true; local id = get_next_texture_id(); nodes[get_note_title(note, "A")] = id; nodeLookup[id] = note; end for id, note in pairs(RECIPEPROFIT_horde) do safeRecipes[note.item] = true; local id = get_next_texture_id(); nodes[get_note_title(note, "H")] = id; nodeLookup[id] = note; end for i = 1, lastNodeTextureId, 1 do GatherMate.nodeTextures["RecipeProfit"][i] = "Interface\\Icons\\INV_Scroll_05" end GatherMate.reverseNodeIDs["RecipeProfit"] = GatherMate:CreateReversedTable(nodes) end function inject_options() GatherMate:GetModule("Config").options.args.display.args.general.args.showGroup.args["showRecipeProfit"] = { order = 6, name = "Show RecipeProfit nodes.", desc = "Toggle showing nodes added by RecipeProfit.", type = "select", values = { ["always"] = "Always show", ["never"] = "Never show", }, arg = "RecipeProfit", } GatherMate:GetModule("Config").options.args.display.args.general.args.iconGroup.args.tracking.args["showRecipeProfit"] = { order = 6.5, name = "RecipeProfit", desc = "Color of the tracking circle.", type = "color", hasAlpha = true, arg = "RecipeProfit", } end function get_colored_note_name(self, nodeID) local text = self.reverseNodeIDs["RecipeProfit"][nodeID] local sName, sLink, iRarity, iLevel, iMinLevel, sType, sSubType, iStackCount = GetItemInfo(nodeLookup[nodeID].itementry) if(not sLink) then return text end local count = GetItemCount(sLink, true) local prefix = "|cFF888888(" .. count .. ") |cFF66DD66" if(count == 0) then prefix = "|cFF00FFFF(" .. count .. ") |cFF66DD66" elseif(count >= 5) then prefix = "|cFFFF0000(" .. count .. ") |cFF66DD66" end return prefix .. text end