Mercurial > wow > askmrrobot
comparison Gear.lua @ 139:c229c759a125 v65
Update to support multiple setups per spec.
author | yellowfive |
---|---|
date | Mon, 05 Nov 2018 16:06:00 -0800 |
parents | 6dc0e8e9f960 |
children | 55823e37403b |
comparison
equal
deleted
inserted
replaced
138:45e467335a1b | 139:c229c759a125 |
---|---|
1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") | 1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") |
2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) | 2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) |
3 local AceGUI = LibStub("AceGUI-3.0") | 3 local AceGUI = LibStub("AceGUI-3.0") |
4 | 4 |
5 local _gearTabs | 5 local _cboSetups |
6 local _activeTab | 6 local _panelGear |
7 local _activeSetupId | |
8 | |
9 local function getSetupById(id) | |
10 if not id then | |
11 id = _activeSetupId | |
12 end | |
13 local setup | |
14 for i,s in ipairs(Amr.db.char.GearSetups) do | |
15 if s.Id == id then | |
16 setup = s | |
17 break | |
18 end | |
19 end | |
20 return setup | |
21 end | |
7 | 22 |
8 -- Returns a number indicating how different two items are (0 means the same, higher means more different) | 23 -- Returns a number indicating how different two items are (0 means the same, higher means more different) |
9 local function countItemDifferences(item1, item2) | 24 local function countItemDifferences(item1, item2) |
10 -- both nil, the same | 25 -- both nil, the same |
11 if not item1 and not item2 then | 26 if not item1 and not item2 then |
186 socketIcon:SetHeight(18) | 201 socketIcon:SetHeight(18) |
187 | 202 |
188 return socketBorder, socketIcon | 203 return socketBorder, socketIcon |
189 end | 204 end |
190 | 205 |
191 local function renderGear(spec, container) | 206 local function renderGear(setupId, container) |
207 | |
208 -- release all children that were previously rendered, we gonna redo it now | |
209 container:ReleaseChildren() | |
192 | 210 |
193 local player = Amr:ExportCharacter() | 211 local player = Amr:ExportCharacter() |
194 local gear = Amr.db.char.GearSets[spec] | 212 |
213 local gear | |
214 local spec | |
215 local setupIndex | |
216 for i, setup in ipairs(Amr.db.char.GearSetups) do | |
217 if setup.Id == setupId then | |
218 setupIndex = i | |
219 gear = setup.Gear | |
220 spec = setup.SpecSlot | |
221 break | |
222 end | |
223 end | |
224 | |
195 local equipped = player.Equipped[player.ActiveSpec] | 225 local equipped = player.Equipped[player.ActiveSpec] |
196 | 226 |
197 if not gear then | 227 if not gear then |
198 -- no gear has been imported for this spec so show a message | 228 -- no gear has been imported for this spec so show a message |
199 renderEmptyGear(container) | 229 renderEmptyGear(container) |
234 btnEquip:SetBackgroundColor(Amr.Colors.Green) | 264 btnEquip:SetBackgroundColor(Amr.Colors.Green) |
235 btnEquip:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White)) | 265 btnEquip:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White)) |
236 btnEquip:SetWidth(300) | 266 btnEquip:SetWidth(300) |
237 btnEquip:SetHeight(26) | 267 btnEquip:SetHeight(26) |
238 btnEquip:SetCallback("OnClick", function(widget) | 268 btnEquip:SetCallback("OnClick", function(widget) |
239 Amr:EquipGearSet(spec) | 269 Amr:EquipGearSet(setupIndex) |
240 end) | 270 end) |
241 panelGear:AddChild(btnEquip) | 271 panelGear:AddChild(btnEquip) |
242 btnEquip:SetPoint("LEFT", icon.frame, "RIGHT", 40, 0) | 272 btnEquip:SetPoint("LEFT", icon.frame, "RIGHT", 40, 0) |
243 btnEquip:SetPoint("RIGHT", panelGear.content, "RIGHT", -40, 0) | 273 btnEquip:SetPoint("RIGHT", panelGear.content, "RIGHT", -40, 0) |
244 | 274 |
390 prevElem = lbl | 420 prevElem = lbl |
391 end | 421 end |
392 end | 422 end |
393 end | 423 end |
394 | 424 |
395 local function onGearTabSelected(container, event, group) | 425 local function onSetupChange(widget, eventName, value) |
396 container:ReleaseChildren() | 426 _activeSetupId = value |
397 _activeTab = group | 427 renderGear(_activeSetupId, _panelGear) |
398 renderGear(tonumber(group), container) | |
399 end | 428 end |
400 | 429 |
401 local function onImportClick(widget) | 430 local function onImportClick(widget) |
402 Amr:ShowImportWindow() | 431 Amr:ShowImportWindow() |
432 end | |
433 | |
434 function Amr:PickFirstSetupForSpec() | |
435 local specSlot = GetSpecialization() | |
436 for i, setup in ipairs(Amr.db.char.GearSetups) do | |
437 if setup.SpecSlot == specSlot then | |
438 _activeSetupId = setup.Id | |
439 break | |
440 end | |
441 end | |
442 end | |
443 | |
444 function Amr:GetActiveSetupId() | |
445 return _activeSetupId | |
446 end | |
447 | |
448 function Amr:SetActiveSetupId(setupId) | |
449 _activeSetupId = setupId | |
450 end | |
451 | |
452 function Amr:GetActiveSetupLabel() | |
453 if not _activeSetupId then | |
454 return nil | |
455 end | |
456 local setup = getSetupById(_activeSetupId) | |
457 if not setup then | |
458 return nil | |
459 else | |
460 return setup.Label | |
461 end | |
403 end | 462 end |
404 | 463 |
405 -- renders the main UI for the Gear tab | 464 -- renders the main UI for the Gear tab |
406 function Amr:RenderTabGear(container) | 465 function Amr:RenderTabGear(container) |
407 | 466 |
444 lbl2:SetText(L.GearTipCommands) | 503 lbl2:SetText(L.GearTipCommands) |
445 lbl2:SetWidth(130) | 504 lbl2:SetWidth(130) |
446 lbl2:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text)) | 505 lbl2:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text)) |
447 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 10, -5) | 506 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 10, -5) |
448 | 507 |
449 local t = AceGUI:Create("AmrUiTabGroup") | 508 _cboSetups = AceGUI:Create("AmrUiDropDown") |
450 t:SetLayout("None") | 509 _cboSetups:SetWidth(300) |
451 | 510 container:AddChild(_cboSetups) |
452 local tabz = {} | 511 _cboSetups:SetPoint("TOPLEFT", container.content, "TOPLEFT", 150, -27.5) |
453 for pos = 1, 4 do | 512 |
454 local specId = GetSpecializationInfo(pos) | 513 _panelGear = AceGUI:Create("AmrUiPanel") |
455 if specId then | 514 _panelGear:SetLayout("None") |
456 table.insert(tabz, { text = L.SpecsShort[Amr.SpecIds[specId]], value = pos .. "", style = "bold" }) | 515 _panelGear:SetBackgroundColor(Amr.Colors.Bg) |
457 end | 516 container:AddChild(_panelGear) |
458 end | 517 _panelGear:SetPoint("TOPLEFT", container.content, "TOPLEFT", 144, -58) |
459 | 518 _panelGear:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT") |
460 t:SetTabs(tabz) | |
461 t:SetCallback("OnGroupSelected", onGearTabSelected) | |
462 container:AddChild(t) | |
463 t:SetPoint("TOPLEFT", container.content, "TOPLEFT", 144, -30) | |
464 t:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT") | |
465 _gearTabs = t; | |
466 | 519 |
467 local btnShop = AceGUI:Create("AmrUiButton") | 520 local btnShop = AceGUI:Create("AmrUiButton") |
468 btnShop:SetText(L.GearButtonShop) | 521 btnShop:SetText(L.GearButtonShop) |
469 btnShop:SetBackgroundColor(Amr.Colors.Blue) | 522 btnShop:SetBackgroundColor(Amr.Colors.Blue) |
470 btnShop:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White)) | 523 btnShop:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White)) |
471 btnShop:SetWidth(245) | 524 btnShop:SetWidth(245) |
472 btnShop:SetHeight(26) | 525 btnShop:SetHeight(26) |
473 btnShop:SetCallback("OnClick", function(widget) Amr:ShowShopWindow() end) | 526 btnShop:SetCallback("OnClick", function(widget) Amr:ShowShopWindow() end) |
474 container:AddChild(btnShop) | 527 container:AddChild(btnShop) |
475 btnShop:SetPoint("TOPRIGHT", container.content, "TOPRIGHT", -20, -25) | 528 btnShop:SetPoint("TOPRIGHT", container.content, "TOPRIGHT", -20, -25) |
476 | 529 |
477 if not _activeTab then | 530 -- pick a default tab based on player's current spec if none is already specified |
478 _activeTab = tostring(GetSpecialization()) | 531 if not _activeSetupId then |
479 end | 532 Amr:PickFirstSetupForSpec() |
480 | 533 end |
481 t:SelectTab(_activeTab) | 534 |
482 end | 535 Amr:RefreshGearDisplay() |
483 | 536 |
484 -- do cleanup when the gear tab is released | 537 -- set event on dropdown after UI has been initially rendered |
538 _cboSetups:SetCallback("OnChange", onSetupChange) | |
539 end | |
540 | |
485 function Amr:ReleaseTabGear() | 541 function Amr:ReleaseTabGear() |
486 _gearTabs = nil | 542 _cboSetups = nil |
487 end | 543 _panelGear = nil |
488 | |
489 -- show and update the gear tab for the specified spec | |
490 function Amr:ShowGearTab(spec) | |
491 if not _gearTabs then return end | |
492 | |
493 _activeTab = tostring(spec) | |
494 _gearTabs:SelectTab(_activeTab) | |
495 end | 544 end |
496 | 545 |
497 -- refresh display of the current gear tab | 546 -- refresh display of the current gear tab |
498 function Amr:RefreshGearTab() | 547 function Amr:RefreshGearDisplay() |
499 if not _gearTabs then return end | 548 |
500 _gearTabs:SelectTab(_activeTab) | 549 if not _panelGear then |
550 return | |
551 end | |
552 | |
553 -- fill the gear setup picker | |
554 local setupList = {} | |
555 for i, setup in ipairs(Amr.db.char.GearSetups) do | |
556 table.insert(setupList, { text = setup.Label, value = setup.Id }) | |
557 end | |
558 _cboSetups:SetItems(setupList) | |
559 | |
560 -- set selected value | |
561 local prev = _activeSetupId | |
562 _cboSetups:SelectItem(_activeSetupId) | |
563 | |
564 if prev == _activeSetupId then | |
565 -- selecting will trigger the change event if it changed; if it didn't change, do a render now | |
566 renderGear(_activeSetupId, _panelGear) | |
567 end | |
501 end | 568 end |
502 | 569 |
503 | 570 |
504 ------------------------------------------------------------------------------------------------ | 571 ------------------------------------------------------------------------------------------------ |
505 -- Gear Set Management | 572 -- Gear Set Management |
637 setIcon = itemObj:GetItemIcon() | 704 setIcon = itemObj:GetItemIcon() |
638 end | 705 end |
639 end | 706 end |
640 ]] | 707 ]] |
641 | 708 |
642 local setname = "AMR " .. specName | 709 local setup = getSetupById(_activeSetupId) |
710 local setname = setup.Label -- "AMR " .. specName | |
643 local setid = C_EquipmentSet.GetEquipmentSetID(setname) | 711 local setid = C_EquipmentSet.GetEquipmentSetID(setname) |
644 if setid then | 712 if setid then |
645 C_EquipmentSet.SaveEquipmentSet(setid, setIcon) | 713 C_EquipmentSet.SaveEquipmentSet(setid, setIcon) |
646 else | 714 else |
647 C_EquipmentSet.CreateEquipmentSet(setname, setIcon) | 715 C_EquipmentSet.CreateEquipmentSet(setname, setIcon) |
655 _itemLockAction = nil | 723 _itemLockAction = nil |
656 _gearOpPasses = 0 | 724 _gearOpPasses = 0 |
657 _gearOpWaiting = nil | 725 _gearOpWaiting = nil |
658 | 726 |
659 -- make sure the gear tab is still in sync | 727 -- make sure the gear tab is still in sync |
660 Amr:RefreshGearTab() | 728 Amr:RefreshGearDisplay() |
661 end | 729 end |
662 | 730 |
663 -- initialize a gear op to start running it | 731 -- initialize a gear op to start running it |
664 local function initializeGearOp(op, spec, pos) | 732 local function initializeGearOp(op, setupId, pos) |
665 op.pos = pos | 733 op.pos = pos |
666 op.spec = spec | 734 op.setupId = setupId |
667 | 735 |
668 -- fill the remaining slot list and set the starting slot | 736 -- fill the remaining slot list and set the starting slot |
669 op.nextSlot = nil | 737 op.nextSlot = nil |
670 op.slotsRemaining = {} | 738 op.slotsRemaining = {} |
671 op.isWaiting = false | 739 op.isWaiting = false |
788 | 856 |
789 -- when a gear op completes successfully, this will advance to the next op or finish | 857 -- when a gear op completes successfully, this will advance to the next op or finish |
790 function nextGearOp() | 858 function nextGearOp() |
791 if not _currentGearOp then return end | 859 if not _currentGearOp then return end |
792 | 860 |
793 local spec = _currentGearOp.spec | 861 local setupId = _currentGearOp.setupId |
794 local pos = _currentGearOp.pos | 862 local pos = _currentGearOp.pos |
795 local passes = _gearOpPasses | 863 local passes = _gearOpPasses |
796 | 864 |
797 -- mark the slot as done and move to the next | 865 -- mark the slot as done and move to the next |
798 if _currentGearOp.nextSlot then | 866 if _currentGearOp.nextSlot then |
815 _currentGearOp.isWaiting = true | 883 _currentGearOp.isWaiting = true |
816 else | 884 else |
817 _currentGearOp = _pendingGearOps[pos + 1] | 885 _currentGearOp = _pendingGearOps[pos + 1] |
818 if _currentGearOp then | 886 if _currentGearOp then |
819 -- we have another op, do it | 887 -- we have another op, do it |
820 initializeGearOp(_currentGearOp, spec, pos + 1) | 888 initializeGearOp(_currentGearOp, setupId, pos + 1) |
821 processCurrentGearOp() | 889 processCurrentGearOp() |
822 else | 890 else |
823 -- we are done | 891 -- we are done |
824 disposeGearOp() | 892 disposeGearOp() |
825 | 893 |
826 -- this will check if not all items were swapped, and either finish up, try again, or abort if have tried too many times | 894 -- this will check if not all items were swapped, and either finish up, try again, or abort if have tried too many times |
827 beginEquipGearSet(spec, passes + 1) | 895 beginEquipGearSet(setupId, passes + 1) |
828 end | 896 end |
829 end | 897 end |
830 else | 898 else |
831 -- do the next item | 899 -- do the next item |
832 processCurrentGearOp() | 900 processCurrentGearOp() |
905 [20] = true, -- PaladinProtection | 973 [20] = true, -- PaladinProtection |
906 [32] = true, -- WarlockDemonology | 974 [32] = true, -- WarlockDemonology |
907 [36] = true -- WarriorProtection | 975 [36] = true -- WarriorProtection |
908 } | 976 } |
909 | 977 |
910 function beginEquipGearSet(spec, passes) | 978 function beginEquipGearSet(setupId, passes) |
911 | 979 |
912 local gear = Amr.db.char.GearSets[spec] | 980 local setup = getSetupById(setupId) |
913 if not gear then | 981 |
982 if not setup or not setup.Gear then | |
914 Amr:Print(L.GearEquipErrorEmpty) | 983 Amr:Print(L.GearEquipErrorEmpty) |
915 return | 984 return |
916 end | 985 end |
917 | 986 |
918 -- ensure all our stored data is up to date | 987 local gear = setup.Gear |
988 local spec = setup.SpecSlot | |
989 | |
990 -- ensure all our stored data is up to date | |
919 local player = Amr:ExportCharacter() | 991 local player = Amr:ExportCharacter() |
920 local doOhFirst = _ohFirst[player.Specs[spec]] | 992 local doOhFirst = _ohFirst[player.Specs[spec]] |
921 | 993 |
922 local itemsToEquip = { | 994 local itemsToEquip = { |
923 legendaries = {}, | 995 legendaries = {}, |
1058 _gearOpWaiting = { inventory = {} } | 1130 _gearOpWaiting = { inventory = {} } |
1059 end | 1131 end |
1060 | 1132 |
1061 _gearOpPasses = passes | 1133 _gearOpPasses = passes |
1062 _currentGearOp = _pendingGearOps[1] | 1134 _currentGearOp = _pendingGearOps[1] |
1063 initializeGearOp(_currentGearOp, spec, 1) | 1135 initializeGearOp(_currentGearOp, setupId, 1) |
1064 | 1136 |
1065 processCurrentGearOp() | 1137 processCurrentGearOp() |
1066 else | 1138 else |
1067 -- TODO: print message that gear set couldn't be equipped | 1139 -- TODO: print message that gear set couldn't be equipped |
1068 end | 1140 end |
1077 local auto = Amr.db.profile.options.autoGear | 1149 local auto = Amr.db.profile.options.autoGear |
1078 local currentSpec = GetSpecialization() | 1150 local currentSpec = GetSpecialization() |
1079 local waitingSpec = _waitingForSpec | 1151 local waitingSpec = _waitingForSpec |
1080 _waitingForSpec = 0 | 1152 _waitingForSpec = 0 |
1081 | 1153 |
1154 -- when spec changes, change active setup to first one for this spec (does nothing if they have no setups for this spec) | |
1155 if _activeSetupId then | |
1156 local currentSetup = getSetupById(_activeSetupId) | |
1157 if currentSetup.SpecSlot ~= currentSpec then | |
1158 Amr:PickFirstSetupForSpec() | |
1159 end | |
1160 end | |
1161 | |
1082 if currentSpec == waitingSpec or auto then | 1162 if currentSpec == waitingSpec or auto then |
1083 -- spec is what we want, now equip the gear but after a short delay because the game auto-swaps artifact weapons | 1163 -- spec is what we want, now equip the gear but after a short delay because the game auto-swaps artifact weapons |
1084 Amr.Wait(2, function() | 1164 Amr.Wait(2, function() |
1085 beginEquipGearSet(GetSpecialization(), 0) | 1165 beginEquipGearSet(_activeSetupId, 0) |
1086 end) | 1166 end) |
1087 end | 1167 end |
1088 end | 1168 end |
1089 | 1169 |
1090 -- activate the specified spec and then equip the saved gear set | 1170 -- activate the specified spec and then equip the saved gear set |
1091 function Amr:EquipGearSet(spec) | 1171 function Amr:EquipGearSet(setupIndex) |
1092 | 1172 |
1093 -- if no argument, then cycle spec | 1173 -- if no argument, then cycle |
1094 if not spec then | 1174 if not setupIndex then |
1095 spec = GetSpecialization() + 1 | 1175 if not _activeSetupId then |
1096 end | 1176 Amr:PickFirstSetupForSpec() |
1097 | 1177 end |
1098 -- allow some flexibility in the arguments | 1178 for i,setup in ipairs(Amr.db.char.GearSetups) do |
1099 if spec == "1" or spec == "2" or spec == "3" or spec == "4" then spec = tonumber(spec) end | 1179 if setup.Id == _activeSetupId then |
1100 | 1180 setupIndex = i |
1101 local specId = GetSpecializationInfo(spec) | 1181 break |
1102 if not specId then spec = 1 end | 1182 end |
1103 | 1183 end |
1184 if not setupIndex then | |
1185 setupIndex = 1 | |
1186 else | |
1187 setupIndex = setupIndex + 1 | |
1188 end | |
1189 end | |
1190 | |
1191 setupIndex = tonumber(setupIndex) | |
1192 | |
1193 if setupIndex > #Amr.db.char.GearSetups then | |
1194 setupIndex = 1 | |
1195 end | |
1196 | |
1104 if UnitAffectingCombat("player") then | 1197 if UnitAffectingCombat("player") then |
1105 Amr:Print(L.GearEquipErrorCombat) | 1198 Amr:Print(L.GearEquipErrorCombat) |
1106 return | 1199 return |
1107 end | 1200 end |
1108 | 1201 |
1202 _activeSetupId = Amr.db.char.GearSetups[setupIndex].Id | |
1203 Amr:RefreshGearDisplay() | |
1204 | |
1205 local setup = Amr.db.char.GearSetups[setupIndex] | |
1109 local currentSpec = GetSpecialization() | 1206 local currentSpec = GetSpecialization() |
1110 if currentSpec ~= spec then | 1207 if currentSpec ~= setup.SpecSlot then |
1111 _waitingForSpec = spec | 1208 _waitingForSpec = setup.SpecSlot |
1112 SetSpecialization(spec) | 1209 SetSpecialization(setup.SpecSlot) |
1113 else | 1210 else |
1114 -- spec is what we want, now equip the gear | 1211 -- spec is what we want, now equip the gear |
1115 beginEquipGearSet(currentSpec, 0) | 1212 beginEquipGearSet(_activeSetupId, 0) |
1116 end | 1213 end |
1117 end | 1214 end |
1118 | 1215 |
1119 -- moves any gear in bags to the bank if not part of a gear set | 1216 -- moves any gear in bags to the bank if not part of a gear set |
1120 function Amr:CleanBags() | 1217 function Amr:CleanBags() |
1136 if unitID and unitID ~= "player" then return end | 1233 if unitID and unitID ~= "player" then return end |
1137 | 1234 |
1138 -- don't update during a gear operation, wait until it is totally finished | 1235 -- don't update during a gear operation, wait until it is totally finished |
1139 if _pendingGearOps then return end | 1236 if _pendingGearOps then return end |
1140 | 1237 |
1141 Amr:RefreshGearTab() | 1238 Amr:RefreshGearDisplay() |
1142 end) | 1239 end) |
1143 | 1240 |
1144 Amr:AddEventHandler("ITEM_UNLOCKED", handleItemUnlocked) | 1241 Amr:AddEventHandler("ITEM_UNLOCKED", handleItemUnlocked) |
1145 end | 1242 end |