Mercurial > wow > itemauditor
comparison Modules/Crafting.lua @ 128:451d8a19edea
Ticket 33 - Implemented a persistent queue. This allows the crafting queue to be seen even if your tradeskills aren't open and allows you to mix all of your tradeskills into a single queue.
| author | Asa Ayers <Asa.Ayers@Gmail.com> |
|---|---|
| date | Thu, 02 Sep 2010 23:59:09 -0700 |
| parents | e8d3c299542c |
| children | 78c6d905c2e1 7f81764aa03a |
comparison
equal
deleted
inserted
replaced
| 127:4f26dc55455d | 128:451d8a19edea |
|---|---|
| 8 | 8 |
| 9 local validateMoney = ItemAuditor.validateMoney | 9 local validateMoney = ItemAuditor.validateMoney |
| 10 local parseMoney = ItemAuditor.parseMoney | 10 local parseMoney = ItemAuditor.parseMoney |
| 11 | 11 |
| 12 local realData = {} | 12 local realData = {} |
| 13 local nameMap = nil | |
| 14 local shoppingList = nil | |
| 13 | 15 |
| 14 local vellumLevelMap = { | 16 local vellumLevelMap = { |
| 15 [38682] = 37602, -- Armor Vellum => Armor Vellum II | 17 [38682] = 37602, -- Armor Vellum => Armor Vellum II |
| 16 [37602] = 43145, -- Armor Vellum II => Armor Vellum III | 18 [37602] = 43145, -- Armor Vellum II => Armor Vellum III |
| 17 [39349] = 39350, -- Weapon Vellum => Weapon Vellum II | 19 [39349] = 39350, -- Weapon Vellum => Weapon Vellum II |
| 18 [39350] = 43146, -- Weapon Vellum II => Weapon Vellum III | 20 [39350] = 43146, -- Weapon Vellum II => Weapon Vellum III |
| 19 } | 21 } |
| 22 | |
| 23 function Crafting:OnInitialize() | |
| 24 local allQueues = ItemAuditor.db.factionrealm.queue | |
| 25 if not allQueues[UnitName("player")] then | |
| 26 allQueues[UnitName("player")] = {} | |
| 27 end | |
| 28 realData = allQueues[UnitName("player")] | |
| 29 | |
| 30 self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") | |
| 31 end | |
| 32 | |
| 33 local function getQueueLocation(name) | |
| 34 if not nameMap then | |
| 35 nameMap = {} | |
| 36 for key, data in pairs(realData) do | |
| 37 nameMap[data.skillName] = key | |
| 38 end | |
| 39 end | |
| 40 return nameMap[name] | |
| 41 end | |
| 42 | |
| 43 --@debug@ | |
| 44 Crafting.getQueueLocation = getQueueLocation | |
| 45 function Crafting.getNameMap() | |
| 46 return nameMap | |
| 47 end | |
| 48 | |
| 49 function Crafting.getRealData() | |
| 50 return realData | |
| 51 end | |
| 52 --@end-debug@ | |
| 53 | |
| 54 function Crafting:UNIT_SPELLCAST_SUCCEEDED(event, unit, spell) | |
| 55 if unit == "player" and getQueueLocation(spell) then | |
| 56 local data = realData[getQueueLocation(spell)] | |
| 57 data.queue = data.queue - 1 | |
| 58 ItemAuditor:RefreshCraftingTable() | |
| 59 end | |
| 60 end | |
| 20 | 61 |
| 21 local queueDestinations = {} | 62 local queueDestinations = {} |
| 22 local displayCraftingDestinations = {} | 63 local displayCraftingDestinations = {} |
| 23 function Crafting.RegisterQueueDestination(name, destination) | 64 function Crafting.RegisterQueueDestination(name, destination) |
| 24 queueDestinations[name] = destination | 65 queueDestinations[name] = destination |
| 150 | 191 |
| 151 -- ItemAuditor:GetModule('Crafting').filter_queued = false | 192 -- ItemAuditor:GetModule('Crafting').filter_queued = false |
| 152 Crafting.filter_have_mats = false | 193 Crafting.filter_have_mats = false |
| 153 Crafting.filter_show_all = false | 194 Crafting.filter_show_all = false |
| 154 local function tableFilter(self, row, ...) | 195 local function tableFilter(self, row, ...) |
| 196 if Crafting.nameFilter then | |
| 197 return string.find(row[1], Crafting.nameFilter) ~= nil | |
| 198 end | |
| 199 | |
| 155 if Crafting.filter_show_all then | 200 if Crafting.filter_show_all then |
| 156 return true | 201 return true |
| 157 end | 202 end |
| 158 | 203 |
| 159 -- column 5 is how many should be crafted | 204 -- column 5 is how many should be crafted |
| 187 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30) | 232 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30) |
| 188 | 233 |
| 189 craftingTable:RegisterEvents({ | 234 craftingTable:RegisterEvents({ |
| 190 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) | 235 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) |
| 191 if realrow then | 236 if realrow then |
| 192 local data = realData[realrow] | 237 if column == 1 then |
| 193 | 238 local data = realData[realrow] |
| 194 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR") | 239 |
| 195 GameTooltip:SetHyperlink(data.link) | 240 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR") |
| 196 GameTooltip:Show() | 241 GameTooltip:SetHyperlink(data.link) |
| 242 GameTooltip:Show() | |
| 243 elseif column == 2 then | |
| 244 local data = realData[realrow] | |
| 245 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR") | |
| 246 GameTooltip:SetText(format('Create %sx%s', data.link, data.queue)) | |
| 247 for i, reagent in pairs(data.reagents) do | |
| 248 GameTooltip:AddDoubleLine("\124cffffffff"..reagent.link, format("\124cffffffff%s/%s", reagent.count-reagent.need, reagent.count)) | |
| 249 --[[ | |
| 250 reagents[reagentId] = { | |
| 251 link = reagentLink, | |
| 252 itemID = vellumID, | |
| 253 name = reagentName, | |
| 254 count = 1, | |
| 255 price = self:GetReagentCost(reagentLink, 1), | |
| 256 need = 0, -- This will get populated after the decisions have been made. it can't | |
| 257 -- be done before that because highest profit items get priority on materials. | |
| 258 }]] | |
| 259 end | |
| 260 GameTooltip:Show() | |
| 261 end | |
| 197 end | 262 end |
| 198 end, | 263 end, |
| 199 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) | 264 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) |
| 200 GameTooltip:Hide() | 265 GameTooltip:Hide() |
| 201 end, | 266 end, |
| 272 end | 337 end |
| 273 | 338 |
| 274 btnProcess:SetScript("OnClick", function (self, button, down) | 339 btnProcess:SetScript("OnClick", function (self, button, down) |
| 275 local data = ItemAuditor:GetCraftingRow(1) | 340 local data = ItemAuditor:GetCraftingRow(1) |
| 276 if data then | 341 if data then |
| 342 -- This will make sure the correct tradeskill window is open. | |
| 343 local tradeskillName = GetTradeSkillLine() | |
| 344 if data.tradeskillName ~= tradeskillName then | |
| 345 CastSpellByName(data.tradeskillName) | |
| 346 end | |
| 347 | |
| 277 local queue = data.queue | 348 local queue = data.queue |
| 278 local vellumID = nil | 349 local vellumID = nil |
| 279 _, _, _, _, altVerb = GetTradeSkillInfo(data.tradeSkillIndex) | 350 _, _, _, _, altVerb = GetTradeSkillInfo(data.tradeSkillIndex) |
| 280 if altVerb == 'Enchant' and LSW.scrollData[data.recipeID] ~= nil then | 351 if altVerb == 'Enchant' and LSW.scrollData[data.recipeID] ~= nil then |
| 281 vellumID = LSW.scrollData[data.recipeID]["vellumID"] | 352 vellumID = LSW.scrollData[data.recipeID]["vellumID"] |
| 285 DoTradeSkill(data.tradeSkillIndex, queue) | 356 DoTradeSkill(data.tradeSkillIndex, queue) |
| 286 if vellumID then | 357 if vellumID then |
| 287 useVellum(vellumID) | 358 useVellum(vellumID) |
| 288 end | 359 end |
| 289 | 360 |
| 290 data.queue = data.queue - queue | |
| 291 ItemAuditor:RefreshCraftingTable() | |
| 292 UpdateProcessTooltip() | 361 UpdateProcessTooltip() |
| 293 end | 362 end |
| 294 end) | 363 end) |
| 295 | 364 |
| 296 btnProcess:SetScript("OnEnter", UpdateProcessTooltip) | 365 btnProcess:SetScript("OnEnter", UpdateProcessTooltip) |
| 416 }, | 485 }, |
| 417 } | 486 } |
| 418 | 487 |
| 419 Crafting.RegisterCraftingDecider('Is Profitable', isProfitable, isProfitableOptions) | 488 Crafting.RegisterCraftingDecider('Is Profitable', isProfitable, isProfitableOptions) |
| 420 | 489 |
| 421 | 490 function Crafting.ClearProfession(tradeskillName) |
| 491 -- This will initialize nameMap if it isn't already. | |
| 492 getQueueLocation('') | |
| 493 | |
| 494 for key = #(realData), 1, -1 do | |
| 495 if realData[key].tradeskillName == tradeskillName then | |
| 496 nameMap[realData[key].tradeskillName] = nil | |
| 497 tremove(realData, key) | |
| 498 end | |
| 499 end | |
| 500 end | |
| 422 | 501 |
| 423 local tableData = {} | 502 local tableData = {} |
| 424 function ItemAuditor:UpdateCraftingTable() | 503 function ItemAuditor:UpdateCraftingTable() |
| 425 if LSW == nil then | 504 if LSW == nil then |
| 426 self:Print("This feature requires LilSparky's Workshop.") | 505 self:Print("This feature requires LilSparky's Workshop.") |
| 430 elseif AucAdvanced and AucAdvanced.Version then | 509 elseif AucAdvanced and AucAdvanced.Version then |
| 431 else | 510 else |
| 432 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.") | 511 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.") |
| 433 return | 512 return |
| 434 end | 513 end |
| 435 wipe(realData) | 514 local tradeskillName = GetTradeSkillLine() |
| 515 Crafting.ClearProfession(tradeskillName) | |
| 516 shoppingList = nil | |
| 517 | |
| 436 wipe(tableData) | 518 wipe(tableData) |
| 437 | 519 |
| 438 local profitableItems = {} | 520 local profitableItems = {} |
| 439 local profitableIndex = 1 | 521 local profitableIndex = 1 |
| 440 local numChecked = 0 | 522 local numChecked = 0 |
| 441 local row = 1 | 523 local row = #(realData)+1 |
| 442 | 524 local numTradeSkills = GetNumTradeSkills() |
| 443 for i = 1, GetNumTradeSkills() do | 525 if tradeskillName == 'UNKNOWN' then |
| 526 numTradeSkills = 0 | |
| 527 end | |
| 528 | |
| 529 for i = 1, numTradeSkills do | |
| 444 local itemLink = GetTradeSkillItemLink(i) | 530 local itemLink = GetTradeSkillItemLink(i) |
| 445 local itemId = Utils.GetItemID(itemLink) | 531 local itemId = Utils.GetItemID(itemLink) |
| 446 local vellumID = nil | 532 local vellumID = nil |
| 533 | |
| 534 local spellName = itemName | |
| 447 | 535 |
| 448 --Figure out if its an enchant or not | 536 --Figure out if its an enchant or not |
| 449 _, _, _, _, altVerb = GetTradeSkillInfo(i) | 537 _, _, _, _, altVerb = GetTradeSkillInfo(i) |
| 450 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then | 538 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then |
| 451 -- Ask LSW for the correct scroll | 539 -- Ask LSW for the correct scroll |
| 501 local data = { | 589 local data = { |
| 502 recipeLink = recipeLink, | 590 recipeLink = recipeLink, |
| 503 recipeID = Utils.GetItemID(recipeLink), | 591 recipeID = Utils.GetItemID(recipeLink), |
| 504 link = itemLink, | 592 link = itemLink, |
| 505 name = itemName, | 593 name = itemName, |
| 594 skillName = skillName, | |
| 506 count = count, | 595 count = count, |
| 507 price = price, | 596 price = price, |
| 508 cost = totalCost, | 597 cost = totalCost, |
| 509 profit = price - totalCost, | 598 profit = price - totalCost, |
| 510 reagents = reagents, | 599 reagents = reagents, |
| 511 count = count, | 600 count = count, |
| 512 tradeSkillIndex = i, | 601 tradeSkillIndex = i, |
| 513 queue = 0, | 602 queue = 0, |
| 514 winner = "", | 603 winner = "", |
| 604 tradeskillName = tradeskillName, | |
| 515 } | 605 } |
| 516 | 606 |
| 517 data.winner, data.queue = Decide(data) | 607 data.winner, data.queue = Decide(data) |
| 518 --[[ | 608 --[[ |
| 519 If it wasn't vetoed we need to reduce the number by how many are owned | 609 If it wasn't vetoed we need to reduce the number by how many are owned |
| 524 end | 614 end |
| 525 | 615 |
| 526 -- If a tradeskill makes 5 at a time and something asks for 9, we should only | 616 -- If a tradeskill makes 5 at a time and something asks for 9, we should only |
| 527 -- craft twice to get 10. | 617 -- craft twice to get 10. |
| 528 data.queue = ceil(data.queue / GetTradeSkillNumMade(i)) | 618 data.queue = ceil(data.queue / GetTradeSkillNumMade(i)) |
| 529 | 619 |
| 530 realData[row] = data | 620 realData[row] = data |
| 621 nameMap[skillName] = row | |
| 531 row = row + 1 | 622 row = row + 1 |
| 532 end | 623 end |
| 533 end | 624 end |
| 534 end | 625 end |
| 535 table.sort(realData, function(a, b) return a.profit*max(1, a.queue) > b.profit*max(1, b.queue) end) | 626 table.sort(realData, function(a, b) return a.profit*max(1, a.queue) > b.profit*max(1, b.queue) end) |
| 562 craftingTable:SetFilter(tableFilter) | 653 craftingTable:SetFilter(tableFilter) |
| 563 self:RefreshCraftingTable() | 654 self:RefreshCraftingTable() |
| 564 end | 655 end |
| 565 end | 656 end |
| 566 | 657 |
| 658 | |
| 659 local numOwned = {} | |
| 660 | |
| 661 local function BuildShoppingList(character, queue) | |
| 662 for key, data in pairs(queue) do | |
| 663 if data.queue > 0 then | |
| 664 for id, reagent in pairs(data.reagents) do | |
| 665 if not numOwned[reagent.link] then | |
| 666 numOwned[reagent.link] = ItemAuditor:GetItemCount(Utils.GetItemID(reagent.link)) | |
| 667 end | |
| 668 numOwned[reagent.link] = numOwned[reagent.link] - reagent.count | |
| 669 | |
| 670 shoppingList[reagent.itemID] = shoppingList[reagent.itemID] or { | |
| 671 total = 0, | |
| 672 need = 0, | |
| 673 characters = {} | |
| 674 } | |
| 675 local slItem = shoppingList[reagent.itemID] | |
| 676 | |
| 677 | |
| 678 if numOwned[reagent.link] < 0 and not vellumLevelMap[reagent.itemID] then | |
| 679 reagent.need = min(reagent.count, abs(numOwned[reagent.link])) | |
| 680 elseif numOwned[reagent.link] >= 0 then | |
| 681 reagent.need = 0 | |
| 682 end | |
| 683 shoppingList[reagent.itemID].total = shoppingList[reagent.itemID].total + reagent.count | |
| 684 shoppingList[reagent.itemID].need = shoppingList[reagent.itemID].need + reagent.need | |
| 685 | |
| 686 slItem.characters[UnitName("player")] = slItem.characters[UnitName("player")] or {} | |
| 687 slItem.characters[UnitName("player")][data.recipeLink] = { | |
| 688 count = reagent.count, | |
| 689 need = reagent.need, | |
| 690 } | |
| 691 end | |
| 692 end | |
| 693 end | |
| 694 end | |
| 695 | |
| 696 function Crafting.GetShoppingList(itemID) | |
| 697 if not shoppingList then | |
| 698 shoppingList = {} | |
| 699 wipe(numOwned) | |
| 700 | |
| 701 -- This is done here instead of in the loop to make sure the current | |
| 702 -- character gets the first pick of materials. | |
| 703 local me = UnitName("player") | |
| 704 BuildShoppingList(me, realData) | |
| 705 | |
| 706 for alt, queue in pairs(ItemAuditor.db.factionrealm.queue) do | |
| 707 if alt ~= me then | |
| 708 BuildShoppingList(alt, queue) | |
| 709 end | |
| 710 end | |
| 711 elseif shoppingList[itemID] then | |
| 712 local data = shoppingList[itemID] | |
| 713 if data.need ~= max(0, data.total - ItemAuditor:GetItemCount(itemID)) then | |
| 714 shoppingList = nil | |
| 715 -- I'm rebuilding the list instead of just the item because | |
| 716 -- it will be eaiser than tracking down the queued recipes that | |
| 717 -- need to change. If this becomes a problem, I may change it. | |
| 718 return Crafting.GetShoppingList(itemID) | |
| 719 end | |
| 720 end | |
| 721 | |
| 722 return shoppingList[itemID] | |
| 723 end | |
| 724 | |
| 567 function ItemAuditor:RefreshCraftingTable() | 725 function ItemAuditor:RefreshCraftingTable() |
| 726 tableData = {} | |
| 727 nameMap = {} | |
| 568 for key, data in pairs(realData) do | 728 for key, data in pairs(realData) do |
| 729 nameMap[data.name] = key | |
| 730 | |
| 569 tableData[key] = { | 731 tableData[key] = { |
| 570 data.name, | 732 data.name, |
| 571 data.cost, | 733 data.cost, |
| 572 data.price, | 734 data.price, |
| 573 data.winner, | 735 data.winner, |
