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