|
Aaron@4
|
1 --[[--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))
|
|
Aaron@4
|
2
|
|
Aaron@4
|
3 RecipeProfit by -[@project-author@]-
|
|
Aaron@4
|
4
|
|
Aaron@4
|
5 Rev: @project-revision@
|
|
Aaron@4
|
6 Updated: @file-date-iso@
|
|
Aaron@4
|
7
|
|
Aaron@4
|
8 --))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))
|
|
Aaron@4
|
9
|
|
Aaron@22
|
10 URL:
|
|
Aaron@22
|
11 http://www.wrathguides.com/
|
|
Aaron@22
|
12
|
|
Aaron@22
|
13 License:
|
|
Aaron@22
|
14 This file is a part of "RecipeProfit for GatherMate."
|
|
Aaron@22
|
15
|
|
Aaron@22
|
16 This program is free software; you can redistribute it and/or
|
|
Aaron@22
|
17 modify it under the terms of the GNU General Public License
|
|
Aaron@22
|
18 as published by the Free Software Foundation, either version 3
|
|
Aaron@22
|
19 of the License, or (at your option) any later version.
|
|
Aaron@22
|
20
|
|
Aaron@22
|
21 This program is distributed in the hope that it will be useful,
|
|
Aaron@22
|
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Aaron@22
|
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Aaron@22
|
24 GNU General Public License for more details.
|
|
Aaron@22
|
25
|
|
Aaron@22
|
26 You should have received a copy of the GNU General Public License
|
|
Aaron@22
|
27 along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
|
Aaron@22
|
28
|
|
Aaron@22
|
29 Note:
|
|
Aaron@22
|
30 This program's source code is specifically designed to work with
|
|
Aaron@22
|
31 World of Warcraft's interpreted AddOn system.
|
|
Aaron@22
|
32
|
|
Aaron@22
|
33 You have an implicit license to use this program with these facilities
|
|
Aaron@22
|
34 since that is it's designated purpose as per:
|
|
Aaron@22
|
35 http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat
|
|
Aaron@4
|
36
|
|
Aaron@4
|
37 --]]--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))--))
|
|
Aaron@4
|
38
|
|
Aaron@22
|
39
|
|
Aaron@12
|
40 local RecipeProfit = LibStub("AceAddon-3.0"):NewAddon("RecipeProfit", "AceEvent-3.0", "AceConsole-3.0")
|
|
Aaron@0
|
41 local GatherMate = LibStub("AceAddon-3.0"):GetAddon("GatherMate")
|
|
Aaron@0
|
42 local tabletest = {}
|
|
Aaron@16
|
43 local db = {}
|
|
Aaron@1
|
44 local safeRecipes = {}
|
|
Aaron@16
|
45 local ids = {}
|
|
Aaron@16
|
46
|
|
Aaron@17
|
47 local profile
|
|
Aaron@17
|
48
|
|
Aaron@0
|
49 RecipeProfit.db = db;
|
|
Aaron@0
|
50
|
|
Aaron@17
|
51 --[[ Forward Definitions (for local functions) ]]
|
|
Aaron@16
|
52 local get_faction_db,
|
|
Aaron@16
|
53 add_note,
|
|
Aaron@16
|
54 button_update,
|
|
Aaron@16
|
55 find_good_id,
|
|
Aaron@16
|
56 safe_cache_vendor,
|
|
Aaron@17
|
57 get_note_title,
|
|
Aaron@17
|
58 get_next_texture_id,
|
|
Aaron@17
|
59 set_node_constants,
|
|
Aaron@17
|
60 inject_options;
|
|
Aaron@16
|
61
|
|
Aaron@17
|
62 --[[ Deep table inspection for debugging ]]
|
|
Aaron@0
|
63 function debugprint(val, indent)
|
|
Aaron@0
|
64 indent = indent or "";
|
|
Aaron@0
|
65 if not(type(val) == "table") then
|
|
Aaron@0
|
66 print("Not table: " .. val)
|
|
Aaron@0
|
67 return
|
|
Aaron@0
|
68 end
|
|
Aaron@0
|
69
|
|
Aaron@0
|
70 for k,v in pairs(val) do
|
|
Aaron@0
|
71 if(type(k) == "table" and type(v) == "table") then
|
|
Aaron@0
|
72 print(indent .. "table key: {")
|
|
Aaron@0
|
73 debugprint(k, indent .. " ")
|
|
Aaron@0
|
74 print(indent .. "} = {")
|
|
Aaron@0
|
75 debugprint(v, indent .. " ")
|
|
Aaron@0
|
76 print(indent .. "}")
|
|
Aaron@12
|
77 elseif(type(v) == "table") then
|
|
Aaron@0
|
78 print(indent .. k .. " = {")
|
|
Aaron@0
|
79 debugprint(v, indent .. " ")
|
|
Aaron@0
|
80 print(indent .. "}")
|
|
Aaron@0
|
81 else
|
|
Aaron@12
|
82 if(type(v) ~= "boolean") then
|
|
Aaron@12
|
83 print(indent .. k .. " = " .. v)
|
|
Aaron@12
|
84 else
|
|
Aaron@12
|
85 print(indent .. k .. " = " .. (v and "true" or "false"))
|
|
Aaron@12
|
86 end
|
|
Aaron@0
|
87 end
|
|
Aaron@0
|
88 end
|
|
Aaron@0
|
89 end
|
|
Aaron@8
|
90
|
|
Aaron@7
|
91 local defaultProfile = {
|
|
Aaron@7
|
92 ["show"] = {
|
|
Aaron@7
|
93 ["RecipeProfit"] = "always",
|
|
Aaron@7
|
94 ["Herb Gathering"] = "never",
|
|
Aaron@7
|
95 ["Extract Gas"] = "never",
|
|
Aaron@7
|
96 ["Fishing"] = "never",
|
|
Aaron@7
|
97 ["Mining"] = "never",
|
|
Aaron@7
|
98 ["Treasure"] = "never",
|
|
Aaron@7
|
99 },
|
|
Aaron@8
|
100 ["trackShow"] = "active",
|
|
Aaron@7
|
101 }
|
|
Aaron@0
|
102
|
|
Aaron@0
|
103 local options = {
|
|
Aaron@0
|
104 type = "group",
|
|
Aaron@0
|
105 name = "RecipeProfit", -- addon name to import from, don't localize
|
|
Aaron@0
|
106 handler = {},
|
|
Aaron@0
|
107 disabled = false,
|
|
Aaron@0
|
108 args = {
|
|
Aaron@1
|
109 opt = {
|
|
Aaron@0
|
110 order = 1,
|
|
Aaron@0
|
111 name = "Select Database",
|
|
Aaron@0
|
112 desc = "Show a different database",
|
|
Aaron@0
|
113 type = "group",
|
|
Aaron@0
|
114 guiInline = true,
|
|
Aaron@0
|
115 args = {
|
|
Aaron@0
|
116 faction = {
|
|
Aaron@0
|
117 order = 0,
|
|
Aaron@0
|
118 name = "Faction",
|
|
Aaron@0
|
119 desc = "Show a different database.",
|
|
Aaron@0
|
120 type = "select",
|
|
Aaron@0
|
121 values = {
|
|
Aaron@0
|
122 ["Alliance"] = "Alliance",
|
|
Aaron@0
|
123 ["Horde"] = "Horde",
|
|
Aaron@1
|
124 ["default"] = "Default",
|
|
Aaron@0
|
125 },
|
|
Aaron@0
|
126 arg = "faction",
|
|
Aaron@0
|
127 },
|
|
Aaron@1
|
128
|
|
Aaron@1
|
129 safeBuy = {
|
|
Aaron@1
|
130 order = 1,
|
|
Aaron@1
|
131 name = "Safe Recipe Buy",
|
|
Aaron@1
|
132 desc = "Warn when buying a recipe not on the RecipeProfit list.",
|
|
Aaron@1
|
133 type = "select",
|
|
Aaron@1
|
134 values = {
|
|
Aaron@7
|
135 --["on"] = "On",
|
|
Aaron@1
|
136 ["off"]= "Off",
|
|
Aaron@1
|
137 },
|
|
Aaron@1
|
138 arg = "safebuy",
|
|
Aaron@1
|
139 },
|
|
Aaron@0
|
140 },
|
|
Aaron@1
|
141 get = function(k) return db.profile[k.arg]; end,
|
|
Aaron@0
|
142 set = function(k, v) db.profile[k.arg] = v; RecipeProfit:DoMerge(); end,
|
|
Aaron@0
|
143 },
|
|
Aaron@0
|
144 loadData = {
|
|
Aaron@0
|
145 order = 8,
|
|
Aaron@0
|
146 name = "Import Data",
|
|
Aaron@0
|
147 desc = "Load RecipeProfit and import the data to your database.",
|
|
Aaron@0
|
148 type = "execute",
|
|
Aaron@0
|
149 func = function()
|
|
Aaron@0
|
150 RecipeProfit:DoMerge()
|
|
Aaron@0
|
151 end
|
|
Aaron@0
|
152 },
|
|
Aaron@7
|
153 loadProfile = {
|
|
Aaron@7
|
154 order = 9,
|
|
Aaron@7
|
155 name = "Load RecipeProfit Profile",
|
|
Aaron@7
|
156 desc = "Loads the RecipeProfit Profile into Gathermate for easy recipe tracking.",
|
|
Aaron@7
|
157 type = "execute",
|
|
Aaron@7
|
158 func = function()
|
|
Aaron@7
|
159 GatherMate.db.profiles["RecipeProfit"] = GatherMate.db.profiles["RecipeProfit"] or {}
|
|
Aaron@7
|
160 gmdb = GatherMate.db.profiles["RecipeProfit"]
|
|
Aaron@7
|
161 for k, v in pairs(defaultProfile) do
|
|
Aaron@7
|
162 gmdb[k] = v;
|
|
Aaron@7
|
163 end
|
|
Aaron@7
|
164 GatherMate:SendMessage("OnProfileChanged");
|
|
Aaron@7
|
165 GatherMate:GetModule("Config"):UpdateConfig()
|
|
Aaron@7
|
166 GatherMate:SendMessage("GatherMateConfigChanged")
|
|
Aaron@7
|
167 GatherMate.db:SetProfile("RecipeProfit")
|
|
Aaron@7
|
168 end
|
|
Aaron@7
|
169 },
|
|
Aaron@0
|
170 }
|
|
Aaron@0
|
171 }
|
|
Aaron@0
|
172
|
|
Aaron@0
|
173 local defaults = {
|
|
Aaron@1
|
174 faction = "default",
|
|
Aaron@1
|
175 safebuy = "on",
|
|
Aaron@16
|
176
|
|
Aaron@16
|
177 --submitting cached data not yet implemented
|
|
Aaron@16
|
178 enable_cache = false,
|
|
Aaron@16
|
179 location_cache = {},
|
|
Aaron@0
|
180 }
|
|
Aaron@0
|
181
|
|
Aaron@0
|
182 function RecipeProfit:OnInitialize()
|
|
Aaron@17
|
183 profile = RECIPEPROFIT_profile or defaults
|
|
Aaron@7
|
184
|
|
Aaron@1
|
185 for k, v in pairs(defaults) do
|
|
Aaron@1
|
186 profile[k] = profile[k] or v;
|
|
Aaron@1
|
187 end
|
|
Aaron@1
|
188
|
|
Aaron@12
|
189 self:RegisterChatCommand("recipeprofit", "ShowOptions")
|
|
Aaron@12
|
190 self:RegisterChatCommand("rp", "ShowOptions")
|
|
Aaron@12
|
191 self:RegisterChatCommand("profit", "ShowOptions")
|
|
Aaron@12
|
192
|
|
Aaron@0
|
193 db.profile = profile
|
|
Aaron@0
|
194 db.storage = {}
|
|
Aaron@0
|
195
|
|
Aaron@0
|
196 GatherMate:GetModule("Config"):RegisterModule("RecipeProfit", options)
|
|
Aaron@0
|
197 GatherMate:RegisterDBType("RecipeProfit", db.storage)
|
|
Aaron@8
|
198 GatherMate.db.profile.show["RecipeProfit"] = GatherMate.db.profile.show["RecipeProfit"] or "always"
|
|
Aaron@0
|
199
|
|
Aaron@17
|
200 set_node_constants()
|
|
Aaron@17
|
201 inject_options()
|
|
Aaron@8
|
202
|
|
Aaron@0
|
203 GatherMate:GetModule("Config"):UpdateConfig()
|
|
Aaron@0
|
204 GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged")
|
|
Aaron@0
|
205 end
|
|
Aaron@0
|
206
|
|
Aaron@17
|
207
|
|
Aaron@17
|
208 function RecipeProfit:OnEnable()
|
|
Aaron@17
|
209
|
|
Aaron@17
|
210 _G["MerchantPrevPageButton"]:HookScript("OnClick", self.UpdateButtons)
|
|
Aaron@17
|
211 _G["MerchantNextPageButton"]:HookScript("OnClick", self.UpdateButtons)
|
|
Aaron@17
|
212
|
|
Aaron@17
|
213 self:RegisterEvent("MERCHANT_SHOW", "UpdateButtons")
|
|
Aaron@17
|
214 self:RegisterEvent("MERCHANT_UPDATE", "UpdateButtons")
|
|
Aaron@17
|
215 self:RegisterEvent("BAG_UPDATE", "UpdateButtons")
|
|
Aaron@17
|
216
|
|
Aaron@17
|
217 RecipeProfit:DoMerge()
|
|
Aaron@17
|
218 end
|
|
Aaron@17
|
219
|
|
Aaron@12
|
220 function RecipeProfit:ShowOptions()
|
|
Aaron@13
|
221 LibStub("AceConfigDialog-3.0"):Open("GatherMate")
|
|
Aaron@13
|
222 LibStub("AceConfigDialog-3.0"):SelectGroup("GatherMate", "RecipeProfit")
|
|
Aaron@12
|
223 end
|
|
Aaron@12
|
224
|
|
Aaron@16
|
225 function RecipeProfit:UpdateButtons(event, ...)
|
|
Aaron@16
|
226 --print("UpdateButtons", event)
|
|
Aaron@16
|
227 if(not MerchantFrame:IsVisible()) then
|
|
Aaron@16
|
228 --print("UpdateButtons - (Event: ", event, ") - MerchantFrame not visible.");
|
|
Aaron@16
|
229 return;
|
|
Aaron@16
|
230 end
|
|
Aaron@16
|
231
|
|
Aaron@16
|
232 for i=1, MERCHANT_ITEMS_PER_PAGE, 1 do
|
|
Aaron@16
|
233 local buttonframe = _G["MerchantItem"..i];
|
|
Aaron@16
|
234 local index = (((MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE) + i);
|
|
Aaron@16
|
235 --print(index)
|
|
Aaron@16
|
236 if index <= GetMerchantNumItems() then
|
|
Aaron@16
|
237 button_update(buttonframe)
|
|
Aaron@16
|
238 end
|
|
Aaron@16
|
239 end
|
|
Aaron@17
|
240 end
|
|
Aaron@16
|
241
|
|
Aaron@16
|
242 function RecipeProfit:DoMerge()
|
|
Aaron@16
|
243 ids = {}
|
|
Aaron@16
|
244 local selectedDB = get_faction_db();
|
|
Aaron@16
|
245
|
|
Aaron@16
|
246 GatherMate:ClearDB("RecipeProfit")
|
|
Aaron@16
|
247 for id, note in pairs(selectedDB) do
|
|
Aaron@16
|
248 x, y = find_good_id(note.x, note.y)
|
|
Aaron@16
|
249 add_note(x, y, note)
|
|
Aaron@16
|
250 end
|
|
Aaron@16
|
251
|
|
Aaron@16
|
252 GatherMate:SendMessage("GatherMateDataImport")
|
|
Aaron@16
|
253 GatherMate:GetModule("Config"):SendMessage("GatherMateConfigChanged")
|
|
Aaron@16
|
254 end
|
|
Aaron@16
|
255
|
|
Aaron@16
|
256 function get_note_title(note, factionTag)
|
|
Aaron@16
|
257 if(not factionTag) then
|
|
Aaron@16
|
258 _, factionTag = get_faction_db();
|
|
Aaron@16
|
259 end
|
|
Aaron@16
|
260
|
|
Aaron@16
|
261 return note.item.." - ("..note.vendor.." ".. factionTag ..")";
|
|
Aaron@16
|
262 end
|
|
Aaron@16
|
263
|
|
Aaron@16
|
264 function add_note(x, y, note)
|
|
Aaron@16
|
265 GatherMate:AddNode(note.map, x / 100, y / 100, "RecipeProfit", get_note_title(note));
|
|
Aaron@16
|
266 end
|
|
Aaron@16
|
267
|
|
Aaron@16
|
268 function get_faction_db()
|
|
Aaron@16
|
269 local factionAlliance = db.profile.faction == "Alliance" or
|
|
Aaron@16
|
270 db.profile.faction == "default" and UnitFactionGroup("player") == "Alliance";
|
|
Aaron@16
|
271 if(factionAlliance) then
|
|
Aaron@16
|
272 return RECIPEPROFIT_alliance, "A";
|
|
Aaron@16
|
273 else
|
|
Aaron@16
|
274 return RECIPEPROFIT_horde, "H";
|
|
Aaron@16
|
275 end
|
|
Aaron@16
|
276 end
|
|
Aaron@16
|
277
|
|
Aaron@16
|
278 function safe_cache_vendor()
|
|
Aaron@16
|
279 if(not profile.enable_cache) then
|
|
Aaron@16
|
280 return
|
|
Aaron@16
|
281 end
|
|
Aaron@16
|
282
|
|
Aaron@16
|
283 if(not profile.location_cache[UnitName("NPC")]) then
|
|
Aaron@16
|
284 SetMapToCurrentZone()
|
|
Aaron@16
|
285 local pos = {}
|
|
Aaron@16
|
286 pos.x, pos.y = GetPlayerMapPosition("player")
|
|
Aaron@16
|
287 profile.location_cache[UnitName("NPC")] = pos
|
|
Aaron@16
|
288 end
|
|
Aaron@16
|
289 end
|
|
Aaron@15
|
290
|
|
Aaron@9
|
291 function button_update(self)
|
|
Aaron@9
|
292 local buttonName = _G[self:GetName().."Name"];
|
|
Aaron@9
|
293 local link = GetMerchantItemLink(_G[self:GetName().."ItemButton"]:GetID());
|
|
Aaron@9
|
294 if(not link) then
|
|
Aaron@9
|
295 return;
|
|
Aaron@9
|
296 end
|
|
Aaron@9
|
297
|
|
Aaron@9
|
298 local sName, sLink, iRarity, iLevel, iMinLevel, sType, sSubType, iStackCount = GetItemInfo(link)
|
|
Aaron@9
|
299
|
|
Aaron@16
|
300 if(sType == "Recipe" and safeRecipes[sName]) then
|
|
Aaron@16
|
301 safe_cache_vendor();
|
|
Aaron@9
|
302 SetItemButtonNameFrameVertexColor(self, 0, 0, 1.0);
|
|
Aaron@9
|
303 SetItemButtonSlotVertexColor(self, 0, 0, 0.5);
|
|
Aaron@9
|
304 buttonName:SetText("* " .. sName)
|
|
Aaron@9
|
305 if(GetItemCount(link, true) == 0) then
|
|
Aaron@9
|
306 buttonName:SetTextColor(0,1,1);
|
|
Aaron@9
|
307 elseif(GetItemCount(link, true) < 5) then
|
|
Aaron@9
|
308 buttonName:SetTextColor(1,0,1);
|
|
Aaron@9
|
309 else
|
|
Aaron@9
|
310 buttonName:SetTextColor(1,0,0);
|
|
Aaron@9
|
311 end
|
|
Aaron@9
|
312 else
|
|
Aaron@9
|
313 buttonName:SetTextColor(GameFontNormalSmall:GetTextColor());
|
|
Aaron@9
|
314 end
|
|
Aaron@9
|
315 end
|
|
Aaron@9
|
316
|
|
Aaron@16
|
317 function find_good_id(x, y)
|
|
Aaron@0
|
318 if ids[x.." "..y] then
|
|
Aaron@16
|
319 return find_good_id(x + .01, y)
|
|
Aaron@0
|
320 end
|
|
Aaron@0
|
321
|
|
Aaron@0
|
322 ids[x.." "..y] = true
|
|
Aaron@0
|
323 return x, y
|
|
Aaron@17
|
324 end
|
|
Aaron@17
|
325
|
|
Aaron@17
|
326 local lastNodeTextureId = 0;
|
|
Aaron@17
|
327
|
|
Aaron@17
|
328 function get_next_texture_id()
|
|
Aaron@17
|
329 lastNodeTextureId = lastNodeTextureId + 1;
|
|
Aaron@17
|
330 return lastNodeTextureId;
|
|
Aaron@17
|
331 end
|
|
Aaron@17
|
332
|
|
Aaron@17
|
333 function set_node_constants()
|
|
Aaron@17
|
334 GatherMate.nodeIDs["RecipeProfit"] = {}
|
|
Aaron@17
|
335 GatherMate.nodeTextures["RecipeProfit"] = {}
|
|
Aaron@17
|
336 GatherMate.nodeMinHarvest["RecipeProfit"] = {}
|
|
Aaron@17
|
337
|
|
Aaron@17
|
338 local nodes = GatherMate.nodeIDs["RecipeProfit"]
|
|
Aaron@17
|
339 for id, note in pairs(RECIPEPROFIT_alliance) do
|
|
Aaron@17
|
340 safeRecipes[note.item] = true;
|
|
Aaron@17
|
341 nodes[get_note_title(note, "A")] = get_next_texture_id()
|
|
Aaron@17
|
342 end
|
|
Aaron@17
|
343
|
|
Aaron@17
|
344 for id, note in pairs(RECIPEPROFIT_horde) do
|
|
Aaron@17
|
345 safeRecipes[note.item] = true;
|
|
Aaron@17
|
346 nodes[get_note_title(note, "H")] = get_next_texture_id()
|
|
Aaron@17
|
347 end
|
|
Aaron@17
|
348
|
|
Aaron@17
|
349 for i = 1, lastNodeTextureId, 1 do
|
|
Aaron@17
|
350 GatherMate.nodeTextures["RecipeProfit"][i] = "Interface\\Icons\\INV_Scroll_05"
|
|
Aaron@17
|
351 end
|
|
Aaron@17
|
352
|
|
Aaron@17
|
353 GatherMate.reverseNodeIDs["RecipeProfit"] = GatherMate:CreateReversedTable(nodes)
|
|
Aaron@17
|
354 end
|
|
Aaron@17
|
355
|
|
Aaron@17
|
356 function inject_options()
|
|
Aaron@17
|
357 GatherMate:GetModule("Config").options.args.display.args.general.args.showGroup.args["showRecipeProfit"] = {
|
|
Aaron@17
|
358 order = 6,
|
|
Aaron@17
|
359 name = "Show RecipeProfit nodes.",
|
|
Aaron@17
|
360 desc = "Toggle showing nodes added by RecipeProfit.",
|
|
Aaron@17
|
361 type = "select",
|
|
Aaron@17
|
362 values = {
|
|
Aaron@17
|
363 ["always"] = "Always show",
|
|
Aaron@17
|
364 ["never"] = "Never show",
|
|
Aaron@17
|
365 },
|
|
Aaron@17
|
366 arg = "RecipeProfit",
|
|
Aaron@17
|
367 }
|
|
Aaron@17
|
368
|
|
Aaron@17
|
369 GatherMate:GetModule("Config").options.args.display.args.general.args.iconGroup.args.tracking.args["showRecipeProfit"] = {
|
|
Aaron@17
|
370 order = 6.5,
|
|
Aaron@17
|
371 name = "RecipeProfit",
|
|
Aaron@17
|
372 desc = "Color of the tracking circle.",
|
|
Aaron@17
|
373 type = "color",
|
|
Aaron@17
|
374 hasAlpha = true,
|
|
Aaron@17
|
375 arg = "RecipeProfit",
|
|
Aaron@17
|
376 }
|
|
Aaron@17
|
377 end
|