Aaron@4: --[[--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) Aaron@4: Aaron@4: RecipeProfit by -[@project-author@]- Aaron@4: Aaron@4: Rev: @project-revision@ Aaron@4: Updated: @file-date-iso@ Aaron@4: Aaron@4: --))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) Aaron@4: Aaron@4: http://www.wrathguides.com/ Aaron@4: Aaron@4: --]]--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--)) Aaron@4: Aaron@12: local RecipeProfit = LibStub("AceAddon-3.0"):NewAddon("RecipeProfit", "AceEvent-3.0", "AceConsole-3.0") Aaron@0: local GatherMate = LibStub("AceAddon-3.0"):GetAddon("GatherMate") Aaron@0: local tabletest = {} Aaron@16: local db = {} Aaron@1: local safeRecipes = {} Aaron@16: local ids = {} Aaron@16: Aaron@17: local profile Aaron@17: Aaron@0: RecipeProfit.db = db; Aaron@0: Aaron@17: --[[ Forward Definitions (for local functions) ]] Aaron@16: local get_faction_db, Aaron@16: add_note, Aaron@16: button_update, Aaron@16: find_good_id, Aaron@16: safe_cache_vendor, Aaron@17: get_note_title, Aaron@17: get_next_texture_id, Aaron@17: set_node_constants, Aaron@17: inject_options; Aaron@16: Aaron@17: --[[ Deep table inspection for debugging ]] Aaron@0: function debugprint(val, indent) Aaron@0: indent = indent or ""; Aaron@0: if not(type(val) == "table") then Aaron@0: print("Not table: " .. val) Aaron@0: return Aaron@0: end Aaron@0: Aaron@0: for k,v in pairs(val) do Aaron@0: if(type(k) == "table" and type(v) == "table") then Aaron@0: print(indent .. "table key: {") Aaron@0: debugprint(k, indent .. " ") Aaron@0: print(indent .. "} = {") Aaron@0: debugprint(v, indent .. " ") Aaron@0: print(indent .. "}") Aaron@12: elseif(type(v) == "table") then Aaron@0: print(indent .. k .. " = {") Aaron@0: debugprint(v, indent .. " ") Aaron@0: print(indent .. "}") Aaron@0: else Aaron@12: if(type(v) ~= "boolean") then Aaron@12: print(indent .. k .. " = " .. v) Aaron@12: else Aaron@12: print(indent .. k .. " = " .. (v and "true" or "false")) Aaron@12: end Aaron@0: end Aaron@0: end Aaron@0: end Aaron@8: Aaron@7: local defaultProfile = { Aaron@7: ["show"] = { Aaron@7: ["RecipeProfit"] = "always", Aaron@7: ["Herb Gathering"] = "never", Aaron@7: ["Extract Gas"] = "never", Aaron@7: ["Fishing"] = "never", Aaron@7: ["Mining"] = "never", Aaron@7: ["Treasure"] = "never", Aaron@7: }, Aaron@8: ["trackShow"] = "active", Aaron@7: } Aaron@0: Aaron@0: local options = { Aaron@0: type = "group", Aaron@0: name = "RecipeProfit", -- addon name to import from, don't localize Aaron@0: handler = {}, Aaron@0: disabled = false, Aaron@0: args = { Aaron@1: opt = { Aaron@0: order = 1, Aaron@0: name = "Select Database", Aaron@0: desc = "Show a different database", Aaron@0: type = "group", Aaron@0: guiInline = true, Aaron@0: args = { Aaron@0: faction = { Aaron@0: order = 0, Aaron@0: name = "Faction", Aaron@0: desc = "Show a different database.", Aaron@0: type = "select", Aaron@0: values = { Aaron@0: ["Alliance"] = "Alliance", Aaron@0: ["Horde"] = "Horde", Aaron@1: ["default"] = "Default", Aaron@0: }, Aaron@0: arg = "faction", Aaron@0: }, Aaron@1: Aaron@1: safeBuy = { Aaron@1: order = 1, Aaron@1: name = "Safe Recipe Buy", Aaron@1: desc = "Warn when buying a recipe not on the RecipeProfit list.", Aaron@1: type = "select", Aaron@1: values = { Aaron@7: --["on"] = "On", Aaron@1: ["off"]= "Off", Aaron@1: }, Aaron@1: arg = "safebuy", Aaron@1: }, Aaron@0: }, Aaron@1: get = function(k) return db.profile[k.arg]; end, Aaron@0: set = function(k, v) db.profile[k.arg] = v; RecipeProfit:DoMerge(); end, Aaron@0: }, Aaron@0: loadData = { Aaron@0: order = 8, Aaron@0: name = "Import Data", Aaron@0: desc = "Load RecipeProfit and import the data to your database.", Aaron@0: type = "execute", Aaron@0: func = function() Aaron@0: RecipeProfit:DoMerge() Aaron@0: end Aaron@0: }, Aaron@7: loadProfile = { Aaron@7: order = 9, Aaron@7: name = "Load RecipeProfit Profile", Aaron@7: desc = "Loads the RecipeProfit Profile into Gathermate for easy recipe tracking.", Aaron@7: type = "execute", Aaron@7: func = function() Aaron@7: GatherMate.db.profiles["RecipeProfit"] = GatherMate.db.profiles["RecipeProfit"] or {} Aaron@7: gmdb = GatherMate.db.profiles["RecipeProfit"] Aaron@7: for k, v in pairs(defaultProfile) do Aaron@7: gmdb[k] = v; Aaron@7: end Aaron@7: GatherMate:SendMessage("OnProfileChanged"); Aaron@7: GatherMate:GetModule("Config"):UpdateConfig() Aaron@7: GatherMate:SendMessage("GatherMateConfigChanged") Aaron@7: GatherMate.db:SetProfile("RecipeProfit") Aaron@7: end Aaron@7: }, Aaron@0: } Aaron@0: } Aaron@0: Aaron@0: local defaults = { Aaron@1: faction = "default", Aaron@1: safebuy = "on", Aaron@16: Aaron@16: --submitting cached data not yet implemented Aaron@16: enable_cache = false, Aaron@16: location_cache = {}, Aaron@0: } Aaron@0: Aaron@0: function RecipeProfit:OnInitialize() Aaron@17: profile = RECIPEPROFIT_profile or defaults Aaron@7: Aaron@1: for k, v in pairs(defaults) do Aaron@1: profile[k] = profile[k] or v; Aaron@1: end Aaron@1: Aaron@12: self:RegisterChatCommand("recipeprofit", "ShowOptions") Aaron@12: self:RegisterChatCommand("rp", "ShowOptions") Aaron@12: self:RegisterChatCommand("profit", "ShowOptions") Aaron@12: Aaron@0: db.profile = profile Aaron@0: db.storage = {} Aaron@0: Aaron@0: GatherMate:GetModule("Config"):RegisterModule("RecipeProfit", options) Aaron@0: GatherMate:RegisterDBType("RecipeProfit", db.storage) Aaron@8: GatherMate.db.profile.show["RecipeProfit"] = GatherMate.db.profile.show["RecipeProfit"] or "always" Aaron@0: Aaron@17: set_node_constants() Aaron@17: inject_options() Aaron@8: Aaron@0: GatherMate:GetModule("Config"):UpdateConfig() Aaron@0: GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged") Aaron@0: end Aaron@0: Aaron@17: Aaron@17: function RecipeProfit:OnEnable() Aaron@17: Aaron@17: _G["MerchantPrevPageButton"]:HookScript("OnClick", self.UpdateButtons) Aaron@17: _G["MerchantNextPageButton"]:HookScript("OnClick", self.UpdateButtons) Aaron@17: Aaron@17: self:RegisterEvent("MERCHANT_SHOW", "UpdateButtons") Aaron@17: self:RegisterEvent("MERCHANT_UPDATE", "UpdateButtons") Aaron@17: self:RegisterEvent("BAG_UPDATE", "UpdateButtons") Aaron@17: Aaron@17: RecipeProfit:DoMerge() Aaron@17: end Aaron@17: Aaron@12: function RecipeProfit:ShowOptions() Aaron@13: LibStub("AceConfigDialog-3.0"):Open("GatherMate") Aaron@13: LibStub("AceConfigDialog-3.0"):SelectGroup("GatherMate", "RecipeProfit") Aaron@12: end Aaron@12: Aaron@16: function RecipeProfit:UpdateButtons(event, ...) Aaron@16: --print("UpdateButtons", event) Aaron@16: if(not MerchantFrame:IsVisible()) then Aaron@16: --print("UpdateButtons - (Event: ", event, ") - MerchantFrame not visible."); Aaron@16: return; Aaron@16: end Aaron@16: Aaron@16: for i=1, MERCHANT_ITEMS_PER_PAGE, 1 do Aaron@16: local buttonframe = _G["MerchantItem"..i]; Aaron@16: local index = (((MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE) + i); Aaron@16: --print(index) Aaron@16: if index <= GetMerchantNumItems() then Aaron@16: button_update(buttonframe) Aaron@16: end Aaron@16: end Aaron@17: end Aaron@16: Aaron@16: function RecipeProfit:DoMerge() Aaron@16: ids = {} Aaron@16: local selectedDB = get_faction_db(); Aaron@16: Aaron@16: GatherMate:ClearDB("RecipeProfit") Aaron@16: for id, note in pairs(selectedDB) do Aaron@16: x, y = find_good_id(note.x, note.y) Aaron@16: add_note(x, y, note) Aaron@16: end Aaron@16: Aaron@16: GatherMate:SendMessage("GatherMateDataImport") Aaron@16: GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged") Aaron@16: end Aaron@16: Aaron@16: function get_note_title(note, factionTag) Aaron@16: if(not factionTag) then Aaron@16: _, factionTag = get_faction_db(); Aaron@16: end Aaron@16: Aaron@16: return note.item.." - ("..note.vendor.." ".. factionTag ..")"; Aaron@16: end Aaron@16: Aaron@16: function add_note(x, y, note) Aaron@16: GatherMate:AddNode(note.map, x / 100, y / 100, "RecipeProfit", get_note_title(note)); Aaron@16: end Aaron@16: Aaron@16: function get_faction_db() Aaron@16: local factionAlliance = db.profile.faction == "Alliance" or Aaron@16: db.profile.faction == "default" and UnitFactionGroup("player") == "Alliance"; Aaron@16: if(factionAlliance) then Aaron@16: return RECIPEPROFIT_alliance, "A"; Aaron@16: else Aaron@16: return RECIPEPROFIT_horde, "H"; Aaron@16: end Aaron@16: end Aaron@16: Aaron@16: function safe_cache_vendor() Aaron@16: if(not profile.enable_cache) then Aaron@16: return Aaron@16: end Aaron@16: Aaron@16: if(not profile.location_cache[UnitName("NPC")]) then Aaron@16: SetMapToCurrentZone() Aaron@16: local pos = {} Aaron@16: pos.x, pos.y = GetPlayerMapPosition("player") Aaron@16: profile.location_cache[UnitName("NPC")] = pos Aaron@16: end Aaron@16: end Aaron@15: Aaron@9: function button_update(self) Aaron@9: local buttonName = _G[self:GetName().."Name"]; Aaron@9: local link = GetMerchantItemLink(_G[self:GetName().."ItemButton"]:GetID()); Aaron@9: if(not link) then Aaron@9: return; Aaron@9: end Aaron@9: Aaron@9: local sName, sLink, iRarity, iLevel, iMinLevel, sType, sSubType, iStackCount = GetItemInfo(link) Aaron@9: Aaron@16: if(sType == "Recipe" and safeRecipes[sName]) then Aaron@16: safe_cache_vendor(); Aaron@9: SetItemButtonNameFrameVertexColor(self, 0, 0, 1.0); Aaron@9: SetItemButtonSlotVertexColor(self, 0, 0, 0.5); Aaron@9: buttonName:SetText("* " .. sName) Aaron@9: if(GetItemCount(link, true) == 0) then Aaron@9: buttonName:SetTextColor(0,1,1); Aaron@9: elseif(GetItemCount(link, true) < 5) then Aaron@9: buttonName:SetTextColor(1,0,1); Aaron@9: else Aaron@9: buttonName:SetTextColor(1,0,0); Aaron@9: end Aaron@9: else Aaron@9: buttonName:SetTextColor(GameFontNormalSmall:GetTextColor()); Aaron@9: end Aaron@9: end Aaron@9: Aaron@16: function find_good_id(x, y) Aaron@0: if ids[x.." "..y] then Aaron@16: return find_good_id(x + .01, y) Aaron@0: end Aaron@0: Aaron@0: ids[x.." "..y] = true Aaron@0: return x, y Aaron@17: end Aaron@17: Aaron@17: local lastNodeTextureId = 0; Aaron@17: Aaron@17: function get_next_texture_id() Aaron@17: lastNodeTextureId = lastNodeTextureId + 1; Aaron@17: return lastNodeTextureId; Aaron@17: end Aaron@17: Aaron@17: function set_node_constants() Aaron@17: GatherMate.nodeIDs["RecipeProfit"] = {} Aaron@17: GatherMate.nodeTextures["RecipeProfit"] = {} Aaron@17: GatherMate.nodeMinHarvest["RecipeProfit"] = {} Aaron@17: Aaron@17: local nodes = GatherMate.nodeIDs["RecipeProfit"] Aaron@17: for id, note in pairs(RECIPEPROFIT_alliance) do Aaron@17: safeRecipes[note.item] = true; Aaron@17: nodes[get_note_title(note, "A")] = get_next_texture_id() Aaron@17: end Aaron@17: Aaron@17: for id, note in pairs(RECIPEPROFIT_horde) do Aaron@17: safeRecipes[note.item] = true; Aaron@17: nodes[get_note_title(note, "H")] = get_next_texture_id() Aaron@17: end Aaron@17: Aaron@17: for i = 1, lastNodeTextureId, 1 do Aaron@17: GatherMate.nodeTextures["RecipeProfit"][i] = "Interface\\Icons\\INV_Scroll_05" Aaron@17: end Aaron@17: Aaron@17: GatherMate.reverseNodeIDs["RecipeProfit"] = GatherMate:CreateReversedTable(nodes) Aaron@17: end Aaron@17: Aaron@17: function inject_options() Aaron@17: GatherMate:GetModule("Config").options.args.display.args.general.args.showGroup.args["showRecipeProfit"] = { Aaron@17: order = 6, Aaron@17: name = "Show RecipeProfit nodes.", Aaron@17: desc = "Toggle showing nodes added by RecipeProfit.", Aaron@17: type = "select", Aaron@17: values = { Aaron@17: ["always"] = "Always show", Aaron@17: ["never"] = "Never show", Aaron@17: }, Aaron@17: arg = "RecipeProfit", Aaron@17: } Aaron@17: Aaron@17: GatherMate:GetModule("Config").options.args.display.args.general.args.iconGroup.args.tracking.args["showRecipeProfit"] = { Aaron@17: order = 6.5, Aaron@17: name = "RecipeProfit", Aaron@17: desc = "Color of the tracking circle.", Aaron@17: type = "color", Aaron@17: hasAlpha = true, Aaron@17: arg = "RecipeProfit", Aaron@17: } Aaron@17: end