vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | ------------------------------------------------------ |
2 | -- AutoCraft.lua |
||
3 | -- Originally based on BetterTradeSkill by Matt Perry (http://somewhere.fscked.org) |
||
4 | ------------------------------------------------------ |
||
5 | FAC_VERSION = "11200.1"; |
||
6 | ------------------------------------------------------ |
||
7 | |||
8 | FAC_Config = {}; |
||
9 | FAC_Config.AutoIterate = false; |
||
10 | |||
11 | local P = {}; |
||
12 | AutoCraft = P; |
||
13 | |||
14 | P.OrderedQueue = {}; |
||
15 | P.QueuedReagents = {}; |
||
16 | P.ManuallyPaused = false; |
||
17 | P.SkillCache = {}; |
||
18 | P.ReagentCache = {}; |
||
19 | P.NoOverride = true; |
||
20 | P.TradeSkillsSeen = {}; |
||
21 | |||
22 | local MAX_QUEUE_BUTTONS = 10; |
||
23 | local CACHE_TIME = 5; -- We cache the returns from our hooked GetTradeSkillInfo because it can be called many times a second without actually having any relevant conditions be different. This keeps us from repeatedly recalculating it when not needed. |
||
24 | local QUEUE_ADVANCE_DELAY = 1; -- In 1.8 we seem to have problems if we try to advance the queue too soon after finishing an item (if the item we just finished is needed to craft the next item in the queue, WoW thinks we don't have it yet and thus can't craft the next item). May have something to do with lag. So, we wait this many seconds before trying to advance the queue. |
||
25 | local TRADESKILL_UPDATE_TIME = 5; |
||
26 | |||
27 | function P.GetTradeSkillInfo(index) |
||
28 | if (P.SkillCache[index] and (GetTime() - P.SkillCache[index].time < CACHE_TIME)) then |
||
29 | local info = P.SkillCache[index].info; |
||
30 | return info.skillName, info.difficulty, info.numAvailable, info.isExpanded, info.itemName; |
||
31 | end |
||
32 | |||
33 | local skillName, difficulty, numAvailable, isExpanded = P.Orig_GetTradeSkillInfo(index); |
||
34 | |||
35 | if (skillName == nil or difficulty == "header") then |
||
36 | -- something calls us a lot when the TradeSkillFrame is first shown, and Orig_GetTradeSkillInfo returns bogus at that time. |
||
37 | -- just pass along bogus returns so we don't get bogged down in calculation or cache checks; |
||
38 | -- we'll get called again and be able to use the right info soon enough. |
||
39 | return skillName, difficulty, numAvailable, isExpanded, nil; |
||
40 | end |
||
41 | |||
42 | -- Adjustment #1: recalculate numAvailable based on our altered GetTradeSkillReagentInfo (normally its value is calculated by the client) |
||
43 | local reagentTally = {}; |
||
44 | for reagentIndex = 1, GetTradeSkillNumReagents(index) do |
||
45 | local reagentName, _, reagentCount, playerReagentCount = P.GetTradeSkillReagentInfo(index, reagentIndex); |
||
46 | local completeItemsWorth = math.max(math.floor(playerReagentCount / reagentCount), 0); |
||
47 | table.insert(reagentTally, completeItemsWorth); -- how many could we make if this were the only reagent in question? |
||
48 | end |
||
49 | numAvailable = (math.min(unpack(reagentTally)) or 0); -- this is how many we can really make if we include already-queued reagents |
||
50 | |||
51 | -- Adjustment #2 (TODO): how many of this item could we make if we were to make/buy the reagents right now? |
||
52 | |||
53 | -- For testing |
||
54 | --numAvailable = math.random(5); |
||
55 | |||
56 | local itemName = P.GetTradeItemName(index); |
||
57 | if (skillName ~= nil) then |
||
58 | P.SkillCache[index] = { time=GetTime(), info={ skillName=skillName, difficulty=difficulty, numAvailable=numAvailable, isExpanded=isExpanded, itemName=itemName } }; |
||
59 | end |
||
60 | |||
61 | return skillName, difficulty, numAvailable, isExpanded, itemName; |
||
62 | end |
||
63 | |||
64 | function P.GetTradeSkillReagentInfo(skillIndex, reagentIndex) |
||
65 | local index = skillIndex.."."..reagentIndex; |
||
66 | if (P.ReagentCache[index] and (GetTime() - P.ReagentCache[index].time < CACHE_TIME)) then |
||
67 | local info = P.ReagentCache[index].info; |
||
68 | return info.reagentName, info.reagentTexture, info.reagentCount, info.playerReagentCount; |
||
69 | end |
||
70 | |||
71 | local reagentName, reagentTexture, reagentCount, playerReagentCount = P.Orig_GetTradeSkillReagentInfo(skillIndex, reagentIndex); |
||
72 | |||
73 | if (reagentName == nil or reagentTexture == nil) then |
||
74 | -- something calls us a lot when the TradeSkillFrame is first shown, and Orig_GetTradeSkillReagentInfo returns bogus then. |
||
75 | -- just pass along bogus returns so we don't get bogged down in calculation or cache checks; |
||
76 | -- we'll get called again and be able to use the right info soon enough. |
||
77 | return reagentName, reagentTexture, reagentCount, playerReagentCount; |
||
78 | end |
||
79 | |||
80 | -- Adjustment #1: if you've queued some of this item, add them to effective "inventory" for determining what you can make from it. |
||
81 | playerReagentCount = playerReagentCount + P.NumOfItemInQueue(reagentName); |
||
82 | |||
83 | -- Adjustment #2: if your queue contains items that use this reagent, subtract the amount that will be used from your "inventory". |
||
84 | for _, queueEntry in P.OrderedQueue do |
||
85 | local perItemCount = queueEntry.reagentsPerItem[reagentName]; |
||
86 | if (perItemCount ~= nil) then |
||
87 | playerReagentCount = playerReagentCount - ((queueEntry.numQueued - queueEntry.numProduced) * perItemCount); |
||
88 | end |
||
89 | end |
||
90 | playerReagentCount = math.max(playerReagentCount, 0); |
||
91 | |||
92 | if (reagentName ~= nil) then |
||
93 | P.ReagentCache[index] = { time=GetTime(), info={ reagentName=reagentName, reagentTexture=reagentTexture, reagentCount=reagentCount, playerReagentCount=playerReagentCount } }; |
||
94 | end |
||
95 | |||
96 | return reagentName, reagentTexture, reagentCount, playerReagentCount; |
||
97 | end |
||
98 | |||
99 | function P.GetTradeSkillTools(skillIndex) |
||
100 | local toolInfo = {P.Orig_GetTradeSkillTools(skillIndex)}; |
||
101 | local newToolInfo = {}; |
||
102 | for index = 1, table.getn(toolInfo) do |
||
103 | local item = toolInfo[index]; |
||
104 | if (item and type(item) == "string") then |
||
105 | table.insert(newToolInfo, item); |
||
106 | if (toolInfo[index+1] == 1 or P.NumOfItemInQueue(item) > 0) then |
||
107 | table.insert(newToolInfo, 1); |
||
108 | end |
||
109 | end |
||
110 | end |
||
111 | return unpack(newToolInfo); |
||
112 | end |
||
113 | |||
114 | function P.TradeSkillFrame_Update() |
||
115 | P.Orig_TradeSkillFrame_Update(); |
||
116 | |||
117 | local skillName = GetTradeSkillLine(); |
||
118 | if (P.TradeSkillsSeen[skillName] == nil) then |
||
119 | P.TradeSkillsSeen[skillName] = GetTime(); |
||
120 | --GFWUtils.Print("Disabling TradeSkillFrame overrides."); |
||
121 | P.NoOverride = true; |
||
122 | end |
||
123 | if (P.NoOverride or FAC_Config.NoOverride) then return; end |
||
124 | |||
125 | local numTradeSkills = GetNumTradeSkills(); |
||
126 | local skillOffset = FauxScrollFrame_GetOffset(TradeSkillListScrollFrame); |
||
127 | for i=1, TRADE_SKILLS_DISPLAYED, 1 do |
||
128 | local skillIndex = i + skillOffset; |
||
129 | local skillName, skillType, numAvailable, isExpanded = P.GetTradeSkillInfo(skillIndex); |
||
130 | local skillButton = getglobal("TradeSkillSkill"..i); |
||
131 | if ( skillIndex <= numTradeSkills and skillName ) then |
||
132 | if ( numAvailable == 0 ) then |
||
133 | skillButton:SetText(" "..skillName); |
||
134 | else |
||
135 | skillButton:SetText(" "..skillName.." ["..numAvailable.."]"); |
||
136 | end |
||
137 | end |
||
138 | end |
||
139 | end |
||
140 | |||
141 | function P.TradeSkillFrame_SetSelection(id) |
||
142 | P.Orig_TradeSkillFrame_SetSelection(id); |
||
143 | |||
144 | local skillName = GetTradeSkillLine(); |
||
145 | if (P.TradeSkillsSeen[skillName] == nil) then |
||
146 | P.TradeSkillsSeen[skillName] = GetTime(); |
||
147 | --GFWUtils.Print("Disabling TradeSkillFrame overrides."); |
||
148 | P.NoOverride = true; |
||
149 | end |
||
150 | if (P.NoOverride or FAC_Config.NoOverride) then return; end |
||
151 | |||
152 | local creatable = 1; |
||
153 | local numReagents = GetTradeSkillNumReagents(id); |
||
154 | for i=1, numReagents, 1 do |
||
155 | local reagentName, reagentTexture, reagentCount, playerReagentCount = P.GetTradeSkillReagentInfo(id, i); |
||
156 | local reagent = getglobal("TradeSkillReagent"..i) |
||
157 | local name = getglobal("TradeSkillReagent"..i.."Name"); |
||
158 | local count = getglobal("TradeSkillReagent"..i.."Count"); |
||
159 | if ( reagentName and reagentTexture ) then |
||
160 | if ( playerReagentCount < reagentCount ) then |
||
161 | SetItemButtonTextureVertexColor(reagent, 0.5, 0.5, 0.5); |
||
162 | name:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b); |
||
163 | creatable = nil; |
||
164 | else |
||
165 | SetItemButtonTextureVertexColor(reagent, 1.0, 1.0, 1.0); |
||
166 | name:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); |
||
167 | end |
||
168 | if ( playerReagentCount >= 100 ) then |
||
169 | playerReagentCount = "*"; |
||
170 | end |
||
171 | count:SetText(playerReagentCount.." /"..reagentCount); |
||
172 | end |
||
173 | end |
||
174 | local spellFocus = BuildColoredListString(P.GetTradeSkillTools(id)); |
||
175 | if ( spellFocus ) then |
||
176 | TradeSkillRequirementText:SetText(spellFocus); |
||
177 | end |
||
178 | |||
179 | if (creatable) then |
||
180 | AutoCraftQueue:Enable(); |
||
181 | AutoCraftQueueAll:Enable(); |
||
182 | else |
||
183 | AutoCraftQueue:Disable(); |
||
184 | AutoCraftQueueAll:Disable(); |
||
185 | end |
||
186 | end |
||
187 | |||
188 | function P.Load() |
||
189 | if (not P.Loaded) then |
||
190 | -- Attach our UI elements to the TradeSkillFrame now that it's loaded. |
||
191 | AutoCraftBackground:SetParent(TradeSkillFrame); |
||
192 | AutoCraftBackground:SetPoint("TOPLEFT", 0, 0); |
||
193 | AutoCraftBackground:SetHeight(TradeSkillFrame:GetHeight() + 48); |
||
194 | -- reset this in case someone (say, EnhancedTradeSkill) resized TradeSkillFrame on us |
||
195 | AutoCraftBackground:Show(); |
||
196 | AutoCraftQueue:SetParent(TradeSkillFrame); |
||
197 | AutoCraftQueue:SetPoint("TOPLEFT", TradeSkillCreateButton, "TOPLEFT", 0, 0); |
||
198 | AutoCraftQueue:Show(); |
||
199 | AutoCraftQueueAll:SetParent(TradeSkillFrame); |
||
200 | AutoCraftQueueAll:SetPoint("TOPLEFT", TradeSkillCreateAllButton, "TOPLEFT", 0, 0); |
||
201 | AutoCraftQueueAll:Show(); |
||
202 | AutoCraftBuy:SetParent(TradeSkillFrame); |
||
203 | AutoCraftBuy:SetPoint("TOPLEFT", TradeSkillCancelButton, "TOPLEFT", 0, 0); |
||
204 | AutoCraftBuy:Show(); |
||
205 | AutoCraftQueueEverything:SetParent(TradeSkillFrame); |
||
206 | AutoCraftQueueEverything:Show(); |
||
207 | AutoCraftRunQueue:SetParent(TradeSkillFrame); |
||
208 | AutoCraftRunQueue:Show(); |
||
209 | AutoCraftClear:SetParent(TradeSkillFrame); |
||
210 | AutoCraftClear:Show(); |
||
211 | AutoCraftRunAutomatically:SetParent(TradeSkillFrame); |
||
212 | AutoCraftRunAutomatically:Show(); |
||
213 | AutoCraftRunAutomaticallyText:SetText(FAC_RUN_AUTOMATICALLY_CHECKBUTTON); |
||
214 | AutoCraftRunAutomatically:SetChecked(FAC_Config.AutoIterate); |
||
215 | |||
216 | -- Hide the old Create buttons so I can put my buttons in their place. |
||
217 | -- Not sure if this will always work, but it does at the moment. |
||
218 | TradeSkillCreateButton:Hide(); |
||
219 | TradeSkillCreateAllButton:Hide(); |
||
220 | TradeSkillCancelButton:Hide(); |
||
221 | |||
222 | -- we don't actually hook these anymore, but we keep the "aliases" around to be clearly readable when we're calling originals. |
||
223 | P.Orig_GetTradeSkillTools = GetTradeSkillTools; |
||
224 | P.Orig_GetTradeSkillReagentInfo = GetTradeSkillReagentInfo; |
||
225 | P.Orig_GetTradeSkillInfo = GetTradeSkillInfo; |
||
226 | |||
227 | -- we do hook these, however. |
||
228 | P.Orig_TradeSkillFrame_SetSelection = TradeSkillFrame_SetSelection; |
||
229 | TradeSkillFrame_SetSelection = P.TradeSkillFrame_SetSelection; |
||
230 | P.Orig_TradeSkillFrame_Update = TradeSkillFrame_Update; |
||
231 | TradeSkillFrame_Update = P.TradeSkillFrame_Update; |
||
232 | |||
233 | P.Loaded = true; |
||
234 | GFWUtils.Print("Fizzwidget AutoCraft "..FAC_VERSION.." initialized!"); |
||
235 | end |
||
236 | end |
||
237 | |||
238 | function P.NumOfItemInQueue(itemName) |
||
239 | for _, queueEntry in P.OrderedQueue do |
||
240 | if (queueEntry.item == itemName) then |
||
241 | local numPerCraft = (queueEntry.numPerCraft or 0); |
||
242 | local numQueued = (queueEntry.numQueued or 0); |
||
243 | if (numPerCraft > 1) then |
||
244 | return numQueued * numPerCraft; |
||
245 | else |
||
246 | return numQueued; |
||
247 | end |
||
248 | end |
||
249 | end |
||
250 | return 0; |
||
251 | end |
||
252 | |||
253 | function P.OnUpdate(elapsed) |
||
254 | if (P.NoOverride and P.Loaded and TradeSkillFrame and TradeSkillFrame:IsVisible()) then |
||
255 | local skillName = GetTradeSkillLine(); |
||
256 | if (P.TradeSkillsSeen[skillName] and (GetTime() - P.TradeSkillsSeen[skillName] > TRADESKILL_UPDATE_TIME)) then |
||
257 | P.NoOverride = false; |
||
258 | --GFWUtils.Print("Enabling TradeSkillFrame overrides."); |
||
259 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
260 | TradeSkillFrame_Update(); |
||
261 | end |
||
262 | end |
||
263 | if (not CastingBarFrame:IsVisible()) then |
||
264 | P.CastingOtherSpell = false; |
||
265 | P.CraftingQueuedItem = false; |
||
266 | end |
||
267 | if (P.AdvanceQueueTime ~= nil and GetTime() >= P.AdvanceQueueTime) then |
||
268 | P.Iterate(); |
||
269 | P.AdvanceQueueTime = nil; |
||
270 | end |
||
271 | end |
||
272 | |||
273 | function P.OnLoad() |
||
274 | -- we do most of our loading once the TradeSkillFrame loads (which is on-demand now). |
||
275 | |||
276 | this:RegisterEvent("ADDON_LOADED"); |
||
277 | this:RegisterEvent("CHAT_MSG_SPELL_TRADESKILLS"); |
||
278 | this:RegisterEvent("MERCHANT_SHOW"); |
||
279 | this:RegisterEvent("MERCHANT_CLOSED"); |
||
280 | this:RegisterEvent("TRADE_SKILL_SHOW"); |
||
281 | this:RegisterEvent("TRADE_SKILL_CLOSE"); |
||
282 | this:RegisterEvent("TRADE_SKILL_UPDATE"); |
||
283 | this:RegisterEvent("SPELLCAST_INTERRUPTED"); |
||
284 | this:RegisterEvent("SPELLCAST_FAILED"); |
||
285 | this:RegisterEvent("SPELLCAST_START"); |
||
286 | this:RegisterEvent("SPELLCAST_STOP"); |
||
287 | |||
288 | if ( IsAddOnLoaded("Blizzard_TradeSkillUI") ) then |
||
289 | -- P.Load(); |
||
290 | end |
||
291 | |||
292 | end |
||
293 | |||
294 | function P.OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) |
||
295 | |||
296 | if (event == "ADDON_LOADED" and (arg1 == "Blizzard_TradeSkillUI" or IsAddOnLoaded("Blizzard_TradeSkillUI"))) then |
||
297 | P.Load(); |
||
298 | end |
||
299 | if (not P.Loaded) then |
||
300 | -- all the other events we care about only have relevance once we're fully in action and attached to the TradeSkill UI |
||
301 | return; |
||
302 | end |
||
303 | |||
304 | --DevTools_Dump({event=event, arg1=arg1, arg2=arg2, arg3=arg3, arg4=arg4, arg5=arg5, arg6=arg6, arg7=arg7, arg8=arg8, arg9=arg9}); |
||
305 | if (event == "CHAT_MSG_SPELL_TRADESKILLS") then |
||
306 | if (FAC_CreateItemPattern == nil) then |
||
307 | FAC_CreateItemPattern = GFWUtils.FormatToPattern(TRADESKILL_LOG_FIRSTPERSON); |
||
308 | end |
||
309 | for item in string.gfind(arg1, FAC_CreateItemPattern) do |
||
310 | P.HandleCreated(item); |
||
311 | return; |
||
312 | end |
||
313 | elseif (event == "TRADE_SKILL_CLOSE" or event == "MERCHANT_SHOW" or event == "MERCHANT_CLOSED") then |
||
314 | P.UpdateDisplay(); |
||
315 | elseif (event == "TRADE_SKILL_SHOW") then |
||
316 | P.UpdateDisplay(); |
||
317 | AutoCraftRunAutomaticallyText:SetText(FAC_RUN_AUTOMATICALLY_CHECKBUTTON); |
||
318 | AutoCraftRunAutomatically:SetChecked(FAC_Config.AutoIterate); |
||
319 | -- if we've just switched to the tradeskill window needed for the head of the queue, start iterating again |
||
320 | if (not P.ManuallyPaused and P.OrderedQueue[1] ~= nil and P.OrderedQueue[1].skill == GetTradeSkillLine()) then |
||
321 | P.Iterate(); |
||
322 | end |
||
323 | elseif (event == "TRADE_SKILL_UPDATE") then |
||
324 | P.UpdateDisplay(); |
||
325 | elseif (event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED") then |
||
326 | P.CastingOtherSpell = false; |
||
327 | P.CraftingQueuedItem = false; |
||
328 | if (P.Unqueueing or P.CastingOtherSpell) then |
||
329 | P.Unqueueing = false; |
||
330 | P.Iterate(); |
||
331 | return; |
||
332 | end |
||
333 | P.UpdateDisplay(); |
||
334 | elseif (event == "SPELLCAST_STOP") then |
||
335 | if (P.CastingOtherSpell) then |
||
336 | P.CastingOtherSpell = false; |
||
337 | P.Iterate(); |
||
338 | P.UpdateDisplay(); |
||
339 | end |
||
340 | elseif (event == "SPELLCAST_START") then |
||
341 | if (P.OrderedQueue[1] and CastingBarText:GetText() == P.OrderedQueue[1].recipe) then |
||
342 | P.CraftingQueuedItem = true; |
||
343 | P.CastingOtherSpell = false; |
||
344 | else |
||
345 | P.CraftingQueuedItem = false; |
||
346 | P.CastingOtherSpell = true; |
||
347 | end |
||
348 | P.UpdateDisplay(); |
||
349 | end |
||
350 | end |
||
351 | |||
352 | function P.Queue_OnClick() |
||
353 | local id = tonumber(this:GetID()); |
||
354 | if (P.OrderedQueue[id]) then |
||
355 | table.remove(P.OrderedQueue, id); |
||
356 | if (id == 1 and P.CraftingQueuedItem) then |
||
357 | P.Unqueueing = true; |
||
358 | SpellStopCasting(); |
||
359 | end |
||
360 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
361 | TradeSkillFrame_Update(); |
||
362 | P.UpdateDisplay(); |
||
363 | P.Queue_UpdateTooltip(id); |
||
364 | end |
||
365 | end |
||
366 | |||
367 | function P.Queue_OnEvent() |
||
368 | P.Queue_UpdateTooltip(tonumber(this:GetID())); |
||
369 | end |
||
370 | |||
371 | function P.Queue_UpdateTooltip(id) |
||
372 | local button = getglobal("QueuedSkillIcon"..id); |
||
373 | if (button:IsVisible()) then |
||
374 | GameTooltip:SetOwner(button, "ANCHOR_TOPLEFT"); |
||
375 | if ( id == 1 and P.CraftingQueuedItem) then |
||
376 | GameTooltip:SetText(NORMAL_FONT_COLOR_CODE..FAC_CREATING..FONT_COLOR_CODE_CLOSE, 1.0, 1.0, 1.0); |
||
377 | else |
||
378 | GameTooltip:SetText(NORMAL_FONT_COLOR_CODE..FAC_QUEUED..FONT_COLOR_CODE_CLOSE, 1.0, 1.0, 1.0); |
||
379 | end |
||
380 | if (id == MAX_QUEUE_BUTTONS and table.getn(P.OrderedQueue) > MAX_QUEUE_BUTTONS) then |
||
381 | GameTooltip:AppendText(string.format(FAC_ADDITIONAL_ENTRIES, table.getn(P.OrderedQueue) - MAX_QUEUE_BUTTONS + 1)); |
||
382 | for index = MAX_QUEUE_BUTTONS, table.getn(P.OrderedQueue) do |
||
383 | local num = P.OrderedQueue[index].numQueued - P.OrderedQueue[index].numProduced; |
||
384 | GameTooltip:AppendText("\n"..num .."x ".. P.OrderedQueue[index].item); |
||
385 | end |
||
386 | GameTooltip:AddLine(string.format(FAC_CLICK_TO_CANCEL_FORMAT, P.OrderedQueue[MAX_QUEUE_BUTTONS].item)); |
||
387 | else |
||
388 | local num = P.OrderedQueue[id].numQueued - P.OrderedQueue[id].numProduced; |
||
389 | GameTooltip:AppendText(num .."x ".. P.OrderedQueue[id].item); |
||
390 | GameTooltip:AddLine(FAC_CLICK_TO_CANCEL); |
||
391 | end |
||
392 | GameTooltip:Show(); |
||
393 | end |
||
394 | end |
||
395 | |||
396 | function P.QueueEverything() |
||
397 | local numSkills = GetNumTradeSkills(); |
||
398 | local startIndex, stopIndex, increment; |
||
399 | if (IsAltKeyDown()) then |
||
400 | startIndex = 1; |
||
401 | stopIndex = numSkills; |
||
402 | increment = 1; |
||
403 | else |
||
404 | startIndex = numSkills; |
||
405 | stopIndex = 1; |
||
406 | increment = -1; |
||
407 | end |
||
408 | for index = startIndex, stopIndex, increment do |
||
409 | local recipeName, _, numAvailable, _, itemName = P.GetTradeSkillInfo(index); |
||
410 | if (numAvailable > 0) then |
||
411 | P.AddToQueue(recipeName, itemName, index, numAvailable); |
||
412 | end |
||
413 | end |
||
414 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
415 | TradeSkillFrame_Update(); |
||
416 | if (table.getn(P.OrderedQueue) == 0) then |
||
417 | GFWUtils.Print(FAC_NOTHING_TO_QUEUE); |
||
418 | end |
||
419 | end |
||
420 | |||
421 | -- TODO: option-click for "buy all" equivalent to "queue all" |
||
422 | function P.BuyReagents(amount) |
||
423 | local index = GetTradeSkillSelectionIndex(); |
||
424 | |||
425 | --if (IsAltKeyDown()) then |
||
426 | -- amount = TradeSkillFrame.numAvailable; |
||
427 | --end |
||
428 | |||
429 | for reagentIndex = 1, GetTradeSkillNumReagents(index) do |
||
430 | local reagentName, _, reagentCount, playerReagentCount = P.GetTradeSkillReagentInfo(index, reagentIndex); |
||
431 | local amountNeeded = (reagentCount * amount) - playerReagentCount; |
||
432 | |||
433 | for merchantIndex = 1, GetMerchantNumItems() do |
||
434 | local name, _, price, numPerBuy, numAvailable, _ = GetMerchantItemInfo(merchantIndex); |
||
435 | if (name == reagentName) then |
||
436 | if (numAvailable >= 0 and (numAvailable * numPerBuy) < amountNeeded) then |
||
437 | amountNeeded = numAvailable * numPerBuy; |
||
438 | end |
||
439 | local amountToBuy = math.ceil(amountNeeded / numPerBuy); |
||
440 | if (amountToBuy > 0) then |
||
441 | if (numPerBuy > 1) then |
||
442 | GFWUtils.Print(string.format(FAC_BUYING_SETS_FORMAT, amountToBuy, name)); |
||
443 | while (amountToBuy > 0 ) do |
||
444 | local amountBuyingNow = 1; -- dumb workaround for the API not telling us max stack size for things that come in multi-packs |
||
445 | BuyMerchantItem(merchantIndex, amountBuyingNow); |
||
446 | amountToBuy = amountToBuy - amountBuyingNow; |
||
447 | end |
||
448 | else |
||
449 | while (amountToBuy > 0 ) do |
||
450 | local maxPerBuy = GetMerchantItemMaxStack(merchantIndex); |
||
451 | local amountBuyingNow = math.min(amountToBuy, maxPerBuy); |
||
452 | GFWUtils.Print(string.format(FAC_BUYING_FORMAT, amountBuyingNow, name)); |
||
453 | BuyMerchantItem(merchantIndex, amountBuyingNow); |
||
454 | amountToBuy = amountToBuy - amountBuyingNow; |
||
455 | end |
||
456 | end |
||
457 | elseif (numAvailable == 0) then |
||
458 | GFWUtils.Print(string.format(FAC_NOT_AVAILABLE_FORMAT, name)); |
||
459 | else |
||
460 | GFWUtils.Print(string.format(FAC_ALREADY_ENOUGH_FORMAT, name, amount, P.GetTradeItemName(index))); |
||
461 | end |
||
462 | break; |
||
463 | end |
||
464 | end |
||
465 | end |
||
466 | end |
||
467 | |||
468 | function P.Queue(amount) |
||
469 | local index = GetTradeSkillSelectionIndex(); |
||
470 | local recipeName, _, numAvailable, _, itemName = P.GetTradeSkillInfo(index); |
||
471 | |||
472 | if (amount > numAvailable) then amount = numAvailable; end |
||
473 | |||
474 | if (amount > 0) then |
||
475 | P.AddToQueue(recipeName, itemName, index, amount); |
||
476 | end |
||
477 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
478 | TradeSkillFrame_Update(); |
||
479 | P.UpdateDisplay(); |
||
480 | end |
||
481 | |||
482 | function P.AddToQueue(recipeName, item, index, amount) |
||
483 | |||
484 | local alreadyQueued = false; |
||
485 | GFWUtils.Print(FAC_QUEUEING .. GFWUtils.Hilite(amount .. " x ") .. GetTradeSkillItemLink(index)); |
||
486 | for _, queueEntry in P.OrderedQueue do |
||
487 | if (item == queueEntry.item) then |
||
488 | queueEntry.numQueued = queueEntry.numQueued + amount; |
||
489 | alreadyQueued = true; |
||
490 | end |
||
491 | end |
||
492 | if (not alreadyQueued) then |
||
493 | local reagentsPerItem = {}; |
||
494 | for reagentIndex = 1, GetTradeSkillNumReagents(index) do |
||
495 | local reagentName, _, reagentCount, _ = P.GetTradeSkillReagentInfo(index, reagentIndex); |
||
496 | reagentsPerItem[reagentName] = reagentCount; |
||
497 | end |
||
498 | local minMade, maxMade = GetTradeSkillNumMade(index); |
||
499 | local numPerCraft = math.min((minMade or 0), (maxMade or 0)); |
||
500 | -- assume recipes that make a variable number of items will always produce the minimum, so we can't end up over-queueing. |
||
501 | |||
502 | table.insert(P.OrderedQueue, {recipe=recipeName, item=item, numQueued=amount, numProduced=0, icon=GetTradeSkillIcon(index), skill=GetTradeSkillLine(), reagentsPerItem=reagentsPerItem, numPerCraft=numPerCraft}); |
||
503 | end |
||
504 | |||
505 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
506 | TradeSkillFrame_Update(); |
||
507 | P.UpdateDisplay(); |
||
508 | if (FAC_Config.AutoIterate) then |
||
509 | P.ManuallyPaused = false; |
||
510 | P.Iterate(); |
||
511 | else |
||
512 | P.ManuallyPaused = true; |
||
513 | end |
||
514 | P.UpdateDisplay(); |
||
515 | end |
||
516 | |||
517 | function P.UpdateDisplay() |
||
518 | |||
519 | -- we clear these out in case relevant inventory has (actually or effectively) changed. |
||
520 | P.SkillCache = {}; |
||
521 | P.ReagentCache = {}; |
||
522 | |||
523 | if (MerchantFrame:IsVisible()) then |
||
524 | AutoCraftBuy:Enable(); |
||
525 | else |
||
526 | AutoCraftBuy:Disable(); |
||
527 | end |
||
528 | |||
529 | if (table.getn(P.OrderedQueue) > 0) then |
||
530 | if (P.CraftingQueuedItem) then |
||
531 | QueueMessageText:Hide(); |
||
532 | QueueMessageText:SetText(""); |
||
533 | AutoCraftRunQueue:SetText(FAC_PAUSE_QUEUE_BUTTON); |
||
534 | else |
||
535 | if (not P.ManuallyPaused and P.OrderedQueue[1] ~= nil and P.OrderedQueue[1].skill ~= GetTradeSkillLine()) then |
||
536 | QueueMessageText:SetText(FAC_QUEUE_PAUSED..": "..string.format(FAC_SWITCH_WINDOW_FORMAT, P.OrderedQueue[1].skill)); |
||
537 | elseif (P.CastingOtherSpell) then |
||
538 | if (CastingBarText:GetText() ~= nil) then |
||
539 | QueueMessageText:SetText(FAC_QUEUE_PAUSED..": "..string.format(FAC_WAITING_SPELL_FORMAT, CastingBarText:GetText())); |
||
540 | end |
||
541 | else |
||
542 | QueueMessageText:SetText(FAC_QUEUE_PAUSED); |
||
543 | end |
||
544 | QueueMessageText:Show(); |
||
545 | AutoCraftRunQueue:SetText(FAC_RUN_QUEUE_BUTTON); |
||
546 | end |
||
547 | |||
548 | AutoCraftRunQueue:Enable(); |
||
549 | AutoCraftClear:Enable(); |
||
550 | else |
||
551 | QueueMessageText:Hide(); |
||
552 | QueueMessageText:SetText(""); |
||
553 | AutoCraftRunQueue:SetText(FAC_RUN_QUEUE_BUTTON); |
||
554 | AutoCraftRunQueue:Disable(); |
||
555 | AutoCraftClear:Disable(); |
||
556 | end |
||
557 | |||
558 | for i = 1, MAX_QUEUE_BUTTONS do |
||
559 | button = getglobal("QueuedSkillIcon"..i); |
||
560 | currentItem = P.OrderedQueue[i]; |
||
561 | if (currentItem == nil) then |
||
562 | button:Hide(); |
||
563 | else |
||
564 | if (i == MAX_QUEUE_BUTTONS and table.getn(P.OrderedQueue) > MAX_QUEUE_BUTTONS) then |
||
565 | SetItemButtonTexture(button, "Interface\\Icons\\INV_Misc_QuestionMark"); |
||
566 | SetItemButtonCount(button, (table.getn(P.OrderedQueue) - MAX_QUEUE_BUTTONS - 1)); |
||
567 | else |
||
568 | SetItemButtonTexture(button, currentItem.icon); |
||
569 | SetItemButtonCount(button, (currentItem.numQueued - currentItem.numProduced)); |
||
570 | end |
||
571 | button:Show(); |
||
572 | end |
||
573 | end |
||
574 | end |
||
575 | |||
576 | function P.StartStop() |
||
577 | if (P.CraftingQueuedItem == true) then |
||
578 | P.ManuallyPaused = true; |
||
579 | SpellStopCasting(); |
||
580 | P.UpdateDisplay(); |
||
581 | else |
||
582 | P.ManuallyPaused = false; |
||
583 | P.Iterate(); |
||
584 | P.UpdateDisplay(); |
||
585 | end |
||
586 | end |
||
587 | |||
588 | function P.Clear() |
||
589 | if (table.getn(P.OrderedQueue) > 0) then |
||
590 | if (P.CraftingQueuedItem and not P.ManuallyPaused) then |
||
591 | SpellStopCasting(); |
||
592 | end |
||
593 | P.OrderedQueue = {}; |
||
594 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
595 | TradeSkillFrame_Update(); |
||
596 | P.UpdateDisplay(); |
||
597 | end |
||
598 | end |
||
599 | |||
600 | function P.Iterate() |
||
601 | if (P.CraftingQueuedItem or P.CastingOtherSpell) then return; end |
||
602 | if (table.getn(P.OrderedQueue) > 0) then |
||
603 | local index = P.GetTradeRecipeIndex(P.OrderedQueue[1].recipe); |
||
604 | if (index >= 0) then |
||
605 | if (P.OrderedQueue[1].skill == GetTradeSkillLine()) then |
||
606 | DoTradeSkill(index, (P.OrderedQueue[1].numQueued - P.OrderedQueue[1].numProduced)); |
||
607 | P.UpdateDisplay(); |
||
608 | return; |
||
609 | end |
||
610 | end |
||
611 | P.ManuallyPaused = false; |
||
612 | P.UpdateDisplay(); |
||
613 | end |
||
614 | end |
||
615 | |||
616 | function P.HandleCreated(item) |
||
617 | if (P.OrderedQueue[1] and item == P.OrderedQueue[1].item) then |
||
618 | P.OrderedQueue[1].numProduced = P.OrderedQueue[1].numProduced + 1; |
||
619 | if (P.OrderedQueue[1].numProduced >= P.OrderedQueue[1].numQueued) then |
||
620 | P.CraftingQueuedItem = false; -- this will get set back to true when we get the SPELLCAST_START event |
||
621 | table.remove(P.OrderedQueue, 1); |
||
622 | end |
||
623 | TradeSkillFrame_SetSelection(GetTradeSkillSelectionIndex()); |
||
624 | TradeSkillFrame_Update(); |
||
625 | P.UpdateDisplay(); |
||
626 | --P.Iterate(); |
||
627 | if (table.getn(P.OrderedQueue) > 0) then |
||
628 | P.AdvanceQueueTime = GetTime() + QUEUE_ADVANCE_DELAY; |
||
629 | end |
||
630 | end |
||
631 | end |
||
632 | |||
633 | function P.GetTradeItemName(index) |
||
634 | local linktext = GetTradeSkillItemLink(index); |
||
635 | if (linktext) then |
||
636 | local _,_,item = string.find(linktext, "^.*%[(.*)%].*$"); |
||
637 | return item; |
||
638 | else |
||
639 | local item, difficulty, amount = P.Orig_GetTradeSkillInfo(index); |
||
640 | return item; |
||
641 | end |
||
642 | end |
||
643 | |||
644 | -- find the trade skill index based on the skill name (recipe name), as indices are subject to change. |
||
645 | function P.GetTradeRecipeIndex(recipeName) |
||
646 | local numSkills = GetNumTradeSkills(); |
||
647 | for index = 1, numSkills do |
||
648 | local skillName = P.Orig_GetTradeSkillInfo(index); |
||
649 | if (skillName == recipeName) then |
||
650 | return index; |
||
651 | end |
||
652 | end |
||
653 | return -1; |
||
654 | end |