Mercurial > wow > askmrrobot
comparison Gear.lua @ 129:d9a059484b22 v60
Several bug fixes for 8.0.
author | yellowfive |
---|---|
date | Wed, 18 Jul 2018 13:08:22 -0700 |
parents | e31b02b24488 |
children | a0894ffebd15 |
comparison
equal
deleted
inserted
replaced
128:b16e1f4d100e | 129:d9a059484b22 |
---|---|
82 -- given a table of items (keyed or indexed doesn't matter) find closest match to item, or nil if none are a match | 82 -- given a table of items (keyed or indexed doesn't matter) find closest match to item, or nil if none are a match |
83 local function findMatchingItemFromTable(item, list, bestItem, bestDiff, bestLoc, usedItems, tableType) | 83 local function findMatchingItemFromTable(item, list, bestItem, bestDiff, bestLoc, usedItems, tableType) |
84 if not list then return nil end | 84 if not list then return nil end |
85 | 85 |
86 local found = false | 86 local found = false |
87 for k,listItem in pairs(list) do | 87 for k,listItem in pairs(list) do |
88 if listItem then | 88 if listItem then |
89 local diff = countItemDifferences(item, listItem) | 89 local diff = countItemDifferences(item, listItem) |
90 if diff < bestDiff then | 90 if diff < bestDiff then |
91 -- each physical item can only be used once, the usedItems table has items we can't use in this search | 91 -- each physical item can only be used once, the usedItems table has items we can't use in this search |
92 local key = string.format("%s_%s", tableType, k) | 92 local key = string.format("%s_%s", tableType, k) |
110 | 110 |
111 local equipped = player.Equipped and player.Equipped[player.ActiveSpec] or nil | 111 local equipped = player.Equipped and player.Equipped[player.ActiveSpec] or nil |
112 local bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, equipped, nil, 10000, nil, usedItems, "equip") | 112 local bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, equipped, nil, 10000, nil, usedItems, "equip") |
113 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BagItems, bestItem, bestDiff, bestLoc, usedItems, "bag") | 113 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BagItems, bestItem, bestDiff, bestLoc, usedItems, "bag") |
114 if player.BankItems then | 114 if player.BankItems then |
115 for bagId,bagList in pairs(player.BankItems) do | 115 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BankItems, bestItem, bestDiff, bestLoc, usedItems, "bank") |
116 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, bagList, bestItem, bestDiff, bestLoc, usedItems, "bank" .. bagId) | |
117 end | |
118 end | 116 end |
119 | 117 |
120 if bestDiff >= 10000 then | 118 if bestDiff >= 10000 then |
121 return nil, 10000 | 119 return nil, 10000 |
122 else | 120 else |
590 bestItem, bestDiff, bestLink = scanBagForItem(item, BACKPACK_CONTAINER, bestItem, bestDiff, bestLink) | 588 bestItem, bestDiff, bestLink = scanBagForItem(item, BACKPACK_CONTAINER, bestItem, bestDiff, bestLink) |
591 for bagId = 1, NUM_BAG_SLOTS do | 589 for bagId = 1, NUM_BAG_SLOTS do |
592 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink) | 590 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink) |
593 end | 591 end |
594 | 592 |
593 -- with new approach, the item to use should never be equipped, should be in bags at this point | |
594 --[[ | |
595 -- equipped items, but skip slots we have just equipped (to avoid e.g. just moving 2 of the same item back and forth between mh oh weapon slots) | 595 -- equipped items, but skip slots we have just equipped (to avoid e.g. just moving 2 of the same item back and forth between mh oh weapon slots) |
596 for slotNum = 1, #Amr.SlotIds do | 596 for slotNum = 1, #Amr.SlotIds do |
597 local slotId = Amr.SlotIds[slotNum] | 597 local slotId = Amr.SlotIds[slotNum] |
598 if _currentGearOp.slotsRemaining[slotId] then | 598 if _currentGearOp.slotsRemaining[slotId] then |
599 local itemLink = GetInventoryItemLink("player", slotId) | 599 local itemLink = GetInventoryItemLink("player", slotId) |
608 end | 608 end |
609 end | 609 end |
610 end | 610 end |
611 end | 611 end |
612 end | 612 end |
613 | 613 ]] |
614 | |
614 -- bank | 615 -- bank |
615 if bestDiff > 0 then | 616 if bestDiff > 0 then |
616 bestItem, bestDiff, bestLink = scanBagForItem(item, BANK_CONTAINER, bestItem, bestDiff, bestLink) | 617 bestItem, bestDiff, bestLink = scanBagForItem(item, BANK_CONTAINER, bestItem, bestDiff, bestLink) |
617 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do | 618 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do |
618 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink) | 619 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink) |
751 -- if an item is not soulbound, then warn the user and quit | 752 -- if an item is not soulbound, then warn the user and quit |
752 Amr:Print(L.GearEquipErrorSoulbound(bestLink)) | 753 Amr:Print(L.GearEquipErrorSoulbound(bestLink)) |
753 disposeGearOp() | 754 disposeGearOp() |
754 | 755 |
755 else | 756 else |
757 | |
758 --print("equipping " .. bestLink .. " in slot " .. _currentGearOp.nextSlot) | |
756 | 759 |
757 -- an item in the player's bags or already equipped, equip it | 760 -- an item in the player's bags or already equipped, equip it |
758 if bestItem.bag then | 761 if bestItem.bag then |
759 PickupContainerItem(bestItem.bag, bestItem.slot) | 762 PickupContainerItem(bestItem.bag, bestItem.slot) |
760 else | 763 else |
895 tbl[i], tbl[rand] = tbl[rand], tbl[i] | 898 tbl[i], tbl[rand] = tbl[rand], tbl[i] |
896 end | 899 end |
897 return tbl | 900 return tbl |
898 end | 901 end |
899 | 902 |
903 local _ohFirst = { | |
904 [20] = true, -- PaladinProtection | |
905 [32] = true, -- WarlockDemonology | |
906 [36] = true -- WarriorProtection | |
907 } | |
908 | |
900 function beginEquipGearSet(spec, passes) | 909 function beginEquipGearSet(spec, passes) |
901 | 910 |
902 local gear = Amr.db.char.GearSets[spec] | 911 local gear = Amr.db.char.GearSets[spec] |
903 if not gear then | 912 if not gear then |
904 Amr:Print(L.GearEquipErrorEmpty) | 913 Amr:Print(L.GearEquipErrorEmpty) |
905 return | 914 return |
906 end | 915 end |
907 | 916 |
908 -- ensure all our stored data is up to date | 917 -- ensure all our stored data is up to date |
909 local player = Amr:ExportCharacter() | 918 local player = Amr:ExportCharacter() |
919 local doOhFirst = _ohFirst[player.Specs[spec]] | |
910 | 920 |
911 local itemsToEquip = { | 921 local itemsToEquip = { |
912 legendaries = {}, | 922 legendaries = {}, |
913 weapons = {}, | 923 weapons = {}, |
924 mh = {}, | |
925 oh = {}, | |
914 rings = {}, | 926 rings = {}, |
915 trinkets = {}, | 927 trinkets = {}, |
916 others = {}, | 928 others = {}, |
917 blanks = {} | 929 blanks = {} |
918 } | 930 } |
919 local remaining = 0 | 931 local remaining = 0 |
920 local usedItems = {} | 932 local usedItems = {} |
921 | 933 |
922 -- check for items that need to be equipped, do in a random order to try and defeat any unique constraint issues we might hit | 934 -- check for items that need to be equipped, do in a random order to try and defeat any unique constraint issues we might hit |
923 local slots = {} | 935 local slots = {} |
924 for i,s in ipairs(Amr.SlotIds) do | 936 for i,s in ipairs(Amr.SlotIds) do |
925 table.insert(slots, s) | 937 table.insert(slots, s) |
928 | 940 |
929 for i,slotId in ipairs(slots) do | 941 for i,slotId in ipairs(slots) do |
930 | 942 |
931 -- we do stuff in batches that avoids most unique conflicts | 943 -- we do stuff in batches that avoids most unique conflicts |
932 local list = itemsToEquip.others | 944 local list = itemsToEquip.others |
933 if slotId == 16 or slotId == 17 then | 945 if slotId == 16 then |
934 list = itemsToEquip.weapons | 946 list = itemsToEquip.mh |
947 elseif slotId == 17 then | |
948 list = itemsToEquip.oh | |
935 elseif slotId == 11 or slotId == 12 then | 949 elseif slotId == 11 or slotId == 12 then |
936 list = itemsToEquip.rings | 950 list = itemsToEquip.rings |
937 elseif slotId == 13 or slotId == 14 then | 951 elseif slotId == 13 or slotId == 14 then |
938 list = itemsToEquip.trinkets | 952 list = itemsToEquip.trinkets |
939 end | 953 end |
946 local newItem = Item:CreateFromItemID(new.id) | 960 local newItem = Item:CreateFromItemID(new.id) |
947 local quality = newItem and newItem:GetItemQuality() or 0 | 961 local quality = newItem and newItem:GetItemQuality() or 0 |
948 if quality == 6 then | 962 if quality == 6 then |
949 if not old or new.id ~= old.id then | 963 if not old or new.id ~= old.id then |
950 list[slotId] = new | 964 list[slotId] = new |
965 if list == itemsToEquip.mh or list == itemsToEquip.oh then | |
966 itemsToEquip.weapons[slotId] = {} | |
967 end | |
951 remaining = remaining + 1 | 968 remaining = remaining + 1 |
952 end | 969 end |
953 else | 970 else |
971 -- find the best matching item anywhere in the player's gear | |
972 local bestItem, bestDiff = Amr:FindMatchingItem(new, player, usedItems) | |
973 new = bestItem | |
974 | |
954 local diff = countItemDifferences(old, new) | 975 local diff = countItemDifferences(old, new) |
976 | |
977 --[[ | |
955 if diff > 0 and diff < 1000 then | 978 if diff > 0 and diff < 1000 then |
956 -- same item, see if inventory has one that is closer (e.g. a duplicate item with correct enchants/gems) | 979 -- same item, see if inventory has one that is closer (e.g. a duplicate item with correct enchants/gems) |
957 local bestItem, bestDiff = Amr:FindMatchingItem(new, player, usedItems) | 980 local bestItem, bestDiff = Amr:FindMatchingItem(new, player, usedItems) |
958 if bestDiff and bestDiff < diff then | 981 if bestDiff and bestDiff < diff then |
959 new = bestItem | 982 new = bestItem |
960 diff = bestDiff | 983 diff = bestDiff |
961 end | 984 end |
962 end | 985 end |
963 | 986 ]] |
964 if diff > 0 then | 987 |
988 if diff > 0 then | |
965 list[slotId] = new | 989 list[slotId] = new |
990 if list == itemsToEquip.mh or list == itemsToEquip.oh then | |
991 itemsToEquip.weapons[slotId] = {} | |
992 end | |
966 remaining = remaining + 1 | 993 remaining = remaining + 1 |
967 end | 994 end |
968 end | 995 end |
969 else | 996 elseif old then |
970 -- need to remove this item | 997 -- need to remove this item |
971 itemsToEquip.blanks[slotId] = {} | 998 itemsToEquip.blanks[slotId] = {} |
972 remaining = remaining + 1 | 999 remaining = remaining + 1 |
973 end | 1000 end |
974 | 1001 |
986 if remaining > 0 then | 1013 if remaining > 0 then |
987 | 1014 |
988 if passes < 5 then | 1015 if passes < 5 then |
989 _pendingGearOps = {} | 1016 _pendingGearOps = {} |
990 | 1017 |
991 if not Amr.IsEmpty(itemsToEquip.blanks) then | 1018 if not Amr.IsEmpty(itemsToEquip.blanks) then |
992 -- if gear set wants slots to be blank, do that first | 1019 -- if gear set wants slots to be blank, do that first |
993 table.insert(_pendingGearOps, { items = itemsToEquip.blanks, remove = true, label = "blanks" }) | 1020 table.insert(_pendingGearOps, { items = itemsToEquip.blanks, remove = true, label = "blanks" }) |
994 end | 1021 end |
995 if not Amr.IsEmpty(itemsToEquip.weapons) then | 1022 if not Amr.IsEmpty(itemsToEquip.weapons) then |
996 -- change weapons first: remove both, wait, then equip new ones | 1023 -- change weapons first: remove both, wait, then equip each weapon one by one, waiting after each |
997 table.insert(_pendingGearOps, { items = itemsToEquip.weapons, remove = true, label = "remove weapons" }) | 1024 table.insert(_pendingGearOps, { items = itemsToEquip.weapons, remove = true, label = "remove weapons" }) |
998 table.insert(_pendingGearOps, { items = itemsToEquip.weapons, wait = true, label = "equip weapons" }) | 1025 local thisWeapon = doOhFirst and itemsToEquip.oh or itemsToEquip.mh |
1026 if not Amr.IsEmpty(thisWeapon) then | |
1027 table.insert(_pendingGearOps, { items = thisWeapon, wait = true, label = "equip weapon 1" }) | |
1028 end | |
1029 thisWeapon = doOhFirst and itemsToEquip.mh or itemsToEquip.oh | |
1030 if not Amr.IsEmpty(thisWeapon) then | |
1031 table.insert(_pendingGearOps, { items = thisWeapon, wait = true, label = "equip weapon 2" }) | |
1032 end | |
999 end | 1033 end |
1000 if not Amr.IsEmpty(itemsToEquip.legendaries) then | 1034 if not Amr.IsEmpty(itemsToEquip.legendaries) then |
1001 -- remove any legendaries, wait | 1035 -- remove any legendaries, wait |
1002 table.insert(_pendingGearOps, { items = itemsToEquip.legendaries, remove = true, label = "remove legendaries" }) | 1036 table.insert(_pendingGearOps, { items = itemsToEquip.legendaries, remove = true, label = "remove legendaries" }) |
1003 end | 1037 end |
1039 | 1073 |
1040 local function onActiveTalentGroupChanged() | 1074 local function onActiveTalentGroupChanged() |
1041 | 1075 |
1042 local auto = Amr.db.profile.options.autoGear | 1076 local auto = Amr.db.profile.options.autoGear |
1043 local currentSpec = GetSpecialization() | 1077 local currentSpec = GetSpecialization() |
1044 | 1078 local waitingSpec = _waitingForSpec |
1045 if currentSpec == _waitingForSpec or auto then | |
1046 -- spec is what we want, now equip the gear | |
1047 beginEquipGearSet(currentSpec, 0) | |
1048 end | |
1049 | |
1050 _waitingForSpec = 0 | 1079 _waitingForSpec = 0 |
1080 | |
1081 if currentSpec == waitingSpec or auto then | |
1082 -- spec is what we want, now equip the gear but after a short delay because the game auto-swaps artifact weapons | |
1083 Amr.Wait(2, function() | |
1084 beginEquipGearSet(GetSpecialization(), 0) | |
1085 end) | |
1086 end | |
1051 end | 1087 end |
1052 | 1088 |
1053 -- activate the specified spec and then equip the saved gear set | 1089 -- activate the specified spec and then equip the saved gear set |
1054 function Amr:EquipGearSet(spec) | 1090 function Amr:EquipGearSet(spec) |
1055 | 1091 |
1067 if UnitAffectingCombat("player") then | 1103 if UnitAffectingCombat("player") then |
1068 Amr:Print(L.GearEquipErrorCombat) | 1104 Amr:Print(L.GearEquipErrorCombat) |
1069 return | 1105 return |
1070 end | 1106 end |
1071 | 1107 |
1072 _waitingForSpec = spec | |
1073 | |
1074 local currentSpec = GetSpecialization() | 1108 local currentSpec = GetSpecialization() |
1075 if currentSpec ~= spec then | 1109 if currentSpec ~= spec then |
1110 _waitingForSpec = spec | |
1076 SetSpecialization(spec) | 1111 SetSpecialization(spec) |
1077 else | 1112 else |
1078 onActiveTalentGroupChanged() | 1113 -- spec is what we want, now equip the gear |
1114 beginEquipGearSet(currentSpec, 0) | |
1079 end | 1115 end |
1080 end | 1116 end |
1081 | 1117 |
1082 -- moves any gear in bags to the bank if not part of a gear set | 1118 -- moves any gear in bags to the bank if not part of a gear set |
1083 function Amr:CleanBags() | 1119 function Amr:CleanBags() |