├── .pkgmeta
├── Textures
├── Buttons.blp
├── TrinketMenu-Gear.blp
├── TrinketMenu-Icon-Up.tga
└── TrinketMenu-Icon-Down.tga
├── TrinketMenu.toc
├── Bindings.xml
├── Libs
└── LibStub
│ └── LibStub.lua
├── TrinketMenuGlobals.lua
├── TrinketMenu.xml
├── TrinketMenuOpt.lua
├── Readme.txt
├── TrinketMenuOpt.xml
├── TrinketMenuQueue.lua
├── TrinketMenuQueue.xml
└── TrinketMenu.lua
/.pkgmeta:
--------------------------------------------------------------------------------
1 | package-as: TrinketMenu
2 |
3 | enable-nolib-creation: no
4 |
--------------------------------------------------------------------------------
/Textures/Buttons.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Resike/TrinketMenu/HEAD/Textures/Buttons.blp
--------------------------------------------------------------------------------
/Textures/TrinketMenu-Gear.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Resike/TrinketMenu/HEAD/Textures/TrinketMenu-Gear.blp
--------------------------------------------------------------------------------
/Textures/TrinketMenu-Icon-Up.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Resike/TrinketMenu/HEAD/Textures/TrinketMenu-Icon-Up.tga
--------------------------------------------------------------------------------
/Textures/TrinketMenu-Icon-Down.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Resike/TrinketMenu/HEAD/Textures/TrinketMenu-Icon-Down.tga
--------------------------------------------------------------------------------
/TrinketMenu.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 110105, 40402, 11507
2 | ## Title: TrinketMenu 11.1.8
3 | ## Version: 11.1.8
4 | ## Author: Gello, Resike
5 | ## Notes: Addon to manage trinkets.
6 | ## SavedVariables: TrinketMenuOptions
7 | ## SavedVariablesPerCharacter: TrinketMenuPerOptions, TrinketMenuQueue
8 |
9 | Libs\LibStub\LibStub.lua
10 |
11 | TrinketMenuGlobals.lua
12 | TrinketMenu.lua
13 | TrinketMenu.xml
14 | TrinketMenuOpt.lua
15 | TrinketMenuOpt.xml
16 | TrinketMenuQueue.lua
17 | TrinketMenuQueue.xml
18 |
--------------------------------------------------------------------------------
/Bindings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | TrinketMenu.ToggleFrame(TrinketMenuOptions.DisableToggle == "ON" and TrinketMenu_OptFrame or TrinketMenu_MainFrame)
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Libs/LibStub/LibStub.lua:
--------------------------------------------------------------------------------
1 | -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
2 | -- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
3 | local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
4 | local LibStub = _G[LIBSTUB_MAJOR]
5 |
6 | if not LibStub or LibStub.minor < LIBSTUB_MINOR then
7 | LibStub = LibStub or {libs = {}, minors = {} }
8 | _G[LIBSTUB_MAJOR] = LibStub
9 | LibStub.minor = LIBSTUB_MINOR
10 |
11 | function LibStub:NewLibrary(major, minor)
12 | assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
13 | minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
14 |
15 | local oldminor = self.minors[major]
16 | if oldminor and oldminor >= minor then return nil end
17 | self.minors[major], self.libs[major] = minor, self.libs[major] or {}
18 | return self.libs[major], oldminor
19 | end
20 |
21 | function LibStub:GetLibrary(major, silent)
22 | if not self.libs[major] and not silent then
23 | error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
24 | end
25 | return self.libs[major], self.minors[major]
26 | end
27 |
28 | function LibStub:IterateLibraries() return pairs(self.libs) end
29 | setmetatable(LibStub, { __call = LibStub.GetLibrary })
30 | end
31 |
--------------------------------------------------------------------------------
/TrinketMenuGlobals.lua:
--------------------------------------------------------------------------------
1 | TRINKETMENU_BACKDROP_16_16_4444 = {
2 | bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
3 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
4 | tile = true,
5 | tileEdge = true,
6 | tileSize = 16,
7 | edgeSize = 16,
8 | insets = { left = 4, right = 4, top = 4, bottom = 4 },
9 | }
10 | TRINKETMENU_BACKDROP_16 = {
11 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
12 | edgeSize = 16,
13 | }
14 | TRINKETMENU_SLIDER_BACKDROP = {
15 | bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
16 | edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
17 | tile = true,
18 | tileEdge = true,
19 | tileSize = 8,
20 | edgeSize = 8,
21 | insets = { left = 3, right = 3, top = 6, bottom = 6 },
22 | }
23 |
24 | local BackdropTemplatePolyfillMixin = {}
25 |
26 | function BackdropTemplatePolyfillMixin:OnBackdropLoaded()
27 | if not self.backdropInfo then
28 | return
29 | end
30 |
31 | if not self.backdropInfo.edgeFile and not self.backdropInfo.bgFile then
32 | self.backdropInfo = nil
33 | return
34 | end
35 |
36 | self:ApplyBackdrop()
37 |
38 | if self.backdropColor then
39 | local r, g, b = self.backdropColor:GetRGB()
40 | self:SetBackdropColor(r, g, b, self.backdropColorAlpha or 1)
41 | end
42 |
43 | if self.backdropBorderColor then
44 | local r, g, b = self.backdropBorderColor:GetRGB()
45 | self:SetBackdropBorderColor(r, g, b, self.backdropBorderColorAlpha or 1)
46 | end
47 |
48 | if self.backdropBorderBlendMode then
49 | self:SetBackdropBorderBlendMode(self.backdropBorderBlendMode)
50 | end
51 | end
52 |
53 | function BackdropTemplatePolyfillMixin:OnBackdropSizeChanged()
54 | if self.backdropInfo then
55 | self:SetupTextureCoordinates()
56 | end
57 | end
58 |
59 | function BackdropTemplatePolyfillMixin:ApplyBackdrop()
60 | -- The SetBackdrop call will implicitly reset the background and border
61 | -- texture vertex colors to white, consistent across all client versions.
62 |
63 | self:SetBackdrop(self.backdropInfo)
64 | end
65 |
66 | function BackdropTemplatePolyfillMixin:ClearBackdrop()
67 | self:SetBackdrop(nil)
68 | self.backdropInfo = nil
69 | end
70 |
71 | function BackdropTemplatePolyfillMixin:GetEdgeSize()
72 | -- The below will indeed error if there's no backdrop assigned this is
73 | -- consistent with how it works on 9.x clients.
74 |
75 | return self.backdropInfo.edgeSize or 39
76 | end
77 |
78 | function BackdropTemplatePolyfillMixin:HasBackdropInfo(backdropInfo)
79 | return self.backdropInfo == backdropInfo
80 | end
81 |
82 | function BackdropTemplatePolyfillMixin:SetBorderBlendMode()
83 | -- The pre-9.x API doesn't support setting blend modes for backdrop
84 | -- borders, so this is a no-op that just exists in case we ever assume
85 | -- it exists.
86 | end
87 |
88 | function BackdropTemplatePolyfillMixin:SetupPieceVisuals()
89 | -- Deliberate no-op as backdrop internals are handled C-side pre-9.x.
90 | end
91 |
92 | function BackdropTemplatePolyfillMixin:SetupTextureCoordinates()
93 | -- Deliberate no-op as texture coordinates are handled C-side pre-9.x.
94 | end
95 |
96 | TrinketMenuBackdropTemplateMixin = CreateFromMixins(BackdropTemplateMixin or BackdropTemplatePolyfillMixin)
97 |
--------------------------------------------------------------------------------
/TrinketMenu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | self:RegisterForClicks("LeftButtonUp", "RightButtonUp")
14 | if self.TogglePopup then
15 | self.TogglePopup = function() end
16 | end
17 |
18 |
19 | if self.Arrow then
20 | self.Arrow:SetShown(false)
21 | end
22 |
23 |
24 | TrinketMenu.MainTrinket_OnClick(self, button, down)
25 |
26 |
27 | if TrinketMenuOptions.MenuOnRight == "OFF" then
28 | TrinketMenu.BuildMenu()
29 | end
30 | TrinketMenu.WornTrinketTooltip(self)
31 |
32 |
33 | TrinketMenu.ClearTooltip()
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | self:RegisterForClicks("LeftButtonUp", "RightButtonUp")
42 | if self.TogglePopup then
43 | self.TogglePopup = function() end
44 | end
45 | if self.cooldown then
46 | self.cooldown:SetSwipeColor(0, 0, 0, 0.8)
47 | end
48 | if self.icon then
49 | self.icon:SetAllPoints()
50 | end
51 |
52 |
53 | if self.Arrow then
54 | self.Arrow:SetShown(false)
55 | end
56 |
57 |
58 | TrinketMenu.MenuTrinket_OnClick(self, button, down)
59 |
60 |
61 | TrinketMenu.MenuTrinketTooltip(self)
62 |
63 |
64 | TrinketMenu.ClearTooltip()
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
168 | self:SetPoint("TOPLEFT", 4, -4)
169 | else
170 | self:SetPoint("TOPLEFT", 8, -8)
171 | end
172 | self:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonUp")
173 | if self.cooldown then
174 | self.cooldown:SetSwipeColor(0, 0, 0, 0.8)
175 | end
176 | if self.icon then
177 | self.icon:SetAllPoints()
178 | end
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then
196 | self:SetPoint("BOTTOMRIGHT", -3, 3)
197 | else
198 | self:SetPoint("BOTTOMRIGHT", -8, 8)
199 | end
200 | self:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonUp")
201 | if self.cooldown then
202 | self.cooldown:SetSwipeColor(0, 0, 0, 0.8)
203 | end
204 | if self.icon then
205 | self.icon:SetAllPoints()
206 | end
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 | TrinketMenu.OnLoad(self)
216 |
217 |
218 | TrinketMenu.OnEvent(self, event, ...)
219 |
220 |
221 | TrinketMenu.MainFrame_OnMouseDown(self)
222 |
223 |
224 | TrinketMenu.MainFrame_OnMouseUp(self)
225 |
226 |
227 | TrinketMenu.OnShow()
228 |
229 |
230 | TrinketMenu.OnHide()
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 | self:OnBackdropLoaded()
351 | self:SetBackdropColor(0.0, 0.0, 0.0)
352 | self:SetBackdropBorderColor(0.0, 0.0, 0.0)
353 |
354 |
355 | TrinketMenu.MenuFrame_OnMouseDown(button)
356 |
357 |
358 | TrinketMenu.MenuFrame_OnMouseUp(button)
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 | TrinketMenu.TimersFrame_OnUpdate(elapsed)
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 | self:SetOwner(WorldFrame, "ANCHOR_NONE")
375 |
376 |
377 |
378 |
379 |
--------------------------------------------------------------------------------
/TrinketMenuOpt.lua:
--------------------------------------------------------------------------------
1 | --[[ TrinketMenuOpt.lua : Options and sort window for TrinketMenu ]]
2 |
3 | local _G, math, string, table = _G, math, string, table
4 |
5 | local IsRetail = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
6 |
7 | TrinketMenu.CheckOptInfo = {
8 | {"ShowIcon", "ON", "Minimap Button", "Show or hide minimap button."},
9 | {"SquareMinimap", "OFF", "Square Minimap", "Move minimap button as if around a square minimap.", "ShowIcon"},
10 | {"CooldownCount", "OFF", "Cooldown Numbers", "Display time remaining on cooldowns ontop of the button."},
11 | {"CooldownCountBlizzard", "OFF", "Blizzard Cooldowns", "Display time remaining on cooldowns ontop of the button."},
12 | {"CooldownCountOmniCC", "OFF", "OmniCC Cooldowns", "Display time remaining on cooldowns ontop of the button."},
13 | {"TooltipFollow", "OFF", "At Mouse", "Display all tooltips near the mouse.", "ShowTooltips"},
14 | {"KeepOpen", "OFF", "Keep Menu Open", "Keep menu open at all times."},
15 | {"KeepDocked", "ON", "Keep Menu Docked", "Keep menu docked at all times."},
16 | {"Notify", "OFF", "Notify When Ready", "Sends an overhead notification when a trinket's cooldown is complete."},
17 | {"DisableToggle", "OFF", "Disable Toggle", "Disables the minimap button's ability to toggle the trinket frame.", "ShowIcon"},
18 | {"NotifyChatAlso", "OFF", "Notify Chat Also", "Sends notifications through chat also."},
19 | {"Locked", "OFF", "Lock Windows", "Prevents the windows from being moved, resized or rotated."},
20 | {"ShowTooltips", "ON", "Show Tooltips", "Shows tooltips."},
21 | {"NotifyThirty", "ON", "Notify At 30 sec", "Sends an overhead notification when a trinket has 30 seconds left on cooldown."},
22 | {"MenuOnShift", "OFF", "Menu On Shift", "Check this to prevent the menu appearing unless Shift is held."},
23 | {"TinyTooltips", "OFF", "Tiny Tooltips", "Shrink trinket tooltips to only their name, charges and cooldown.", "ShowTooltips"},
24 | {"SetColumns", "OFF", "Wrap at: ", "Define how many trinkets before the menu will wrap to the next row.\n\nUncheck to let TrinketMenu choose how to wrap the menu."},
25 | {"LargeCooldown", "ON", "Large Numbers", "Display the cooldown time in a larger font.", "CooldownCount"},
26 | {"ShowHotKeys", "ON", "Show Key Bindings", "Display the key bindings over the equipped trinkets."},
27 | {"StopOnSwap", "OFF", "Stop Queue On Swap", "Swapping a passive trinket stops an auto queue. Check this to also stop the auto queue when a clickable trinket is manually swapped in via TrinketMenu. This will have the most use to those with frequent trinkets marked Priority."},
28 | {"HideOnLoad", "OFF", "Close On Profile Load", "Check this to dismiss this window when you load a profile."},
29 | {"RedRange", "OFF", "Red Out of Range", "Check this to red out worn trinkets that are out of range to a valid target. ie, Gnomish Death Ray and Gnomish Net-O-Matic."},
30 | {"HidePetBattle", "ON", "Hide in Pet Battles", "Check this auto hide the frame while in a pet battle."},
31 | {"MenuOnRight", "OFF", "Menu On Right-Click", "Check this to prevent the menu from appearing until either worn trinket is right-clicked.\n\nNOTE: This setting CANNOT be changed while in combat."}
32 | }
33 |
34 | TrinketMenu.TooltipInfo = {
35 | {"TrinketMenu_LockButton", "Lock Windows", "Prevents the windows from being moved, resized or rotated."},
36 | {"TrinketMenu_Trinket0Check", "Top Trinket Auto Queue", "Check this to enable auto queue for this trinket slot. You can also Alt+Click the trinket slot to toggle Auto Queue."},
37 | {"TrinketMenu_Trinket1Check", "Bottom Trinket Auto Queue", "Check this to enable auto queue for this trinket slot. You can also Alt+Click the trinket slot to toggle Auto Queue."},
38 | {"TrinketMenu_SortPriority", "High Priority", "When checked, this trinket will be swapped in as soon as possible, whether the equipped trinket is on cooldown or not.\n\nWhen unchecked, this trinket will not equip over one already worn that's not on cooldown."},
39 | {"TrinketMenu_SortDelay", "Swap Delay", "This is the time (in seconds) before a trinket will be swapped out. ie, for Earthstrike you want 20 seconds to get the full 20 second effect of the buff."},
40 | {"TrinketMenu_SortKeepEquipped", "Pause Queue", "Check this to suspend the auto queue while this trinket is equipped. ie, for Carrot on a Stick if you have a mod to auto-equip it to a slot with Auto Queue active."},
41 | {"TrinketMenu_Profiles", "Profiles", "Here you can load or save auto queue profiles."},
42 | {"TrinketMenu_Delete", "Delete", "Remove this trinket from the list. Trinkets further down the list don't affect performance at all. This option is merely to keep the list managable. Note: Trinkets in your bags will return to end of the list."},
43 | {"TrinketMenu_ProfilesDelete", "Delete Profile", "Remove this profile."},
44 | {"TrinketMenu_ProfilesLoad", "Load Profile", "Load a queue order for the selected trinket slot. You can double-click a profile to load it also."},
45 | {"TrinketMenu_ProfilesSave", "Save Profile", "Save the queue order from the selected trinket slot. Either trinket slot can use saved profiles."},
46 | {"TrinketMenu_ProfileName", "Profile Name", "Enter a name to call the profile. When saved, you can load this profile to either trinket slot."}
47 | }
48 |
49 | function TrinketMenu.InitOptions()
50 | TrinketMenu.CreateTimer("DragMinimapButton", TrinketMenu.DragMinimapButton, 0, 1)
51 | TrinketMenu.MoveMinimapButton()
52 | local item
53 | for i = 1, #TrinketMenu.CheckOptInfo do
54 | item = _G["TrinketMenu_Opt"..TrinketMenu.CheckOptInfo[i][1].."Text"]
55 | if item then
56 | item:SetText(TrinketMenu.CheckOptInfo[i][3])
57 | item:SetTextColor(.95, .95, .95)
58 | end
59 | end
60 | TrinketMenu.Tab_OnClick(1)
61 | table.insert(UISpecialFrames, "TrinketMenu_OptFrame")
62 | TrinketMenu_Title:SetText("TrinketMenu "..TrinketMenu_Version)
63 | TrinketMenu_OptFrame:SetBackdropBorderColor(.3, .3, .3, 1)
64 | TrinketMenu_SubOptFrame:SetBackdropBorderColor(.3, .3, .3, 1)
65 | if TrinketMenu.QueueInit then
66 | TrinketMenu.QueueInit()
67 | TrinketMenu_Tab1:Show()
68 | TrinketMenu_OptFrame:SetHeight(356)
69 | TrinketMenu_SubOptFrame:SetPoint("TOPLEFT", TrinketMenu_OptFrame, "TOPLEFT", 8, - 50)
70 | else
71 | TrinketMenu_OptStopOnSwap:Hide() -- remove StopOnSwap option if queue not loaded
72 | TrinketMenu_Tab1:Hide() -- hide options tab if it's only tab
73 | TrinketMenu_OptFrame:SetHeight(300)
74 | TrinketMenu_SubOptFrame:SetPoint("TOPLEFT", TrinketMenu_OptFrame, "TOPLEFT", 8, - 24)
75 | end
76 | TrinketMenu_OptColumnsSlider:SetValue(TrinketMenuOptions.Columns)
77 | TrinketMenu_OptColumnsSliderText:SetText(TrinketMenuOptions.Columns.." trinkets")
78 | TrinketMenu_OptMainScaleSlider:SetValue(TrinketMenuPerOptions.MainScale)
79 | TrinketMenu_OptMenuScaleSlider:SetValue(TrinketMenuPerOptions.MenuScale)
80 | TrinketMenu.ReflectLock()
81 | TrinketMenu.ReflectCooldownFont()
82 | TrinketMenu.KeyBindingsChanged()
83 | end
84 |
85 | function TrinketMenu.ToggleFrame(frame)
86 | if frame:IsVisible() then
87 | frame:Hide()
88 | else
89 | frame:Show()
90 | end
91 | end
92 |
93 | function TrinketMenu.OptFrame_OnShow()
94 | TrinketMenu.ValidateChecks()
95 | if TrinketMenu.CurrentlySorting then
96 | TrinketMenu.PopulateSort(TrinketMenu.CurrentlySorting)
97 | end
98 | end
99 |
100 | --[[ Minimap button ]]
101 |
102 | function TrinketMenu.MoveMinimapButton()
103 | local xpos, ypos
104 | if TrinketMenuOptions.SquareMinimap == "ON" then
105 | xpos = 110 * cos(TrinketMenuOptions.IconPos or 0)
106 | ypos = 110 * sin(TrinketMenuOptions.IconPos or 0)
107 | xpos = math.max(- 82, math.min(xpos, 84))
108 | ypos = math.max(- 86, math.min(ypos, 82))
109 | else
110 | local radius = IsRetail and 102 or 80
111 | xpos = radius * cos(TrinketMenuOptions.IconPos or 0)
112 | ypos = radius * sin(TrinketMenuOptions.IconPos or 0)
113 | end
114 | if IsRetail then
115 | TrinketMenu_IconFrame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", 82 - xpos, ypos - 84)
116 | else
117 | TrinketMenu_IconFrame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", 52 - xpos, ypos - 52)
118 | end
119 | if TrinketMenuOptions.ShowIcon == "ON" then
120 | TrinketMenu_IconFrame:Show()
121 | else
122 | TrinketMenu_IconFrame:Hide()
123 | end
124 | end
125 |
126 | function TrinketMenu.DragMinimapButton()
127 | local xpos, ypos = GetCursorPosition()
128 | local xmin, ymin = Minimap:GetLeft() or 400, Minimap:GetBottom() or 400
129 | xpos = xmin - xpos / Minimap:GetEffectiveScale() + 70
130 | ypos = ypos / Minimap:GetEffectiveScale() - ymin - 70
131 | TrinketMenuOptions.IconPos = math.deg(math.atan2(ypos, xpos))
132 | TrinketMenu.MoveMinimapButton()
133 | end
134 |
135 | function TrinketMenu.MinimapButton_OnClick(button)
136 | PlaySound(825)
137 | if IsShiftKeyDown() then
138 | TrinketMenuOptions.Locked = TrinketMenuOptions.Locked == "ON" and "OFF" or "ON"
139 | TrinketMenu.ReflectLock()
140 | elseif IsAltKeyDown() and TrinketMenu.QueueInit then
141 | if button == "LeftButton" then
142 | TrinketMenuQueue.Enabled[0] = not TrinketMenuQueue.Enabled[0] and 1 or nil
143 | elseif button == "RightButton" then
144 | TrinketMenuQueue.Enabled[1] = not TrinketMenuQueue.Enabled[1] and 1 or nil
145 | end
146 | TrinketMenu.ReflectQueueEnabled()
147 | TrinketMenu.UpdateCombatQueue()
148 | else
149 | if button == "LeftButton" and TrinketMenuOptions.DisableToggle == "OFF" then
150 | TrinketMenu.ToggleFrame(TrinketMenu_MainFrame)
151 | else
152 | TrinketMenu.ToggleFrame(TrinketMenu_OptFrame)
153 | end
154 | end
155 | end
156 |
157 | --[[ CheckButton ]]
158 |
159 | function TrinketMenu.ValidateChecks()
160 | local check, button
161 | for i = 1, #TrinketMenu.CheckOptInfo do
162 | check = TrinketMenu.CheckOptInfo[i]
163 | button = _G["TrinketMenu_Opt"..check[1]]
164 | if button then
165 | button:SetChecked(TrinketMenuOptions[check[1]] == "ON")
166 | if check[5] then
167 | if TrinketMenuOptions[check[5]] == "ON" then
168 | button:Enable()
169 | _G["TrinketMenu_Opt"..check[1].."Text"]:SetTextColor(.95, .95, .95)
170 | else
171 | button:Disable()
172 | _G["TrinketMenu_Opt"..check[1].."Text"]:SetTextColor(.5, .5, .5)
173 | end
174 | end
175 | end
176 | end
177 | TrinketMenu_OptColumnsSlider:SetAlpha((TrinketMenuOptions.SetColumns == "ON") and 1 or .5)
178 | TrinketMenu_OptColumnsSlider:EnableMouse((TrinketMenuOptions.SetColumns == "ON") and 1 or 0)
179 | TrinketMenu_OptColumnsSlider:SetValue(TrinketMenuOptions.Columns)
180 | end
181 |
182 | function TrinketMenu.OptColumnsSlider_OnValueChanged(self, value)
183 | if not self._onsetting then
184 | self._onsetting = true
185 | self:SetValue(self:GetValue())
186 | value = self:GetValue()
187 | self._onsetting = false
188 | else
189 | return
190 | end
191 | if TrinketMenuOptions then
192 | TrinketMenuOptions.Columns = self:GetValue()
193 | TrinketMenu_OptColumnsSliderText:SetText(TrinketMenuOptions.Columns.." trinkets")
194 | if TrinketMenu_MenuFrame:IsVisible() then
195 | TrinketMenu.BuildMenu()
196 | end
197 | end
198 | end
199 |
200 | function TrinketMenu.OptMainScaleSlider_OnValueChanged(self, value)
201 | if not self._onsetting then
202 | self._onsetting = true
203 | self:SetValue(self:GetValue())
204 | value = self:GetValue()
205 | self._onsetting = false
206 | else
207 | return
208 | end
209 | if TrinketMenuPerOptions then
210 | TrinketMenuPerOptions.MainScale = self:GetValue()
211 | TrinketMenu_OptMainScaleSliderText:SetText(format("Main Scale: %.2f", TrinketMenuPerOptions.MainScale))
212 | TrinketMenu_MainFrame:SetScale(TrinketMenuPerOptions.MainScale)
213 | end
214 | end
215 |
216 | function TrinketMenu.OptMenuScaleSlider_OnValueChanged(self, value)
217 | if not self._onsetting then
218 | self._onsetting = true
219 | self:SetValue(self:GetValue())
220 | value = self:GetValue()
221 | self._onsetting = false
222 | else
223 | return
224 | end
225 | if TrinketMenuPerOptions then
226 | TrinketMenuPerOptions.MenuScale = self:GetValue()
227 | TrinketMenu_OptMenuScaleSliderText:SetText(format("Menu Scale: %.2f", TrinketMenuPerOptions.MenuScale))
228 | TrinketMenu_MenuFrame:SetScale(TrinketMenuPerOptions.MenuScale)
229 | end
230 | end
231 |
232 | function TrinketMenu.SliderOnMouseWheel(self, delta)
233 | if delta > 0 then
234 | self:SetValue(self:GetValue() + self:GetValueStep())
235 | else
236 | self:SetValue(self:GetValue() - self:GetValueStep())
237 | end
238 | end
239 |
240 | function TrinketMenu.CheckButton_OnClick(self)
241 | local _, _, var = string.find(self:GetName(), "TrinketMenu_Opt(.+)")
242 | if TrinketMenuOptions[var] then
243 | TrinketMenuOptions[var] = self:GetChecked() and "ON" or "OFF"
244 | PlaySound(self:GetChecked() and 856 or 857)
245 | TrinketMenu.ValidateChecks()
246 | end
247 | if self == TrinketMenu_OptCooldownCount then
248 | TrinketMenu.WriteWornCooldowns()
249 | TrinketMenu.WriteMenuCooldowns()
250 | elseif self == TrinketMenu_OptCooldownCountBlizzard then
251 | if TrinketMenu_Trinket0 and TrinketMenu_Trinket0.cooldown then
252 | if TrinketMenuOptions.CooldownCountBlizzard == "ON" then
253 | TrinketMenu_Trinket0.cooldown:SetHideCountdownNumbers(false)
254 | else
255 | TrinketMenu_Trinket0.cooldown:SetHideCountdownNumbers(true)
256 | end
257 | end
258 | if TrinketMenu_Trinket1 and TrinketMenu_Trinket1.cooldown then
259 | if TrinketMenuOptions.CooldownCountBlizzard == "ON" then
260 | TrinketMenu_Trinket1.cooldown:SetHideCountdownNumbers(false)
261 | else
262 | TrinketMenu_Trinket1.cooldown:SetHideCountdownNumbers(true)
263 | end
264 | end
265 | for i = 1, TrinketMenu.MaxTrinkets do
266 | local menuButton = _G["TrinketMenu_Menu"..i]
267 | if menuButton and menuButton.cooldown then
268 | if TrinketMenuOptions.CooldownCountBlizzard == "ON" then
269 | menuButton.cooldown:SetHideCountdownNumbers(false)
270 | else
271 | menuButton.cooldown:SetHideCountdownNumbers(true)
272 | end
273 | end
274 | end
275 | elseif self == TrinketMenu_OptCooldownCountOmniCC then
276 | if TrinketMenu_Trinket0 and TrinketMenu_Trinket0.cooldown then
277 | if TrinketMenuOptions.CooldownCountOmniCC == "ON" then
278 | TrinketMenu_Trinket0.cooldown.noCooldownCount = false
279 | else
280 | TrinketMenu_Trinket0.cooldown.noCooldownCount = true
281 | end
282 | end
283 | if TrinketMenu_Trinket1 and TrinketMenu_Trinket1.cooldown then
284 | if TrinketMenuOptions.CooldownCountOmniCC == "ON" then
285 | TrinketMenu_Trinket1.cooldown.noCooldownCount = false
286 | else
287 | TrinketMenu_Trinket1.cooldown.noCooldownCount = true
288 | end
289 | end
290 | for i = 1, TrinketMenu.MaxTrinkets do
291 | local menuButton = _G["TrinketMenu_Menu"..i]
292 | if menuButton and menuButton.cooldown then
293 | if TrinketMenuOptions.CooldownCountOmniCC == "ON" then
294 | menuButton.cooldown.noCooldownCount = false
295 | else
296 | menuButton.cooldown.noCooldownCount = true
297 | end
298 | end
299 | end
300 | elseif self == TrinketMenu_OptLocked then
301 | TrinketMenu.DockWindows()
302 | TrinketMenu.ReflectLock()
303 | elseif self == TrinketMenu_OptKeepOpen or self == TrinketMenu_OptSetColumns then
304 | if TrinketMenuOptions.KeepOpen == "ON" then
305 | TrinketMenu.BuildMenu()
306 | end
307 | elseif self == TrinketMenu_OptKeepDocked then
308 | TrinketMenu.DockWindows()
309 | elseif self == TrinketMenu_OptLargeCooldown then
310 | TrinketMenu.ReflectCooldownFont()
311 | elseif self == TrinketMenu_OptSquareMinimap then
312 | TrinketMenu.MoveMinimapButton()
313 | elseif self == TrinketMenu_OptShowHotKeys then
314 | TrinketMenu.KeyBindingsChanged()
315 | elseif self == TrinketMenu_OptShowIcon then
316 | TrinketMenu.MoveMinimapButton()
317 | --[[elseif self == TrinketMenu_OptRedRange then
318 | TrinketMenu.ReflectRedRange()]]
319 | elseif self == TrinketMenu_OptMenuOnRight then
320 | TrinketMenu.ReflectMenuOnRight()
321 | elseif self == TrinketMenu_OptNotify or self == TrinketMenu_OptNotifyThirty then
322 | if TrinketMenu_OptNotify:GetChecked() or TrinketMenu_OptNotifyThirty:GetChecked() then
323 | TrinketMenu.StartTimer("CooldownUpdate")
324 | elseif not TrinketMenu_OptNotify:GetChecked() and not TrinketMenu_OptNotifyThirty:GetChecked() then
325 | TrinketMenu.StopTimer("CooldownUpdate")
326 | end
327 | end
328 | end
329 |
330 | function TrinketMenu.ReflectLock()
331 | local c = TrinketMenuOptions.Locked == "ON" and 0 or .5
332 | TrinketMenu_OptFrame:SetBackdropBorderColor(c, c, c, 1)
333 | TrinketMenu_MainFrame:SetBackdropColor(c, c, c, c)
334 | TrinketMenu_MainFrame:SetBackdropBorderColor(c, c, c, c * 2)
335 | TrinketMenu_MenuFrame:SetBackdropColor(c, c, c, c)
336 | TrinketMenu_MenuFrame:SetBackdropBorderColor(c, c, c, c * 2)
337 | TrinketMenu_MenuFrame:EnableMouse(c * 2)
338 | if TrinketMenuOptions.Locked == "ON" then
339 | TrinketMenu_OptLocked:SetChecked(true)
340 | else
341 | TrinketMenu_OptLocked:SetChecked(false)
342 | end
343 | local normalTexture = TrinketMenu_LockButton:GetNormalTexture()
344 | local pushedTexture = TrinketMenu_LockButton:GetPushedTexture()
345 | if c == 0 then
346 | normalTexture:SetTexCoord(.875, 1, .125, .25)
347 | pushedTexture:SetTexCoord(.75, .875, .125, .25)
348 | else
349 | normalTexture:SetTexCoord(.75, .875, .125, .25)
350 | pushedTexture:SetTexCoord(.875, 1, .125, .25)
351 | end
352 | end
353 |
354 | function TrinketMenu.ReflectCooldownFont()
355 | TrinketMenu.SetCooldownFont("TrinketMenu_Trinket0")
356 | TrinketMenu.SetCooldownFont("TrinketMenu_Trinket1")
357 | for i = 1, 30 do
358 | TrinketMenu.SetCooldownFont("TrinketMenu_Menu"..i)
359 | end
360 | end
361 |
362 | function TrinketMenu.SetCooldownFont(button)
363 | local item = _G[button.."Time"]
364 | if TrinketMenuOptions.LargeCooldown == "ON" then
365 | item:SetFont("Fonts\\FRIZQT__.TTF", 16, "OUTLINE")
366 | item:SetTextColor(1, .82, 0, 1)
367 | item:ClearAllPoints()
368 | item:SetPoint("CENTER", button, "CENTER")
369 | else
370 | item:SetFont("Fonts\\ARIALN.TTF", 14, "OUTLINE")
371 | item:SetTextColor(1, 1, 1, 1)
372 | item:ClearAllPoints()
373 | item:SetPoint("BOTTOM", button, "BOTTOM")
374 | end
375 | end
376 |
377 | --[[ Titlebar buttons ]]
378 |
379 | function TrinketMenu.SmallButton_OnClick(self)
380 | PlaySound(856)
381 | if self == TrinketMenu_CloseButton then
382 | TrinketMenu_OptFrame:Hide()
383 | elseif self == TrinketMenu_LockButton then
384 | TrinketMenuOptions.Locked = (TrinketMenuOptions.Locked == "ON") and "OFF" or "ON"
385 | TrinketMenu.DockWindows()
386 | TrinketMenu.ReflectLock()
387 | end
388 | end
389 |
390 | --[[ Tabs ]]
391 |
392 | function TrinketMenu.Tab_OnClick(id)
393 | PlaySound(825)
394 | local tab
395 | if TrinketMenu_ProfilesFrame then
396 | TrinketMenu_ProfilesFrame:Hide()
397 | end
398 | for i = 1, 3 do
399 | tab = _G["TrinketMenu_Tab"..i]
400 | if tab then
401 | tab:UnlockHighlight()
402 | end
403 | end
404 | _G["TrinketMenu_Tab"..id]:LockHighlight()
405 | if id == 1 then
406 | TrinketMenu_SubOptFrame:Show()
407 | if TrinketMenu_SubQueueFrame then
408 | TrinketMenu_SubQueueFrame:Hide()
409 | end
410 | else
411 | TrinketMenu_SubOptFrame:Hide()
412 | TrinketMenu_SubQueueFrame:Show()
413 | TrinketMenu.OpenSort(3 - id)
414 | end
415 | end
416 |
--------------------------------------------------------------------------------
/Readme.txt:
--------------------------------------------------------------------------------
1 | TrinketMenu 5.0.2
2 |
3 | This is a mod to make swapping trinkets easier. It will display your two equipped trinkets in a bar. Mouseover on either trinket will display a menu of up to 30 trinkets in your bags to swap.
4 |
5 | __ New in 5.0.3 __
6 | - Changed file coding to UTF-8.
7 |
8 | __ New in 5.0.2 __
9 | - Fixed an itemID bug.
10 |
11 | __ New in 5.0.1 __
12 | - Updated for 5.3.
13 |
14 | __ New in 5.0.0 __
15 | - Updated for 5.2.
16 | - Minor fixes.
17 | - Code Cleanup.
18 | - Moved textures to "Textures" folder.
19 | - Added notification support for MSBT, Parrot, xCT, xCT+.
20 |
21 | __ Swapping/Using trinkets __
22 |
23 | Left click a trinket in the menu to equip it to the top trinket slot.
24 | Right click a trinket in the menu to equip it to the bottom trinket slot.
25 |
26 | Left or Right click either equipped trinket to use them. Or make a key binding for either trinket.
27 |
28 | __ Auto Queue __
29 |
30 | 3.0 introduces auto trinket queues to TrinketMenu. In options you can sort a trinket slot to the order you want trinkets equipped, turn on Auto Queue for that slot (Alt+Click the trinket on the bar or check the tab in options), and the mod will automatically swap trinkets as they're used and come off cooldown.
31 |
32 | It was (hopefully) made to be intuitive enough to use without instructions, but if wondering about specifics:
33 |
34 | The auto queue rules are:
35 | - A trinket at 30 seconds or less cooldown is considered off cooldown.
36 | - If the currently equipped trinket is on cooldown, swap to the first available trinket not on cooldown.
37 | - If the currently equipped trinket cannot go on cooldown (passive trinkets), equip a higher ranking trinket when it comes off cooldown.
38 | - If the currently equipped trinket is ready for use, then do nothing unless a higher-ranked trinket marked 'Priority' is waiting to swap in.
39 | - If a trinket has a 'Delay' defined, then hold that trinket for its delay before swapping it out. (ie, Earthstrike for 20 seconds)
40 | - If a trinket grants a buff and that buff is currently on you, hold that trinket until the buff fades.
41 |
42 | Auto queue icon colors:
43 | - A gold gear on a trinket means that auto queue is active for that slot.
44 | - A grey gear on a trinket means the equipped trinket has a delay defined and is waiting to swap out.
45 | - A red gear on a trinket means the equipped trinket is flagged 'Pause Queue' and auto queue is suspended.
46 |
47 | Other auto queue notes:
48 | - If you use some mod to automatically swap in passive trinkets (Carrot on a Stick or Argent Dawn Commission), flag those trinkets 'Pause Queue' to suspend the queue while they're equipped.
49 | - Swapping a passive trinket manually in TrinketMenu will stop the auto queue for that slot. Alt+click the slot to turn auto queue back on.
50 | - A purely passive trinket will mark the natural end of a queue. If you would like the queue to stop sooner (ie, Burst of Knowledge as bottom-most trinket even on cooldown), move the "-- stop queue here--" mark to where you want the queue to stop.
51 | - The auto queues work independently of the "trinket ready!" notifications.
52 | - Trinkets attempting to swap during combat or while dead will queue for when you drop out of combat or return to life.
53 | - If you don't want to use auto queue and would like to remove it completely, you can delete TrinketMenuQueue.xml and TrinketMenuQueue.lua while out of game. The remaining mod will be about the size of TrinketMenu 2.7 and run better than 2.7.
54 |
55 | __ Auto Queue Shared Timers __
56 |
57 | Keep in mind as you set up your queues that many trinkets trigger shared cooldown timers. As an example:
58 |
59 | Trinket 0 contains a Cannonball Runner not on cooldown
60 | Trinket 1 contains a Diamond Flask not on cooldown
61 |
62 | When you click Diamond Flask, it will put the Cannonball Runner into a 60-second cooldown. TrinketMenu will then look for something more available for Trinket 0, and then 30 seconds later as the Cannonball Runner comes off cooldown it will swap it back in.
63 |
64 | This is expected behavior. If it seems like this happens a lot, you may want to Auto Queue only one trinket slot, until you get trinkets that can be used without triggering the other's cooldown.
65 |
66 | __ Customizing Display __
67 |
68 | The main and menu windows are independently scalable and rotatable. While the windows are unlocked:
69 |
70 | - Move either window by dragging its edge.
71 | - Rotate either window by right-clicking its edge.
72 | - Scale/resize either window with a slider in options.
73 |
74 | If you're having problems grabbing the edge of the menu window to move/rotate it, hold Shift down while it's open and the menu won't go away when the mouse leaves the menu's edge.
75 |
76 | If you right-click the gear icon around the minimap (or /trinket options) a small options window will appear under the minimap. Here you can customize the display further by showing cooldowns as numbers and keeping the menu always open.
77 |
78 | Once you're settled on a setup you like, you can lock the windows in options.
79 |
80 | To set an exact scale (optional):
81 | /trinket scale main n : Scale the main window to n
82 | /trinket scale menu n : Scale the menu window to n
83 | ie: /trinket scale menu 0.85
84 |
85 | __ Docking __
86 |
87 | While 'Keep Menu Docked' is checked (default), the menu will always be docked to one corner of the main window. To change the corner where it's docked, drag the menu window so that a corner of the main and menu windows meet. White brackets will appear at the corners that will dock as you drag.
88 |
89 | If you uncheck 'Keep Menu Docked', remember the menu goes away when the mouse leaves your trinkets. Feel free to experiment if you'd like. Remember that /trinket reset will restore positions/docking, or you can hold Shift down to keep the menu open. Or you can turn on 'Keep Menu Open' in options.
90 |
91 | __ Combat/Death Queued Trinkets __
92 |
93 | We can't swap trinkets during combat or when we're dead. If you attempt to swap trinkets during combat or while dead it will put the trinket on hold and automatically swap them once you leave combat:
94 |
95 | - The queued trinket will appear as a small icon inset into the slot it's heading to.
96 | - If you want to unqueue the trinket, reselect it again for that slot (left or right click).
97 | - If you want to queue the trinket to the other slot, reselect it again for the other slot (left or right click).
98 | - The "combat queue" is only one-trinket deep right now. Meaning, once a queued trinket is equipped that queue is emptied.
99 | - Selecting a series of trinkets for a slot will only change the queued trinket, it won't set up an order to them. Go to options to set up an auto queue sort order.
100 |
101 | __ Misc __
102 |
103 | - If you hold shift while you move trinkets up/down the sort list, the list will stay in place.
104 | - You can drag the minimap icon around the minimap directly.
105 | - You can Shift+click the trinkets to link them to chats just as you would from your bags or inventory.
106 | - If you log in to a character with no trinkets in bags or on their person, the trinket window will not be displayed.
107 | - You can hold Shift while swapping trinkets or manipulating the windows to prevent the menu from disappearing.
108 | - You can set up key bindings to use whatever trinket is in the top or bottom slot.
109 | - If you have Scrolling Combat Text installed, and 'Notify When Ready' checked, it will send a message via SCT when a trinket is ready.
110 |
111 | __ Optional Slash Commands __
112 |
113 | /trinket or /trinketmenu : toggle the window
114 | /trinket reset : reset window
115 | /trinket opt : summons options window
116 | /trinket lock|unlock : toggles window lock
117 | /trinket scale main|menu n : scales windows to exact scale
118 | /trinket help : lists the above commands
119 |
120 | __ TrinketMenu.SetQueue (Advanced Users) __
121 |
122 | This function is intended to be used by those that want to script different sort orders or script the auto queue behavior to work with other gear-swapping mods.
123 |
124 | TrinketMenu.SetQueue(0 or 1,"ON" or "OFF" or "PAUSE" or "RESUME" or list)
125 |
126 | "ON" : Turn queue on irregardless of previous state
127 | "OFF" : Turn queue off irregardless of previous state
128 | "PAUSE" : Suspend queue if it was on
129 | "RESUME" : Return queue to normal operation if it was paused
130 |
131 | some examples:
132 | /script TrinketMenu.SetQueue(1,"PAUSE") -- if queue is going, pause it
133 | /script TrinketMenu.SetQueue(1,"RESUME") -- if queue is paused, resume it
134 | /script TrinketMenu.SetQueue(1,"SORT","Earthstrike","Insignia of the Alliance","Diamond Flask") -- set sort
135 | /script TrinketMenu.SetQueue(0,"SORT","Lifestone","Darkmoon Card: Heroism") -- set sort
136 | /script TrinketMenu.SetQueue(1,"SORT","PVP Profile") -- set sort to "PVP Profile"
137 | (a "stop the queue" is assumed at the end of the list)
138 |
139 | So in ItemRack if you want a different queue when in a raid or not:
140 |
141 | name: In Raid
142 | trigger: RAID_ROSTER_UPDATE
143 | delay: 0.5
144 | script:
145 | if GetNumRaidMembers()>0 and not IR_INRAID then
146 | IR_INRAID = 1
147 | TrinketMenu.SetQueue(1,"SORT","Zandalarian Hero Badge","Force of Will")
148 | elseif IR_INRAID and GetNumRaidMembers()==0 then
149 | IR_INRAID = nil
150 | TrinketMenu.SetQueue(1,"SORT","Earthstrike","Diamond Flask","Defender of the Timbermaw")
151 | end
152 | --[[ Changes trinket sort orders depending on whether in a raid or not ]]
153 |
154 | or for some situation when you don't want trinkets swapping at all:
155 |
156 | name: In IF
157 | trigger: ZONE_CHANGED_NEW_AREA
158 | delay: 2
159 | script:
160 | if GetRealZoneText()=="Ironforge" and not IR_INIF then
161 | IR_INIF = 1
162 | TrinketMenu.SetQueue(0,"PAUSE")
163 | elseif IR_INIF and GetRealZoneText()~="Ironforge" then
164 | IR_INIF = nil
165 | TrinketMenu.SetQueue(0,"RESUME")
166 | end
167 | --[[ Pauses trinket slot 0 auto queue while in IF ]]
168 |
169 | __ FAQ for 3.x __
170 |
171 | Q: Why did you remove the "missing trinket" bit?
172 | A: Because it wasn't always accurate and to make it more accurate would require more bag scanning than is necessary for the mod to function. Specifically: when a series of BAG_UPDATEs occur, it waits until they're done and then quickly scans only the bags that updated. When it finds a trinket it notes its position. If a trinket disappeared it doesn't care because it's not going to show in the menu. I am hyper-sensitive to BAG_UPDATE performance and don't want to spend more CPU cycles than is necessary in normal BAG_UPDATE actions. (You may note that if you remove the TrinketMenuQueue.* files then BAG_UPDATE isn't registered at all)
173 |
174 | Q: Can you let the auto queue remain enabled when I swap in passive trinkets?
175 | A: At some point, you will have to tell the mod that you no longer want to use the passive trinket. Alt+clicking the slot seems simplest.
176 |
177 | Q: Can you make auto queue stop/start with my trinket-swapping mod/macro?
178 | A: There are numerous ways of equipping trinkets: UseContainerItem, UseAction, PickupContainerItem/PickupInventoryItem, EquipCursorItem, etc. I don't want to hook all those functions. I want this mod to be small and unobtrusive. Check 'Pause Queue' on trinkets your mod/macro equips, or use TrinketMenu.SetQueue in the macro or event that does the swap.
179 |
180 | Q: You said you'd never add full queues to this. Why the change?
181 | A: Mostly it was to work out some design problems for ItemRack that will have queues for equippable and consumable items. I needed to back up to a simpler level and adding queues to TrinketMenu was a logical place to work them out.
182 |
183 | Q: One reason I used TrinketMenu was because it wasn't bloated with bells and whistles. Will you release a version without the Auto Queues?
184 | A: If you delete TrinketMenuQueue.xml and TrinketMenuQueue.lua then it will remove the Auto Queue and all the frames and code associated with it. What's left will be about the same size as 2.7 TrinketMenu. If there's demand I can post a zip with those files removed.
185 |
186 | Q: Does this mean you're not working on ItemRack?
187 | A: See above. Work is progressing. Some design issues needed sorted out and this mod's update was a helpful part of that.
188 |
189 | Q: Why a rewrite?
190 | A: I'm hoping to keep this mod tidy with as little feature creep as possible. Rewrites are a good way to trim out unnecessary junk.
191 |
192 | Q: I set the menu columns to X, but it's doing X rows and the wrong number of columns.
193 | A: Rotate the menu by right-clicking its unlocked edge. Then rows will become columns and vice versa.
194 |
195 | Q: I made Trinket A higher priority than Trinket B, but when Trinket A comes off cooldown it's not equipping.
196 | A: The default behavior is to not swap trinkets if the currently-equipped trinket is clickable and not on cooldown. This is to prevent the trinket slots excessively swapping and spending a lot of time in 30-second cooldowns. If you have a trinket you want equipped ASAP when it's ready, select it and check 'Priority' at the bottom.
197 |
198 | __ FAQ __
199 |
200 | Q: How do I equip a trinket to the "off" trinket slot?
201 | A: Left click goes to main trinket slot, right click goes to off slot.
202 |
203 | Q: Can you add items other than trinkets to the menu?
204 | A: See ItemRack, which is the big brother to this mod. It handles all inventory slots as well as item sets and stuff.
205 |
206 | Q: What does ItemRack mean for TrinketMenu's future?
207 | A: TrinketMenu will stay focused on trinkets. For the foreseeable future it will be maintained alongside ItemRack since many are looking for just a trinket manager without the extras. While some new stuff may be added from time to time, any larger changes would probably happen in ItemRack. TrinketMenu will be kept small and focused.
208 |
209 | Q: Localization?
210 | A: This mod should work on all clients. I can't test this for myself but many report it works fine.
211 |
212 | Q: I changed my notify settings on my warrior, but the change shows on my other characters also.
213 | A: Everything in the options window saves for all characters. Just position, orientation, docking and scaling are saved per-character.
214 |
215 | Q: I'd like to go back to using global position/orientation/docking for all my characters. Can I do this?
216 | A: Sure. Edit TrinketMenu.toc and change these two lines to the one that follows:
217 |
218 | Change:
219 | ## SavedVariables: TrinketMenuOptions
220 | ## SavedVariablesPerCharacter: TrinketMenuPerOptions
221 |
222 | To:
223 | ## SavedVariables: TrinketMenuOptions, TrinketMenuPerOptions
224 |
225 | To change all settings (notify, tooltips, etc), change the previous two lines to:
226 | ## SavedVariablesPerCharacter: TrinketMenuOptions, TrinketMenuPerOptions
227 |
228 | Q: How do I move the minimap icon?
229 | A: Drag it like a normal window. Left click and drag it around and it will slide around the edge.
230 |
231 | Q: I'm trying to swap trinkets, but instead of swapping it put a tiny trinket icon over my equipped one.
232 | A: This means you're in combat mode. You won't be able to swap trinkets until you leave combat. The tiny trinket is the one that will swap in once you leave combat.
233 |
234 | Q: What if I don't have Scrolling Combat Text, will it still notify me when trinket cooldowns expire?
235 | A: If you don't have SCT, it will notify in the "errors" overhead, where you get "Insufficient mana", "Out of range", etc type errors.
236 |
237 | Q: I don't have many trinkets and because of this I'm having problems docking to some corners. Any way to make it easier?
238 | A: Temporarily resize either window to make the differences greater so it's easier to dock to an exact corner.
239 |
240 | Q: It's not showing all my trinkets, I have over 30 of them in my bags.
241 | A: This version can handle only up to 32 trinkets. Two equipped and 30 in bags. If you exceed this amount, post how many trinkets you have and I'll up the limit. 30 seemed a reasonable number, but as the screenshots show it's not very difficult to get 30 trinkets if you're an engineer. In the meantime the mod will lift trinkets from right bag to left if you want to control which 30 are displayed.
242 |
243 | Q: I can't rotate, move or do anything with the windows.
244 | A: That sounds like the windows are locked. Enter: /trinket unlock
245 |
246 | __ Changes __
247 |
248 | 5.0.0 2013.04.15. Updated for 5.2, code cleanups.
249 | 3.81, 10/8/08, passed self to SortPriority_OnClick
250 | 3.8, 10/8/08, wotlk beta: scaling done via sliders, removed resize grips, this->self conversion should be complete, removed buff cache, queue won't process while casting
251 | 3.71, 5/7/08, removed ITEM_SPELL_CHARGES_P1 from tiny tooltip, no longer exists
252 | 3.7, 4/1/06, added: engineering bag support, queue won't swap a trinket with an active buff running
253 | 3.6, 12/5/06, live release of 3.5x beta changes
254 | 3.56, 12/1/06, bug fixed: GameTooltip:NumLines in shrink tooltip, removed use entries from Bindings.xml
255 | 3.55, 11/4/06, changed: key bindings moved to ClickBinder, added: shift/alt click options for minimap button
256 | 3.543, 10/27/06, changed: all key binding code to new dummy key bind method, attributes alt-item* to alt-slot*
257 | 3.542, 10/25/06, bugs fixed: converted .../args to .../select(#,...) in SetQueue, equip by name in process queue
258 | 3.541, 10/23/06, changed: UISpecialFrames temporarily removed
259 | 3.54, 10/22/06, added: key bindings, red out of range, removed: item cache and BAG_UPDATE system (wee), changed: using GetItemCooldown instead
260 | 3.53, 10/19/06, changed: "inventory" attribute to "item", check if GetItemInfo results valid on new item at patch
261 | 3.52, 10/14/06, changed: uses secure templates, alt to hide/show trinkets in menu, helpful pointer to the delay bit, /itemrack alpha
262 | 3.41, 8/24/06, added: /trinket load, changed: tabs removed and window shortened if TrinketMenuQueue not installed, bug fixed: /trinket reset (savedvars load defaults if nil), checked for Queue before setting HideOnLoad
263 | 3.4, 8/22/06, added: trinket profiles, delete trinket button
264 | 3.3, 8/5/06, added: 1.12 "Floating Combat Text" support, changed: trinkets coming off cooldown clear combat queue, toggle key binding obeys 'Disable Toggle' option
265 | 3.22, 7/24/06, added: TrinketMenu.SetQueue and TrinketMenu.GetQueue
266 | 3.21, 7/16/06, changed: lock also locks OptFrame, bug fixed: global strings stripped "%1$d Charge" to "%d Charge"
267 | 3.2, 7/16/06, added: Stop Queue On Swap option, global cooldown spinners, alt+click to stop queue cancels combatqueue
268 | 3.1, 7/12/06, changed: cooldown-enabled trinkets swapped in manually will not stop queue, added: "pause queue" attribute to trinkets, bug fixed: error from trinket used then banked while on cooldown, removed: trinket missing checks
269 | 3.01, 7/9/06, bug fixed: hunter fd will allow swap, minimap button can turn off
270 | 3.0, 7/9/06, rewritten, auto trinket queues, new timer and cooldown/notification system, options: set menu columns, tiny tooltips, large cooldowns, show key bindings
271 | 2.7 3/30/05 - added: /trinket debug, changed: update events disabled while zoning
272 | 2.6 2/8/05 - bug fixed: minimap button movement, added: option to drag around square minimap, option to show menu on shift only
273 | 2.5 1/4/05 - added: notify at 30 sec option, changes: 1.9 scaling, uses GetItemInfo, removed: scalebugfix, cooldowns off screen check
274 | 2.4 10/21/05 - added: /trinket scale slash command, sound on notify, changed: per-character position/orientation/docking, UseInventoryItem 13 and 14 hooked to reflect use, bug fixed: added scale bug fix back in
275 | 2.3 10/2/05 - added: option to disable tooltip, changed: options movable window that defaults to center, bug fixed: logging in character without trinkets won't prevent it from showing next login, for 1.8: pre-emptive fix for 1.8 SetPoint layout-cache bit, scale bug fix no longer performed
276 | 2.23 9/3/05 - bug fixed: hunter fd won't queue a trinket that can ordinarily swap, if the mod is hidden on logout it will be hidden on login
277 | 2.22 9/2/05 - bug fixed: if res'ed before releasing your spirit with trinkets in queue, they'll swap on revive normally
278 | 2.21 8/21/05 - bug fixed: window scaling bug definitively fixed, and error when clicking an empty trinket slot
279 | 2.2 8/20/05 - added: swap attempts while dead will queue trinkets to swap on revive, options to disable toggle, notify used only, and notify chats also, bugs fixed: error for more than 30 trinkets, notify corrected, hopeful fix for location bug some have: forced start/stopmove to save to layout-cache.txt, move the window to saved point going in/out of windowed mode
280 | 2.11 8/17/05 - changed: swap attempts won't happen if anything on cursor, bug fixed: options window will appear on screen irregardless where minimap is, added: /trinket debug to help find location bug issue some see
281 | 2.1 8/17/05 - added: a resize grip to lower right corner, trinket queue, option to dock/undock, notification when trinket cooldown ends (via SCT or overhead), bugs fixed: cooldown update made less frequent,
282 | 2.0 8/14/05 - rewritten from scratch, added up to 30+2 trinkets, menu grows outward, cooldown numbers, keep menu open option, minimap icon and scaling, far better handling of bag/inventory updates, cooldown models won't update if they're off the screen
283 | 1.1 7/20/05 - only react to BAG_UPDATE every second (by Thelgar), made lock/unlock more visually apparent and moved menu closer to main window
284 | 1.0 4/8/05 - initial release
--------------------------------------------------------------------------------
/TrinketMenuOpt.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | TrinketMenu.CheckButton_OnClick(self)
41 |
42 |
43 | TrinketMenu.OnTooltip(self)
44 |
45 |
46 | GameTooltip:Hide()
47 |
48 |
49 |
50 |
51 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
146 |
161 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 | TrinketMenu.OptColumnsSlider_OnValueChanged(self, value)
450 |
451 |
452 | TrinketMenu.SliderOnMouseWheel(self, delta)
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 | self:OnBackdropLoaded()
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 | TrinketMenu.OptMainScaleSlider_OnValueChanged(self, value)
499 |
500 |
501 | TrinketMenu.SliderOnMouseWheel(self, delta)
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 | self:OnBackdropLoaded()
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 | TrinketMenu.OptMenuScaleSlider_OnValueChanged(self, value)
548 |
549 |
550 | TrinketMenu.SliderOnMouseWheel(self, delta)
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 | self:OnBackdropLoaded()
561 |
562 |
563 |
564 |
565 |
566 |
567 | self:OnBackdropLoaded()
568 |
569 |
570 |
571 |
572 |
573 |
574 | self:OnBackdropLoaded()
575 |
576 |
577 | self:StartMoving()
578 |
579 |
580 | self:StopMovingOrSizing()
581 |
582 |
583 | TrinketMenu.OptFrame_OnShow()
584 |
585 |
586 |
587 |
588 |
--------------------------------------------------------------------------------
/TrinketMenuQueue.lua:
--------------------------------------------------------------------------------
1 | --[[ TrinketMenuQueue : auto queue system ]]
2 |
3 | local _G, type, string, tonumber, table, pairs, select = _G, type, string, tonumber, table, pairs, select
4 |
5 | local IsClassic = WOW_PROJECT_ID >= WOW_PROJECT_CLASSIC
6 |
7 | TrinketMenu.PausedQueue = { } -- 0 or 1 whether queue is paused
8 |
9 | local TRINKET_KEEP_BUFF_AFTER_SWAP = {
10 | [19341] = true,
11 | }
12 |
13 | function TrinketMenu.QueueInit()
14 | TrinketMenuQueue = TrinketMenuQueue or {
15 | Stats = { }, -- indexed by id of trinket, delay, priority and keep
16 | Sort = { }, -- indexed by number, ids in order of use
17 | Enabled = { } -- 0 or 1 whether auto queue is on for the slot
18 | }
19 | TrinketMenuQueue.Sort[0] = TrinketMenuQueue.Sort[0] or { }
20 | TrinketMenuQueue.Sort[1] = TrinketMenuQueue.Sort[1] or { }
21 | TrinketMenu_SubQueueFrame:SetBackdropBorderColor(.3, .3, .3,1)
22 | TrinketMenu_ProfilesFrame:SetBackdropBorderColor(.3, .3, .3, 1)
23 | TrinketMenu_ProfilesListFrame:SetBackdropBorderColor(.3, .3, .3, 1)
24 | TrinketMenu_SortPriorityText:SetText("Priority")
25 | TrinketMenu_SortPriorityText:SetTextColor(.95, .95, .95)
26 | TrinketMenu_SortKeepEquippedText:SetText("Pause Queue")
27 | TrinketMenu_SortKeepEquippedText:SetTextColor(.95, .95, .95)
28 | TrinketMenu_SortListFrame:SetBackdropBorderColor(.3, .3, .3, 1)
29 | TrinketMenu.ReflectQueueEnabled()
30 | TrinketMenu.UpdateCombatQueue()
31 | TrinketMenuQueue.Profiles = TrinketMenuQueue.Profiles or { }
32 | TrinketMenu.ValidateProfile()
33 | TrinketMenu.OpenSort(0)
34 | TrinketMenu.OpenSort(1)
35 | end
36 |
37 | function TrinketMenu.ReflectQueueEnabled()
38 | TrinketMenu_Trinket0Check:SetChecked(TrinketMenuQueue.Enabled[0])
39 | TrinketMenu_Trinket1Check:SetChecked(TrinketMenuQueue.Enabled[1])
40 | end
41 |
42 | function TrinketMenu.OpenSort(which)
43 | TrinketMenu.CurrentlySorting = which
44 | TrinketMenu.PopulateSort(which)
45 | TrinketMenu.SortSelected = 0
46 | TrinketMenu_SortScrollScrollBar:SetValue(0)
47 | TrinketMenu.SortValidate()
48 | TrinketMenu.SortScrollFrameUpdate()
49 | end
50 |
51 | function TrinketMenu.GetID(bag, slot)
52 | local _, id
53 | if slot then
54 | _, _, id = string.find(TrinketMenu.GetContainerItemLink(bag, slot) or "", "item:(%d+)")
55 | else
56 | _, _, id = string.find(GetInventoryItemLink("player", bag) or "", "item:(%d+)")
57 | end
58 | return id
59 | end
60 |
61 | function TrinketMenu.GetNameByID(id)
62 | if id == 0 then
63 | return "-- stop queue here --", "Interface\\Buttons\\UI-GroupLoot-Pass-Up", 1
64 | else
65 | local name, _, quality, _, _, _, _, _, _, texture = GetItemInfo(id or "")
66 | return name, texture, quality
67 | end
68 | end
69 |
70 | -- adds id to which sort if it's not already in the list
71 | function TrinketMenu.AddToSort(which, id)
72 | if not id then
73 | return
74 | end
75 | local found
76 | for i = 1, #TrinketMenuQueue.Sort[which] do
77 | found = found or TrinketMenuQueue.Sort[which][i] == id
78 | end
79 | if not found then
80 | table.insert(TrinketMenuQueue.Sort[which], id)
81 | end
82 | end
83 |
84 | -- populates sorts adding any new trinkets
85 | function TrinketMenu.PopulateSort(which)
86 | TrinketMenuQueue.Sort[which] = TrinketMenuQueue.Sort[which] or { }
87 | TrinketMenu.AddToSort(which,TrinketMenu.GetID(which + 13))
88 | TrinketMenu.AddToSort(which,TrinketMenu.GetID((1 - which) + 13))
89 | local _, equipLoc, id
90 | for i = 0, 4 do
91 | for j = 1, TrinketMenu.GetContainerNumSlots(i) do
92 | id = TrinketMenu.GetID(i, j)
93 | _, _, _, _, _, _, _, _, equipLoc = GetItemInfo(id or "")
94 | if equipLoc=="INVTYPE_TRINKET" then
95 | TrinketMenu.AddToSort(which, id)
96 | end
97 | end
98 | end
99 | TrinketMenu.AddToSort(which, 0) -- id 0 is Stop
100 | end
101 |
102 | function TrinketMenu.SortScrollFrameUpdate()
103 | local offset = FauxScrollFrame_GetOffset(TrinketMenu_SortScroll)
104 | local list = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting]
105 | FauxScrollFrame_Update(TrinketMenu_SortScroll, list and #list or 0, 9, 24)
106 | if list and list[1] then
107 | local r, g, b, found
108 | local texture, name, quality, idx
109 | local item, itemName, itemIcon
110 | for i = 1, 9 do
111 | item = _G["TrinketMenu_Sort"..i]
112 | itemName = _G["TrinketMenu_Sort"..i.."Name"]
113 | itemIcon = _G["TrinketMenu_Sort"..i.."Icon"]
114 | idx = offset + i
115 | if idx <= #list then
116 | name, texture, quality = TrinketMenu.GetNameByID(list[idx])
117 | itemIcon:SetTexture(texture)
118 | itemName:SetText(name)
119 | if quality then -- GetItemInfo may not be valid early on after patches
120 | r, g, b = GetItemQualityColor(quality)
121 | itemName:SetTextColor(r, g, b)
122 | itemIcon:SetVertexColor(1, 1, 1)
123 | end
124 | item:Show()
125 | if idx == TrinketMenu.SortSelected then
126 | TrinketMenu.LockHighlight(item)
127 | else
128 | TrinketMenu.UnlockHighlight(item)
129 | end
130 | else
131 | item:Hide()
132 | end
133 | end
134 | end
135 | end
136 |
137 | function TrinketMenu.LockHighlight(frame)
138 | if type(frame) == "string" then
139 | frame = _G[frame]
140 | end
141 | if not frame then
142 | return
143 | end
144 | frame.lockedHighlight = 1
145 | _G[frame:GetName().."Highlight"]:Show()
146 | end
147 |
148 | function TrinketMenu.UnlockHighlight(frame)
149 | if type(frame) == "string" then
150 | frame = _G[frame]
151 | end
152 | if not frame then
153 | return
154 | end
155 | frame.lockedHighlight = nil
156 | _G[frame:GetName().."Highlight"]:Hide()
157 | end
158 |
159 | -- shows tooltip for items in the sort list
160 | function TrinketMenu.SortTooltip(self)
161 | local idx = FauxScrollFrame_GetOffset(TrinketMenu_SortScroll) + self:GetID()
162 | local _
163 | local name, itemLink = GetItemInfo(TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting][idx] or "")
164 | _, _, itemLink = string.find(itemLink or "","(item:%d+:%d+:%d+:%d+:%d+:%d+:%d+)")
165 | if itemLink and TrinketMenuOptions.ShowTooltips == "ON" then
166 | TrinketMenu.AnchorTooltip(self)
167 | GameTooltip:SetHyperlink(itemLink)
168 | GameTooltip:Show()
169 | else
170 | TrinketMenu.OnTooltip(self,"Stop Queue Here", "Move this to mark the lowest trinket to auto queue. Sometimes you may want a passive trinket with a click effect to be the end (Burst of Knowledge, Second Wind, etc).")
171 | end
172 | end
173 |
174 | function TrinketMenu.SortOnClick(self)
175 | TrinketMenu_SortDelay:ClearFocus()
176 | local idx = FauxScrollFrame_GetOffset(TrinketMenu_SortScroll) + self:GetID()
177 | if TrinketMenu.SortSelected == idx then
178 | TrinketMenu.SortSelected = 0
179 | else
180 | TrinketMenu.SortSelected = idx
181 | end
182 | TrinketMenu.SortScrollFrameUpdate()
183 | TrinketMenu.SortValidate()
184 | end
185 |
186 | -- turns move buttons on/off, moves the list to keep selected in view and keeps the sorting slot button highlighted
187 | function TrinketMenu.SortValidate()
188 | local selected = TrinketMenu.SortSelected
189 | local list = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting]
190 | TrinketMenu_MoveTop:Enable()
191 | TrinketMenu_MoveUp:Enable()
192 | TrinketMenu_MoveDown:Enable()
193 | TrinketMenu_MoveBottom:Enable()
194 | if selected == 0 or #list < 2 then -- none selected, disable all
195 | TrinketMenu_MoveTop:Disable()
196 | TrinketMenu_MoveUp:Disable()
197 | TrinketMenu_MoveDown:Disable()
198 | TrinketMenu_MoveBottom:Disable()
199 | elseif selected == 1 then -- top selected, disable up
200 | TrinketMenu_MoveUp:Disable()
201 | TrinketMenu_MoveTop:Disable()
202 | TrinketMenu_MoveDown:Enable()
203 | elseif selected == #list then -- bottom selected, disable down
204 | TrinketMenu_MoveDown:Disable()
205 | TrinketMenu_MoveBottom:Disable()
206 | end
207 | local idx = FauxScrollFrame_GetOffset(TrinketMenu_SortScroll)
208 | if selected > 0 and list[selected] and list[selected] ~= 0 then
209 | TrinketMenu_SortDelay:Show()
210 | TrinketMenu_SortPriority:Show()
211 | TrinketMenu_SortKeepEquipped:Show()
212 | TrinketMenu_Delete:Enable()
213 | else
214 | TrinketMenu_SortDelay:Hide()
215 | TrinketMenu_SortPriority:Hide()
216 | TrinketMenu_SortKeepEquipped:Hide()
217 | TrinketMenu_Delete:Disable()
218 | end
219 | local stats = TrinketMenuQueue.Stats[list[TrinketMenu.SortSelected]]
220 | TrinketMenu_SortDelay:SetText(stats and (stats.delay or "0") or "0")
221 | TrinketMenu_SortPriority:SetChecked(stats and stats.priority)
222 | TrinketMenu_SortKeepEquipped:SetChecked(stats and stats.keep)
223 | if not IsShiftKeyDown() and selected > 0 then -- keep selected visible on list, moving thumb as needed, unless shift is down
224 | local parent = TrinketMenu_SortScrollScrollBar
225 | local offset
226 | if selected <= idx then
227 | offset = (selected == 1) and 0 or (parent:GetValue() - (parent:GetHeight() / 2))
228 | parent:SetValue(offset)
229 | PlaySound(1115)
230 | elseif selected >= (idx + 10) then
231 | offset = (selected == #list) and TrinketMenu_SortScroll:GetVerticalScrollRange() or (parent:GetValue() + (parent:GetHeight() / 2))
232 | parent:SetValue(offset)
233 | PlaySound(1115)
234 | end
235 | end
236 | end
237 |
238 | -- movement buttons
239 | function TrinketMenu.SortMove(self)
240 | TrinketMenu_SortDelay:ClearFocus()
241 | local dir = ((self == TrinketMenu_MoveUp) and - 1) or ((self == TrinketMenu_MoveTop) and "top") or ((self == TrinketMenu_MoveDown) and 1) or ((self == TrinketMenu_MoveBottom) and "bottom")
242 | local list = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting]
243 | local idx1 = TrinketMenu.SortSelected
244 | if dir then
245 | local idx2 = ((dir == "top") and 1) or ((dir == "bottom") and #list) or idx1 + dir
246 | local temp = list[idx1]
247 | if tonumber(dir) then
248 | list[idx1] = list[idx2]
249 | list[idx2] = temp
250 | elseif dir == "top" then
251 | table.remove(list, idx1)
252 | table.insert(list, 1, temp)
253 | elseif dir == "bottom" then
254 | table.remove(list, idx1)
255 | table.insert(list, temp)
256 | end
257 | TrinketMenu.SortSelected = idx2
258 | elseif self == TrinketMenu_Profiles then
259 | TrinketMenu.SortSelected = 0
260 | TrinketMenu.ShowProfiles(TrinketMenu_SortListFrame:IsVisible())
261 | elseif self == TrinketMenu_Delete then
262 | table.remove(list, idx1)
263 | TrinketMenu.SortSelected = 0
264 | end
265 | TrinketMenu.SortValidate()
266 | TrinketMenu.SortScrollFrameUpdate()
267 | end
268 |
269 | function TrinketMenu.SortDelay_OnTextChanged()
270 | local delay = tonumber(TrinketMenu_SortDelay:GetText()) or 0
271 | local id = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting][TrinketMenu.SortSelected]
272 | TrinketMenuQueue.Stats[id] = TrinketMenuQueue.Stats[id] or { }
273 | TrinketMenuQueue.Stats[id].delay = delay ~= 0 and delay or nil
274 | end
275 |
276 | function TrinketMenu.SortPriority_OnClick(self)
277 | local check = self:GetChecked()
278 | local id = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting][TrinketMenu.SortSelected]
279 | TrinketMenuQueue.Stats[id] = TrinketMenuQueue.Stats[id] or { }
280 | TrinketMenuQueue.Stats[id].priority = check
281 | end
282 |
283 | function TrinketMenu.SortKeepEquipped_OnClick(self)
284 | local check = self:GetChecked()
285 | local id = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting][TrinketMenu.SortSelected]
286 | TrinketMenuQueue.Stats[id] = TrinketMenuQueue.Stats[id] or { }
287 | TrinketMenuQueue.Stats[id].keep = check
288 | end
289 |
290 | function TrinketMenu.TabCheck_OnClick(self)
291 | TrinketMenuQueue.Enabled[3 - self:GetID()] = self:GetChecked()
292 | TrinketMenu.UpdateCombatQueue()
293 | end
294 |
295 | --[[ Auto queue processing ]]
296 |
297 | function TrinketMenu.TrinketNearReady(id)
298 | local start, duration = TrinketMenu.GetItemCooldown(id)
299 | if start == 0 or duration - (GetTime() - start) <= 30 then
300 | return 1
301 | end
302 | end
303 |
304 | function TrinketMenu.CanCooldown(inv)
305 | local _, _, enable = GetInventoryItemCooldown("player", inv)
306 | return enable == 1
307 | end
308 |
309 | -- this function quickly checks if conditions are right for a possible ProcessAutoQueue
310 | function TrinketMenu.PeriodicQueueCheck()
311 | if not TrinketMenuQueue.Enabled[0] and not TrinketMenuQueue.Enabled[1] then
312 | TrinketMenu.StopTimer("QueueUpdate")
313 | return
314 | end
315 | TrinketMenu.StartTimer("QueueUpdate")
316 | for i = 0, 1 do
317 | if TrinketMenuQueue.Enabled[i] then
318 | TrinketMenu.ProcessAutoQueue(i)
319 | end
320 | end
321 | end
322 |
323 | -- which = 0 or 1, decides if a trinket should be equipped and equips if so
324 | function TrinketMenu.ProcessAutoQueue(which)
325 | local _, _, id, name = string.find(GetInventoryItemLink("player", 13 + which) or "", "item:(%d+).+%[(.+)%]")
326 | if not id then
327 | return
328 | end -- leave if no trinket equipped
329 | local start, duration, enable = GetInventoryItemCooldown("player", 13 + which)
330 | local timeLeft = GetTime() - start
331 | local icon = _G["TrinketMenu_Trinket"..which.."Queue"]
332 | if IsInventoryItemLocked(13 + which) then
333 | return
334 | end -- leave if slot being swapped
335 | if (IsClassic and (CastingInfo() or ChannelInfo())) or (not IsClassic and (UnitCastingInfo("player") or UnitChannelInfo("player"))) then
336 | return
337 | end -- leave if player is casting/channeling
338 | if TrinketMenu.PausedQueue[which] then
339 | icon:SetVertexColor(1, .5, .5) -- leave if SetQueue(which, "PAUSE")
340 | return
341 | end
342 | if TrinketMenuQueue.Stats[id] then
343 | if TrinketMenuQueue.Stats[id].keep then
344 | icon:SetVertexColor(1, .5, .5)
345 | return -- leave if .keep flag set on this item
346 | end
347 | if TrinketMenuQueue.Stats[id].delay then
348 | -- leave if currently equipped trinket is on cooldown for less than its delay
349 | if start > 0 and (duration - timeLeft) > 30 and timeLeft < TrinketMenuQueue.Stats[id].delay then
350 | icon:SetDesaturated(true)
351 | return
352 | end
353 | else
354 | local buffName = GetItemSpell(id)
355 | if buffName then
356 | if IsClassic then
357 | if not TRINKET_KEEP_BUFF_AFTER_SWAP[id] then
358 | local i = 1
359 | local buff
360 | while UnitAura("player", i, "HELPFUL") do
361 | buff = UnitAura("player", i, "HELPFUL")
362 | if buffName == buff or (start > 0 and (duration - timeLeft) > 30 and timeLeft < 1) then
363 | icon:SetDesaturated(true)
364 | return
365 | end
366 | i = i + 1
367 | end
368 | end
369 | else
370 | if AuraUtil.FindAuraByName(buffName, "player", "HELPFUL") or (start > 0 and (duration - timeLeft) > 30 and timeLeft < 1) then
371 | icon:SetDesaturated(true)
372 | return
373 | end
374 | end
375 | end
376 | end
377 | end
378 | icon:SetDesaturated(false) -- normal queue operation, reflect that in queue inset
379 | icon:SetVertexColor(1, 1, 1)
380 | local name
381 | local ready = TrinketMenu.TrinketNearReady(id)
382 | if ready and TrinketMenu.CombatQueue[which] then
383 | TrinketMenu.CombatQueue[which] = nil
384 | TrinketMenu.UpdateCombatQueue()
385 | end
386 | local list, rank = TrinketMenuQueue.Sort[which]
387 | for i = 1, #list do
388 | if list[i] == 0 then
389 | rank = i
390 | break
391 | end
392 | if ready and list[i] == id then
393 | rank = i
394 | break
395 | end
396 | end
397 | if rank then
398 | for i = 1, rank do
399 | if not ready or enable == 0 or (TrinketMenuQueue.Stats[list[i]] and TrinketMenuQueue.Stats[list[i]].priority) then
400 | if TrinketMenu.TrinketNearReady(list[i]) then
401 | if GetItemCount(list[i]) > 0 and not IsEquippedItem(list[i]) then
402 | local _, bag, slot = TrinketMenu.FindItem(list[i])
403 | if bag then
404 | name = GetItemInfo(list[i])
405 | if TrinketMenu.CombatQueue[which] ~= name then
406 | TrinketMenu.EquipTrinketByName(name, 13 + which)
407 | end
408 | break
409 | end
410 | end
411 | end
412 | end
413 | end
414 | end
415 | end
416 |
417 | --[[ TrinketMenu.SetQueue and TrinketMenu.GetQueue ]]
418 |
419 | -- These functions are for macros and mods to configure sort queues
420 |
421 | -- TrinketMenu.SetQueue(0 or 1,"ON" or "OFF" or "PAUSE" or "RESUME" or "SORT"[,"sort list")
422 | -- some examples:
423 | -- TrinketMenu.SetQueue(1, "PAUSE") -- if queue is going, pause it
424 | -- TrinketMenu.SetQueue(1, "RESUME") -- if queue is paused, resume it
425 | -- TrinketMenu.SetQueue(1, "SORT", "Earthstrike", "Insignia of the Alliance", "Diamond Flask") -- set sort
426 | -- TrinketMenu.SetQueue(0, "SORT", "Lifestone", "Darkmoon Card: Heroism") -- set sort for trinket 0
427 | -- TrinketMenu.SetQueue(1, "SORT", "Pvp Profile") -- note you can replace list with a profile name
428 | -- (a "stop the queue" is assumed at the end of the list)
429 | function TrinketMenu.SetQueue(which, ...)
430 | local errorstub = "|cFFBBBBBBTrinketMenu:|cFFFFFFFF "
431 | if not which or not tonumber(which) or which < 0 or which > 1 then
432 | DEFAULT_CHAT_FRAME:AddMessage(errorstub.."First parameter must be 0 for top trinket or 1 for bottom.")
433 | return
434 | end
435 | if (select("#", ...)) < 1 then
436 | DEFAULT_CHAT_FRAME:AddMessage(errorstub.."Second parameter is either ON, OFF, PAUSE, RESUME or the beginning of a list of trinkets in a sort order.")
437 | return
438 | end
439 | if TrinketMenu_OptFrame:IsVisible() then
440 | TrinketMenu_OptFrame:Hide() -- close option frame if it's up. the mess otherwise would be scary
441 | end
442 | local cmd = (select(1, ...))
443 | if cmd == "ON" then
444 | TrinketMenuQueue.Enabled[which] = 1
445 | TrinketMenu.PausedQueue[which] = nil
446 | elseif cmd == "OFF" then
447 | TrinketMenuQueue.Enabled[which] = nil
448 | TrinketMenu.PausedQueue[which] = nil
449 | elseif cmd == "PAUSE" then
450 | TrinketMenu.PausedQueue[which] = 1
451 | elseif cmd == "RESUME" then
452 | TrinketMenu.PausedQueue[which] = nil
453 | elseif cmd == "SORT" and (select("#",...)) > 1 then
454 | local inv, bag, slot
455 | for i in pairs(TrinketMenuQueue.Sort[which]) do
456 | TrinketMenuQueue.Sort[which][i] = nil
457 | end
458 | --table.setn(TrinketMenuQueue.Sort[which], 0)
459 | local profile = TrinketMenu.GetProfileID((select(2,...)))
460 | if profile then
461 | for i = 2, #TrinketMenuQueue.Profiles[profile] do
462 | table.insert(TrinketMenuQueue.Sort[which], TrinketMenuQueue.Profiles[profile][i])
463 | end
464 | else
465 | for i = 2, (select("#", ...)) do
466 | inv, bag, slot = TrinketMenu.FindItem((select(i, ...)), true) -- include inventory
467 | if inv then
468 | table.insert(TrinketMenuQueue.Sort[which], TrinketMenu.GetID(inv))
469 | elseif bag then
470 | table.insert(TrinketMenuQueue.Sort[which], TrinketMenu.GetID(bag, slot))
471 | else
472 | DEFAULT_CHAT_FRAME:AddMessage(errorstub.."Trinket or profile \""..(select(i, ...)).."\" not found.")
473 | end
474 | end
475 | table.insert(TrinketMenuQueue.Sort[which], 0)
476 | end
477 | else
478 | DEFAULT_CHAT_FRAME:AddMessage(errorstub.." Expected ON, OFF, PAUSE, RESUME or SORT+list")
479 | end
480 | TrinketMenu.ReflectQueueEnabled()
481 | TrinketMenu.UpdateCombatQueue()
482 | end
483 |
484 | -- returns 1 or nil if queue is enabled, and a table containing an ordered list of the trinkets
485 | function TrinketMenu.GetQueue(which)
486 | if not which or not tonumber(which) or which < 0 or which > 1 then
487 | DEFAULT_CHAT_FRAME:AddMessage("|cFFBBBBBBTrinketMenu.GetQueue:|cFFFFFFFF Parameter must be 0 for top trinket or 1 for bottom.")
488 | return
489 | end
490 | local trinketList, name = { }
491 | for i = 1, #TrinketMenuQueue.Sort[which] do
492 | name = TrinketMenu.GetNameByID(TrinketMenuQueue.Sort[which][i])
493 | table.insert(trinketList, name)
494 | end
495 | return TrinketMenuQueue.Enabled[which], trinketList
496 | end
497 |
498 | --[[ Profiles ]]
499 |
500 | -- add="add" or "remove" to add or remove "frame" from UISpecialFrames
501 | function TrinketMenu.Escable(frame, add)
502 | local found
503 | for i in pairs(UISpecialFrames) do
504 | found = found or (UISpecialFrames[i] == frame and i)
505 | end
506 | if not found and add == "add" then
507 | table.insert(UISpecialFrames, frame)
508 | elseif found and add == "remove" then
509 | table.remove(UISpecialFrames, found)
510 | end
511 | end
512 |
513 | -- shows profile if show non-nil. TrinketMenu_ProfilesFrame has an OnHide that calls this with nil
514 | function TrinketMenu.ShowProfiles(show)
515 | local normalTexture = TrinketMenu_Profiles:GetNormalTexture()
516 | local pushedTexture = TrinketMenu_Profiles:GetPushedTexture()
517 | if show then
518 | TrinketMenu_SortListFrame:Hide()
519 | TrinketMenu_ProfilesFrame:Show()
520 | normalTexture:SetTexCoord(.875, 1, .25, .375)
521 | pushedTexture:SetTexCoord(.75, .875, .25, .375)
522 | TrinketMenu.Escable("TrinketMenu_ProfilesFrame", "add")
523 | TrinketMenu.Escable("TrinketMenu_OptFrame", "remove")
524 | else
525 | TrinketMenu_SortListFrame:Show()
526 | TrinketMenu_ProfilesFrame:Hide()
527 | pushedTexture:SetTexCoord(.875, 1, .25, .375)
528 | normalTexture:SetTexCoord(.75, .875, .25, .375)
529 | TrinketMenu.Escable("TrinketMenu_ProfilesFrame", "remove")
530 | TrinketMenu.Escable("TrinketMenu_OptFrame", "add")
531 | end
532 | end
533 |
534 | function TrinketMenu.ProfilesFrame_OnHide()
535 | PlaySound(624)
536 | TrinketMenu.ResetProfileSelected()
537 | TrinketMenu.ShowProfiles(nil)
538 | end
539 |
540 | function TrinketMenu.ResetProfileSelected()
541 | TrinketMenu.ProfileSelected = nil
542 | TrinketMenu_ProfileName:SetText("")
543 | TrinketMenu.ProfileScrollFrameUpdate()
544 | TrinketMenu.ValidateProfile()
545 | end
546 |
547 | function TrinketMenu.ProfileScrollFrameUpdate()
548 | local offset = FauxScrollFrame_GetOffset(TrinketMenu_ProfileScroll)
549 | local list = TrinketMenuQueue.Profiles
550 | FauxScrollFrame_Update(TrinketMenu_ProfileScroll, #(list) or 0, 7, 20)
551 | local item, idx
552 | for i = 1, 7 do
553 | idx = offset + i
554 | item = _G["TrinketMenu_Profile"..i]
555 | if idx <= #list then
556 | _G["TrinketMenu_Profile"..i.."Name"]:SetText(list[idx][1])
557 | item:Show()
558 | if TrinketMenu.ProfileSelected == idx then
559 | item:LockHighlight()
560 | else
561 | item:UnlockHighlight()
562 | end
563 | else
564 | item:Hide()
565 | end
566 | end
567 | if #list == 0 then
568 | TrinketMenu_Profile1Name:SetText("No profiles saved yet.")
569 | TrinketMenu_Profile1:Show()
570 | TrinketMenu_Profile1:UnlockHighlight()
571 | end
572 |
573 | end
574 |
575 | function TrinketMenu.ProfileList_OnClick(self)
576 | if #TrinketMenuQueue.Profiles > 0 then
577 | local idx = self:GetID() + FauxScrollFrame_GetOffset(TrinketMenu_ProfileScroll)
578 | if TrinketMenu.ProfileSelected == idx then
579 | TrinketMenu.ProfileSelected = nil
580 | TrinketMenu_ProfileName:SetText("")
581 | else
582 | TrinketMenu.ProfileSelected = idx
583 | TrinketMenu_ProfileName:SetText(TrinketMenuQueue.Profiles[idx][1])
584 | end
585 | TrinketMenu.ProfileScrollFrameUpdate()
586 | TrinketMenu.ValidateProfile()
587 | end
588 | end
589 |
590 | function TrinketMenu.GetProfileID(name)
591 | for i = 1, #TrinketMenuQueue.Profiles do
592 | if TrinketMenuQueue.Profiles[i][1] == name then
593 | return i
594 | end
595 | end
596 | end
597 |
598 | function TrinketMenu.ValidateProfile()
599 | local name = TrinketMenu_ProfileName:GetText() or ""
600 | TrinketMenu_ProfilesDelete:Disable()
601 | TrinketMenu_ProfilesLoad:Disable()
602 | TrinketMenu_ProfilesSave:Disable()
603 | if TrinketMenu.GetProfileID(name) then
604 | TrinketMenu_ProfilesDelete:Enable()
605 | TrinketMenu_ProfilesLoad:Enable()
606 | end
607 | if strlen(name) > 0 then
608 | TrinketMenu_ProfilesSave:Enable()
609 | end
610 | end
611 |
612 | function TrinketMenu.ProfileName_OnTextChanged()
613 | TrinketMenu.ProfileSelected = TrinketMenu.GetProfileID(TrinketMenu_ProfileName:GetText())
614 | TrinketMenu.ProfileScrollFrameUpdate()
615 | TrinketMenu.ValidateProfile()
616 | end
617 |
618 | function TrinketMenu.ProfilesButton_OnClick(self)
619 | local idx = TrinketMenu.ProfileSelected
620 | local name = TrinketMenu_ProfileName:GetText() or ""
621 | if self == TrinketMenu_ProfilesDelete then
622 | if idx and TrinketMenuQueue.Profiles[idx] then
623 | table.remove(TrinketMenuQueue.Profiles, idx)
624 | end
625 | TrinketMenu.ResetProfileSelected()
626 | elseif self == TrinketMenu_ProfilesSave then
627 | if idx and TrinketMenuQueue.Profiles[idx] then
628 | table.remove(TrinketMenuQueue.Profiles, idx)
629 | end
630 | table.insert(TrinketMenuQueue.Profiles, 1, {name})
631 | local list = TrinketMenuQueue.Sort[TrinketMenu.CurrentlySorting]
632 | local save = TrinketMenuQueue.Profiles[1]
633 | for i = 1, #list do
634 | table.insert(save, list[i])
635 | if list[i] == 0 then
636 | break
637 | end
638 | end
639 | TrinketMenu_ProfilesFrame:Hide()
640 | elseif self == TrinketMenu_ProfilesLoad then
641 | TrinketMenu.LoadProfile(TrinketMenu.CurrentlySorting, idx)
642 | elseif self == TrinketMenu_ProfilesCancel then
643 | TrinketMenu_ProfilesFrame:Hide()
644 | end
645 | end
646 |
647 | function TrinketMenu.ProfileList_OnDoubleClick(self)
648 | if #TrinketMenuQueue.Profiles > 0 then
649 | local idx = self:GetID() + FauxScrollFrame_GetOffset(TrinketMenu_ProfileScroll)
650 | if TrinketMenuQueue.Profiles[idx] then
651 | TrinketMenu.LoadProfile(TrinketMenu.CurrentlySorting, idx)
652 | end
653 | end
654 | end
655 |
656 | function TrinketMenu.LoadProfile(which, idx)
657 | local list = TrinketMenuQueue.Sort[which]
658 | local load = TrinketMenuQueue.Profiles[idx]
659 | for i in pairs(list) do
660 | list[i] = nil
661 | end
662 | --table.setn(list, 0)
663 | for i = 2, #load do
664 | table.insert(list, load[i])
665 | end
666 | TrinketMenu_ProfilesFrame:Hide()
667 | TrinketMenu.OpenSort(which)
668 | if TrinketMenuOptions.HideOnLoad == "ON" then
669 | TrinketMenu_OptFrame:Hide()
670 | end
671 | end
672 |
--------------------------------------------------------------------------------
/TrinketMenuQueue.xml:
--------------------------------------------------------------------------------
1 |
2 |
29 |
30 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | self:SetFrameLevel(getglobal("TrinketMenu_Tab"..self:GetID()):GetFrameLevel()+2)
57 |
58 |
59 | TrinketMenu.OnTooltip(self)
60 |
61 |
62 | GameTooltip:Hide()
63 |
64 |
65 | TrinketMenu.TabCheck_OnClick(self)
66 |
67 |
68 |
69 |
70 |
129 |
130 |
149 |
150 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
236 |
254 |
272 |
290 |
305 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 | TrinketMenu.OnTooltip(self)
393 |
394 |
395 | GameTooltip:Hide()
396 |
397 |
398 | self:ClearFocus()
399 |
400 |
401 | self:ClearFocus()
402 |
403 |
404 | TrinketMenu.SortDelay_OnTextChanged()
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 | TrinketMenu.SortPriority_OnClick(self)
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 | TrinketMenu.SortKeepEquipped_OnClick(self)
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
489 |
494 |
499 |
504 |
509 |
514 |
519 |
524 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 | FauxScrollFrame_OnVerticalScroll(self, offset, 24, TrinketMenu.SortScrollFrameUpdate)
559 |
560 |
561 | TrinketMenu.SortScrollFrameUpdate()
562 |
563 |
564 |
565 |
566 |
567 |
568 | self:OnBackdropLoaded()
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 | TrinketMenu.OnTooltip(self)
672 |
673 |
674 | GameTooltip:Hide()
675 |
676 |
677 | self:ClearFocus()
678 |
679 |
680 | self:ClearFocus()
681 |
682 |
683 | TrinketMenu.ProfileName_OnTextChanged()
684 |
685 |
686 |
687 |
688 |
697 |
706 |
715 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
772 |
777 |
782 |
787 |
792 |
797 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 | FauxScrollFrame_OnVerticalScroll(self, offset, 20, TrinketMenu.ProfileScrollFrameUpdate)
832 |
833 |
834 | TrinketMenu.ProfileScrollFrameUpdate()
835 |
836 |
837 |
838 |
839 |
840 |
841 | self:OnBackdropLoaded()
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 | self:OnBackdropLoaded()
858 |
859 |
860 | TrinketMenu.ProfilesFrame_OnHide()
861 |
862 |
863 | PlaySound(624)
864 |
865 |
866 |
867 |
868 |
869 |
870 |
--------------------------------------------------------------------------------
/TrinketMenu.lua:
--------------------------------------------------------------------------------
1 | --[[ TrinketMenu 11.1.8 ]]--
2 |
3 | TrinketMenu = { }
4 |
5 | local _G, math, tonumber, string, type, pairs, ipairs, table, select = _G, math, tonumber, string, type, pairs, ipairs, table, select
6 | local Masque = LibStub("Masque", true)
7 |
8 | local IsClassic = WOW_PROJECT_ID >= WOW_PROJECT_CLASSIC
9 | local IsVanillaClassic = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
10 | local IsRetail = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
11 |
12 | -- localized strings required to support engineering bags
13 | TrinketMenu.BAG = "Bag" -- 7th return of GetItemInfo on a normal bag
14 | TrinketMenu.ENGINEERING_BAG = "Engineering Bag" -- 7th return of GetItemInfo on an engineering bag
15 | TrinketMenu.TRADE_GOODS = "Trade Goods" -- 6th return of GetItemInfo on most engineered trinkets
16 | TrinketMenu.DEVICES = "Devices" -- 7th return of GetItemInfo on most engineered trinkets
17 | TrinketMenu.REQUIRES_ENGINEERING = "Requires Engineering" -- from tooltip when GetItemInfo ambiguous
18 |
19 | function TrinketMenu.LoadDefaults()
20 | TrinketMenuOptions = TrinketMenuOptions or {
21 | IconPos = - 100, -- angle of initial minimap icon position
22 | ShowIcon = "ON", -- whether to show the minimap button
23 | SquareMinimap = "OFF", -- whether the minimap is square instead of circular
24 | CooldownCount = "OFF", -- whether to display numerical cooldown counters
25 | CooldownCountBlizzard = "ON", -- whether to display numerical blizzard cooldown counters
26 | CooldownCountOmniCC = "ON", -- whether to display numerical omnicc cooldown counters
27 | LargeCooldown = "ON", -- whether cooldown numbers are large or small
28 | TooltipFollow = "OFF", -- whether tooltips follow the mouse
29 | KeepOpen = "OFF", -- whether menu hides after use
30 | KeepDocked = "ON", -- whether to keep menu docked at all times
31 | Notify = "OFF", -- whether a message appears when a trinket is ready
32 | DisableToggle = "OFF", -- whether minimap button toggles trinkets
33 | NotifyUsedOnly = "OFF", -- whether notify happens only on trinkets used
34 | NotifyChatAlso = "OFF", -- whether to send notify to chat also
35 | Locked = "OFF", -- whether windows can be moved/scaled/rotated
36 | ShowTooltips = "ON", -- whether to display tooltips at all
37 | NotifyThirty = "OFF", -- whether to notify cooldowns at 30 seconds instead of 0
38 | MenuOnShift = "OFF", -- whether menu requires Shift to display
39 | TinyTooltips = "OFF", -- whether tooltips display only name and cooldown
40 | SetColumns = "OFF", -- whether number of columns in menu is chosen automatically
41 | Columns = 4, -- if SetColumns "ON", number of columns before menu wraps
42 | ShowHotKeys = "OFF", -- whether hotkeys show on trinkets
43 | StopOnSwap = "OFF", -- whether to stop auto queue on all manual swaps
44 | RedRange = "OFF", -- whether to monitor and red out out of range trinkets
45 | HidePetBattle = "ON", -- whether to hide the trinkets while in a pet battle
46 | MenuOnRight = "OFF" -- whether to open menu with right-click
47 | }
48 | TrinketMenuPerOptions = TrinketMenuPerOptions or {
49 | MainDock = "BOTTOMRIGHT", -- corner of main window docked to
50 | MenuDock = "BOTTOMLEFT", -- corner menu window is docked from
51 | MainOrient = "HORIZONTAL", -- direction of main window
52 | MenuOrient = "VERTICAL", -- direction of menu window
53 | XPos = 400, -- left edge of main window
54 | YPos = 400, -- top edge of main window
55 | MainScale = 1, -- scaling of main window
56 | MenuScale = 1, -- scaling of menu window
57 | Visible = "ON", -- whether to display the trinkets
58 | FirstUse = true, -- whether this is the first time this user has used the mod
59 | ItemsUsed = { }, -- table of trinkets used and their cooldown status
60 | Alpha = 1, -- alpha of both windows
61 | Hidden = { } -- table of trinkets hidden
62 | }
63 | end
64 |
65 | --[[ Misc Variables ]]--
66 |
67 | TrinketMenu_Version = C_AddOns.GetAddOnMetadata("TrinketMenu", "Version")
68 | BINDING_HEADER_TRINKETMENU = "TrinketMenu"
69 | setglobal("BINDING_NAME_CLICK TrinketMenu_Trinket0:LeftButton", "Use Top Trinket")
70 | setglobal("BINDING_NAME_CLICK TrinketMenu_Trinket1:LeftButton", "Use Bottom Trinket")
71 |
72 | TrinketMenu.MaxTrinkets = 30 -- add more to TrinketMenu_MenuFrame if this changes
73 | TrinketMenu.BaggedTrinkets = { } -- indexed by number, 1-30 of trinkets in the menu
74 | TrinketMenu.NumberOfTrinkets = 0 -- number of trinkets in the menu
75 | TrinketMenu.CombatQueue = { } -- [0] or [1] = name of trinket queued for slot 0 or 1
76 | TrinketMenu.Corners = {"TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT"}
77 |
78 | --[[ Local functions ]]--
79 |
80 | -- dock-dependant offset and directions: MainDock..MenuDock
81 | -- x/yoff = offset MenuFrame is positioned to MainFrame
82 | -- x/ydir = direction trinkets are added to menu
83 | -- x/ystart = starting offset when building a menu, relativePoint MenuDock
84 | if IsRetail then
85 | TrinketMenu.DockStats = {
86 | ["TOPRIGHTTOPLEFT"] = { xoff = -7, yoff = 0, xdir = 1, ydir = - 1, xstart = 4, ystart = -4 },
87 | ["BOTTOMRIGHTBOTTOMLEFT"] = { xoff = -7, yoff = 0, xdir = 1, ydir = 1, xstart = 4, ystart = 48 },
88 | ["TOPLEFTTOPRIGHT"] = { xoff = 7, yoff = 0, xdir = - 1, ydir = -1, xstart = -48, ystart = -4 },
89 | ["BOTTOMLEFTBOTTOMRIGHT"] = { xoff = 7, yoff = 0, xdir = - 1, ydir = 1, xstart = -48, ystart = 48 },
90 | ["TOPRIGHTBOTTOMRIGHT"] = { xoff = 0, yoff = -7, xdir = -1, ydir = 1, xstart = -48, ystart = 48 },
91 | ["BOTTOMRIGHTTOPRIGHT"] = { xoff = 0, yoff = 7, xdir = - 1, ydir = -1, xstart = -48, ystart = -4 },
92 | ["TOPLEFTBOTTOMLEFT"] = { xoff = 0, yoff = -7, xdir = 1, ydir = 1, xstart = 4, ystart = 48 },
93 | ["BOTTOMLEFTTOPLEFT"] = { xoff = 0, yoff = 7, xdir = 1, ydir = - 1, xstart = 4, ystart = -4 }
94 | }
95 | else
96 | TrinketMenu.DockStats = {
97 | ["TOPRIGHTTOPLEFT"] = { xoff = -12, yoff = 0, xdir = 1, ydir = - 1, xstart = 8, ystart = -8 },
98 | ["BOTTOMRIGHTBOTTOMLEFT"] = { xoff = -12, yoff = 0, xdir = 1, ydir = 1, xstart = 8, ystart = 44 },
99 | ["TOPLEFTTOPRIGHT"] = { xoff = 12, yoff = 0, xdir = -1, ydir = -1, xstart = -44, ystart = -8 },
100 | ["BOTTOMLEFTBOTTOMRIGHT"] = { xoff = 12, yoff = 0, xdir = -1, ydir = 1, xstart = -44, ystart = 44 },
101 | ["TOPRIGHTBOTTOMRIGHT"] = { xoff = 0, yoff = -12, xdir = -1, ydir = 1, xstart = -44, ystart = 44 },
102 | ["BOTTOMRIGHTTOPRIGHT"] = { xoff = 0, yoff = 12, xdir = -1, ydir = -1, xstart = -44, ystart = -8 },
103 | ["TOPLEFTBOTTOMLEFT"] = { xoff = 0, yoff = -12, xdir = 1, ydir = 1, xstart = 8, ystart = 44 },
104 | ["BOTTOMLEFTTOPLEFT"] = { xoff = 0, yoff = 12, xdir = 1, ydir = - 1, xstart = 8, ystart = -8 }
105 | }
106 | end
107 |
108 | -- returns offset and direction depending on current docking. ie: TrinketMenu.DockInfo("xoff")
109 | function TrinketMenu.DockInfo(arg1)
110 | local anchor = TrinketMenuPerOptions.MainDock..TrinketMenuPerOptions.MenuDock
111 | if TrinketMenu.DockStats[anchor] and arg1 and TrinketMenu.DockStats[anchor][arg1] then
112 | return TrinketMenu.DockStats[anchor][arg1]
113 | else
114 | return 0
115 | end
116 | end
117 |
118 | -- hide the docking markers
119 | function TrinketMenu.ClearDocking()
120 | for i = 1, 4 do
121 | _G["TrinketMenu_MainDock_"..TrinketMenu.Corners[i]]:Hide()
122 | _G["TrinketMenu_MenuDock_"..TrinketMenu.Corners[i]]:Hide()
123 | end
124 | end
125 |
126 | -- returns true if the two values are close to each other
127 | function TrinketMenu.Near(arg1, arg2)
128 | return (math.max(arg1, arg2) - math.min(arg1, arg2)) < 15
129 | end
130 |
131 | -- moves the MenuFrame to the dock position against MainFrame
132 | function TrinketMenu.DockWindows()
133 | TrinketMenu.ClearDocking()
134 | if TrinketMenuOptions.KeepDocked == "ON" then
135 | TrinketMenu_MenuFrame:ClearAllPoints()
136 | if TrinketMenuOptions.Locked == "OFF" then
137 | TrinketMenu_MenuFrame:SetPoint(TrinketMenuPerOptions.MenuDock, "TrinketMenu_MainFrame", TrinketMenuPerOptions.MainDock, TrinketMenu.DockInfo("xoff"), TrinketMenu.DockInfo("yoff"))
138 | else
139 | TrinketMenu_MenuFrame:SetPoint(TrinketMenuPerOptions.MenuDock, "TrinketMenu_MainFrame", TrinketMenuPerOptions.MainDock, TrinketMenu.DockInfo("xoff"), TrinketMenu.DockInfo("yoff"))
140 | end
141 | end
142 | if TrinketMenu_MenuFrame:IsVisible() then
143 | TrinketMenu.BuildMenu()
144 | end
145 | end
146 |
147 | -- displays windows vertically or horizontally
148 | function TrinketMenu.OrientWindows()
149 | if TrinketMenuPerOptions.MainOrient == "HORIZONTAL" then
150 | if IsRetail then
151 | TrinketMenu_MainFrame:SetWidth(97)
152 | TrinketMenu_MainFrame:SetHeight(52)
153 | else
154 | TrinketMenu_MainFrame:SetWidth(92)
155 | TrinketMenu_MainFrame:SetHeight(52)
156 | end
157 | else
158 | if IsRetail then
159 | TrinketMenu_MainFrame:SetWidth(52)
160 | TrinketMenu_MainFrame:SetHeight(97)
161 | else
162 | TrinketMenu_MainFrame:SetWidth(52)
163 | TrinketMenu_MainFrame:SetHeight(92)
164 | end
165 | end
166 | end
167 |
168 | function TrinketMenu.ScaleFrame(scale)
169 | TrinketMenu.FrameToScale:SetScale(scale)
170 | end
171 |
172 | function TrinketMenu.GetContainerNumSlots(bagID)
173 | return C_Container.GetContainerNumSlots(bagID)
174 | end
175 |
176 | function TrinketMenu.GetContainerItemCooldown(bagID, slotIndex)
177 | return C_Container.GetContainerItemCooldown(bagID, slotIndex)
178 | end
179 |
180 | function TrinketMenu.GetContainerItemInfo(bagID, slotIndex)
181 | return C_Container.GetContainerItemInfo(bagID, slotIndex)
182 | end
183 |
184 | function TrinketMenu.GetContainerItemLink(bagID, slotIndex)
185 | return C_Container.GetContainerItemLink(bagID, slotIndex)
186 | end
187 |
188 | function TrinketMenu.PickupContainerItem(bagID, slotIndex)
189 | return C_Container.PickupContainerItem(bagID, slotIndex)
190 | end
191 |
192 | function TrinketMenu.GetItemCooldown(itemID)
193 | return C_Container.GetItemCooldown(itemID)
194 | end
195 |
196 | -- scan inventory and build MenuFrame
197 | function TrinketMenu.BuildMenu()
198 | if not IsShiftKeyDown() and TrinketMenuOptions.MenuOnShift == "ON" then
199 | return
200 | end
201 | local idx = 1
202 | local _, itemLink, itemID, itemName, equipSlot, itemTexture
203 | -- go through bags and gather trinkets into .BaggedTrinkets
204 | for i = 0, 4 do
205 | for j = 1, TrinketMenu.GetContainerNumSlots(i) do
206 | itemLink = TrinketMenu.GetContainerItemLink(i, j)
207 | if itemLink then
208 | _, _, itemID, itemName = string.find(TrinketMenu.GetContainerItemLink(i, j) or "", "item:(%d+).+%[(.+)%]")
209 | _, _, _, _, _, _, _, _, equipSlot, itemTexture = GetItemInfo(itemID or "")
210 | if equipSlot == "INVTYPE_TRINKET" and (IsAltKeyDown() or not TrinketMenuPerOptions.Hidden[itemID]) then
211 | if not TrinketMenu.BaggedTrinkets[idx] then
212 | TrinketMenu.BaggedTrinkets[idx] = { }
213 | end
214 | TrinketMenu.BaggedTrinkets[idx].id = itemID
215 | TrinketMenu.BaggedTrinkets[idx].bag = i
216 | TrinketMenu.BaggedTrinkets[idx].slot = j
217 | TrinketMenu.BaggedTrinkets[idx].name = itemName
218 | TrinketMenu.BaggedTrinkets[idx].texture = itemTexture
219 | idx = idx + 1
220 | end
221 | end
222 | end
223 | end
224 | TrinketMenu.NumberOfTrinkets = math.min(idx - 1, TrinketMenu.MaxTrinkets)
225 | if TrinketMenu.NumberOfTrinkets < 1 then
226 | -- user has no bagged trinkets :(
227 | TrinketMenu_MenuFrame:Hide()
228 | else
229 | -- display trinkets outward from docking point
230 | local col, row, xpos, ypos = 0, 0, TrinketMenu.DockInfo("xstart"), TrinketMenu.DockInfo("ystart")
231 | local max_cols = 1
232 | if TrinketMenu.NumberOfTrinkets > 24 then
233 | max_cols = 5
234 | elseif TrinketMenu.NumberOfTrinkets > 18 then
235 | max_cols = 4
236 | elseif TrinketMenu.NumberOfTrinkets > 12 then
237 | max_cols = 3
238 | elseif TrinketMenu.NumberOfTrinkets > 4 then
239 | max_cols = 2
240 | end
241 | if TrinketMenuOptions.SetColumns == "ON" and TrinketMenuOptions.Columns then
242 | max_cols = TrinketMenuOptions.Columns
243 | end
244 | local item, icon
245 | for i = 1, TrinketMenu.NumberOfTrinkets do
246 | item = _G["TrinketMenu_Menu"..i]
247 | icon = _G["TrinketMenu_Menu"..i.."Icon"]
248 | icon:SetTexture(TrinketMenu.BaggedTrinkets[i].texture)
249 | if TrinketMenuPerOptions.Hidden[TrinketMenu.BaggedTrinkets[i].id] then
250 | icon:SetDesaturated(true)
251 | else
252 | icon:SetDesaturated(false)
253 | end
254 | item:SetPoint("TOPLEFT", "TrinketMenu_MenuFrame", TrinketMenuPerOptions.MenuDock, xpos, ypos)
255 | if TrinketMenuPerOptions.MenuOrient == "VERTICAL" then
256 | xpos = xpos + TrinketMenu.DockInfo("xdir") * (IsRetail and 45 or 40)
257 | col = col + 1
258 | if col == max_cols then
259 | xpos = TrinketMenu.DockInfo("xstart")
260 | col = 0
261 | ypos = ypos + TrinketMenu.DockInfo("ydir") * (IsRetail and 45 or 40)
262 | row = row + 1
263 | end
264 | item:Show()
265 | else
266 | ypos = ypos + TrinketMenu.DockInfo("ydir") * (IsRetail and 45 or 40)
267 | col = col + 1
268 | if col == max_cols then
269 | ypos = TrinketMenu.DockInfo("ystart")
270 | col = 0
271 | xpos = xpos + TrinketMenu.DockInfo("xdir") * (IsRetail and 45 or 40)
272 | row = row + 1
273 | end
274 | item:Show()
275 | end
276 | end
277 | for i = (TrinketMenu.NumberOfTrinkets + 1), TrinketMenu.MaxTrinkets do
278 | _G["TrinketMenu_Menu"..i]:Hide()
279 | end
280 | if col == 0 then
281 | row = row - 1
282 | end
283 | if TrinketMenuPerOptions.MenuOrient == "VERTICAL" then
284 | TrinketMenu_MenuFrame:SetWidth((IsRetail and 7 or 12) + (max_cols * (IsRetail and 45 or 40)))
285 | TrinketMenu_MenuFrame:SetHeight((IsRetail and 7 or 12) + ((row + 1) * (IsRetail and 45 or 40)))
286 | else
287 | TrinketMenu_MenuFrame:SetWidth((IsRetail and 7 or 12) + ((row + 1) * (IsRetail and 45 or 40)))
288 | TrinketMenu_MenuFrame:SetHeight((IsRetail and 7 or 12) + (max_cols * (IsRetail and 45 or 40)))
289 | end
290 | TrinketMenu.UpdateMenuCooldowns()
291 | TrinketMenu_MenuFrame:Show()
292 | TrinketMenu.StartTimer("MenuMouseover")
293 | end
294 | end
295 |
296 | function TrinketMenu.Initialize()
297 | local options = TrinketMenuOptions
298 | -- Set TrinketMenu Skin
299 | if (Masque and not TrinketMenu.MasqueGroup) then
300 | local group = Masque:Group("TrinketMenu")
301 | TrinketMenu.MasqueGroup = group
302 | group:AddButton(TrinketMenu_Trinket0)
303 | group:AddButton(TrinketMenu_Trinket1)
304 | for i = 1, 30 do
305 | _G["TrinketMenu_Menu"..i]:SetFrameLevel(2)
306 | group:AddButton(_G["TrinketMenu_Menu"..i])
307 | end
308 | end
309 | options.KeepDocked = options.KeepDocked or "ON" -- new option for 2.1
310 | options.Notify = options.Notify or "OFF" -- 2.1
311 | options.DisableToggle = options.DisableToggle or "OFF" -- new option for 2.2
312 | options.NotifyUsedOnly = options.NotifyUsedOnly or "OFF" -- 2.2
313 | options.NotifyChatAlso = options.NotifyChatAlso or "OFF" -- 2.2
314 | options.ShowTooltips = options.ShowTooltips or "ON" -- 2.3
315 | options.NotifyThirty = options.NotifyThirty or "OFF" -- 2.5
316 | options.SquareMinimap = options.SquareMinimap or "OFF" -- 2.6
317 | options.MenuOnShift = options.MenuOnShift or "OFF" -- 2.6
318 | options.TinyTooltips = options.TinyTooltips or "OFF" -- 3.0
319 | options.SetColumns = options.SetColumns or "OFF" -- 3.0
320 | options.Columns = options.Columns or 4 -- 3.0
321 | options.CooldownCount = options.CooldownCount or "OFF" -- 3.0
322 | options.LargeCooldown = options.LargeCooldown or "OFF" -- 3.0
323 | options.ShowHotKeys = options.ShowHotKeys or "OFF" -- 3.0
324 | TrinketMenuPerOptions.ItemsUsed = TrinketMenuPerOptions.ItemsUsed or { } -- 3.0
325 | options.StopOnSwap = options.StopOnSwap or "OFF" -- 3.2
326 | options.HideOnLoad = options.HideOnLoad or "OFF" -- 3.4
327 | options.RedRange = options.RedRange or "OFF" -- 3.54
328 | options.HidePetBattle = options.HidePetBattle or "ON" -- 6.0.3
329 | options.CooldownCountBlizzard = options.CooldownCountBlizzard or "ON" -- 11.1.6
330 | options.CooldownCountOmniCC = options.CooldownCountOmniCC or "ON" -- 11.1.6
331 | TrinketMenuPerOptions.Alpha = TrinketMenuPerOptions.Alpha or 1 -- 3.5
332 | TrinketMenuPerOptions.Hidden = TrinketMenuPerOptions.Hidden or { }
333 | options.MenuOnRight = options.MenuOnRight or "OFF" -- 3.61
334 | if TrinketMenuPerOptions.XPos and TrinketMenuPerOptions.YPos then
335 | TrinketMenu_MainFrame:ClearAllPoints()
336 | TrinketMenu_MainFrame:SetPoint("TOPLEFT", "UIParent", "BOTTOMLEFT", TrinketMenuPerOptions.XPos, TrinketMenuPerOptions.YPos)
337 | end
338 | if TrinketMenuPerOptions.MainScale then
339 | TrinketMenu_MainFrame:SetScale(TrinketMenuPerOptions.MainScale)
340 | end
341 | if TrinketMenuPerOptions.MenuScale then
342 | TrinketMenu_MenuFrame:SetScale(TrinketMenuPerOptions.MenuScale)
343 | end
344 | TrinketMenu.ReflectAlpha()
345 | TrinketMenu_Trinket0:SetAttribute("type", "item")
346 | TrinketMenu_Trinket1:SetAttribute("type", "item")
347 | TrinketMenu_Trinket0:SetAttribute("slot", 13)
348 | TrinketMenu_Trinket1:SetAttribute("slot", 14)
349 | if TrinketMenu.QueueInit then
350 | -- alt has a special purpose if queue installed
351 | TrinketMenu_Trinket0:SetAttribute("alt-slot*", ATTRIBUTE_NOOP)
352 | TrinketMenu_Trinket1:SetAttribute("alt-slot*", ATTRIBUTE_NOOP)
353 | end
354 | TrinketMenu_Trinket0:SetAttribute("shift-slot*", ATTRIBUTE_NOOP)
355 | TrinketMenu_Trinket1:SetAttribute("shift-slot*", ATTRIBUTE_NOOP)
356 | TrinketMenu.ReflectMenuOnRight()
357 | TrinketMenu.InitTimers()
358 | TrinketMenu.CreateTimer("UpdateWornTrinkets", TrinketMenu.UpdateWornTrinkets, .75)
359 | TrinketMenu.CreateTimer("DockingMenu", TrinketMenu.DockingMenu, .2, 1)
360 | TrinketMenu.CreateTimer("MenuMouseover", TrinketMenu.MenuMouseover, .25, 1)
361 | TrinketMenu.CreateTimer("TooltipUpdate", TrinketMenu.TooltipUpdate, 1, 1)
362 | TrinketMenu.CreateTimer("CooldownUpdate", TrinketMenu.CooldownUpdate, 1, 1)
363 | TrinketMenu.CreateTimer("QueueUpdate", TrinketMenu.QueueUpdate, 1, 1)
364 | --TrinketMenu.CreateTimer("RedRange", TrinketMenu.RedRangeUpdate, .33, 1)
365 | hooksecurefunc("UseInventoryItem", TrinketMenu.newUseInventoryItem)
366 | hooksecurefunc("UseAction", TrinketMenu.newUseAction)
367 | TrinketMenu.InitOptions()
368 | TrinketMenu.UpdateWornTrinkets()
369 | TrinketMenu.DockWindows()
370 | TrinketMenu.OrientWindows()
371 | if options.CooldownCount == "ON" or options.NotifyThirty == "ON" or options.Notify == "ON" then
372 | TrinketMenu.StartTimer("CooldownUpdate")
373 | end
374 | if TrinketMenu_Trinket0 and TrinketMenu_Trinket0.cooldown then
375 | if options.CooldownCountBlizzard == "ON" then
376 | TrinketMenu_Trinket0.cooldown:SetHideCountdownNumbers(false)
377 | else
378 | TrinketMenu_Trinket0.cooldown:SetHideCountdownNumbers(true)
379 | end
380 | if options.CooldownCountOmniCC == "ON" then
381 | TrinketMenu_Trinket0.cooldown.noCooldownCount = false
382 | else
383 | TrinketMenu_Trinket0.cooldown.noCooldownCount = true
384 |
385 | end
386 | end
387 | if TrinketMenu_Trinket1 and TrinketMenu_Trinket1.cooldown then
388 | if options.CooldownCountBlizzard == "ON" then
389 | TrinketMenu_Trinket1.cooldown:SetHideCountdownNumbers(false)
390 | else
391 | TrinketMenu_Trinket1.cooldown:SetHideCountdownNumbers(true)
392 | end
393 | if options.CooldownCountOmniCC == "ON" then
394 | TrinketMenu_Trinket1.cooldown.noCooldownCount = false
395 | else
396 | TrinketMenu_Trinket1.cooldown.noCooldownCount = true
397 | end
398 | end
399 | for i = 1, TrinketMenu.MaxTrinkets do
400 | local menuButton = _G["TrinketMenu_Menu"..i]
401 | if menuButton and menuButton.cooldown then
402 | if options.CooldownCountBlizzard == "ON" then
403 | menuButton.cooldown:SetHideCountdownNumbers(false)
404 | else
405 | menuButton.cooldown:SetHideCountdownNumbers(true)
406 | end
407 | if options.CooldownCountOmniCC == "ON" then
408 | menuButton.cooldown.noCooldownCount = false
409 | else
410 | menuButton.cooldown.noCooldownCount = true
411 | end
412 | end
413 | end
414 | if TrinketMenu.PeriodicQueueCheck then
415 | TrinketMenu.PeriodicQueueCheck()
416 | end
417 | --TrinketMenu.StartTimer("QueueUpdate")
418 | --TrinketMenu.ReflectRedRange()
419 | if TrinketMenuPerOptions.Visible == "ON" and (GetInventoryItemLink("player", 13) or GetInventoryItemLink("player", 14)) then
420 | TrinketMenu_MainFrame:Show()
421 | end
422 | -- fix for OmniCC
423 | TrinketMenu_MainFrame:SetFrameLevel(1)
424 | TrinketMenu_MenuFrame:SetFrameLevel(1)
425 | TrinketMenu_Trinket0:SetFrameLevel(2)
426 | TrinketMenu_Trinket1:SetFrameLevel(2)
427 | for i = 1, TrinketMenu.MaxTrinkets do
428 | _G["TrinketMenu_Menu"..i]:SetFrameLevel(2)
429 | end
430 |
431 | end
432 |
433 | function TrinketMenu.ReflectMenuOnRight()
434 | TrinketMenu_Trinket0:SetAttribute("slot2", TrinketMenuOptions.MenuOnRight == "ON" and ATTRIBUTE_NOOP or nil)
435 | TrinketMenu_Trinket1:SetAttribute("slot2", TrinketMenuOptions.MenuOnRight == "ON" and ATTRIBUTE_NOOP or nil)
436 | end
437 |
438 | -- returns true if the player is really dead or ghost, not merely FD
439 | function TrinketMenu.IsPlayerReallyDead()
440 | if IsVanillaClassic then
441 | return UnitIsDeadOrGhost("player") and not UnitIsFeignDeath("player")
442 | else
443 | return UnitIsDeadOrGhost("player")
444 | end
445 | end
446 |
447 | function TrinketMenu.ItemInfo(slot)
448 | local _
449 | local link, id, name, equipLoc, texture = GetInventoryItemLink("player", slot)
450 | if link then
451 | local _, _, id = string.find(link, "item:(%d+)")
452 | name, _, _, _, _, _, _, _, equipLoc, texture = GetItemInfo(id)
453 | else
454 | _, texture = GetInventorySlotInfo("Trinket"..(slot - 13).."Slot")
455 | end
456 | return texture, name, equipLoc
457 | end
458 |
459 | function TrinketMenu.FindItem(item, includeInventory)
460 | if includeInventory then
461 | for i = 13, 14 do
462 | local itemLink = GetInventoryItemLink("player", i) or ""
463 | local inventoryItemID = strmatch(itemLink, "item:(%d+)")
464 | local itemName = GetItemInfo(itemLink)
465 | if item == itemName or item == inventoryItemID then
466 | return i
467 | end
468 | end
469 | end
470 | for i = 0, 4 do
471 | for j = 1, TrinketMenu.GetContainerNumSlots(i) do
472 | local containerItemLink = TrinketMenu.GetContainerItemLink(i, j) or ""
473 | local containerItemID = strmatch(containerItemLink, "item:(%d+)")
474 | local containerItemName = GetItemInfo(containerItemLink)
475 | if item == containerItemName or item == containerItemID then
476 | return nil, i, j
477 | end
478 | end
479 | end
480 | end
481 |
482 | --[[ Frame Scripts ]]--
483 |
484 | function TrinketMenu.OnLoad(self)
485 | self:OnBackdropLoaded()
486 | self:SetBackdropColor(0.0, 0.0, 0.0)
487 | self:SetBackdropBorderColor(0.0, 0.0, 0.0)
488 | SlashCmdList["TrinketMenuCOMMAND"] = TrinketMenu.SlashHandler
489 | SLASH_TrinketMenuCOMMAND1 = "/trinketmenu"
490 | SLASH_TrinketMenuCOMMAND2 = "/trinket"
491 | self:RegisterEvent("PLAYER_LOGIN")
492 | end
493 |
494 | function TrinketMenu.OnEvent(self, event, ...)
495 | if event == "UNIT_INVENTORY_CHANGED" then
496 | local unitID = ...
497 | if unitID == "player" then
498 | TrinketMenu.UpdateWornTrinkets()
499 | end
500 | elseif event == "PLAYER_EQUIPMENT_CHANGED" then
501 | TrinketMenu.UpdateWornTrinkets()
502 | elseif event == "ACTIONBAR_UPDATE_COOLDOWN" then
503 | TrinketMenu.UpdateWornCooldowns(1)
504 | elseif event == "PET_BATTLE_OPENING_START" then
505 | if TrinketMenuOptions.HidePetBattle == "ON" then
506 | TrinketMenu_MainFrame.WasShown = TrinketMenu_MainFrame:IsShown()
507 | if TrinketMenu_MainFrame.WasShown then
508 | TrinketMenu_MainFrame:Hide()
509 | end
510 | TrinketMenu_MenuFrame.WasShown = TrinketMenu_MenuFrame:IsShown()
511 | if TrinketMenu_MenuFrame.WasShown then
512 | TrinketMenu_MenuFrame:Hide()
513 | end
514 | end
515 | elseif event == "PET_BATTLE_CLOSE" then
516 | if TrinketMenuOptions.HidePetBattle == "ON" then
517 | if TrinketMenu_MainFrame.WasShown then
518 | TrinketMenu_MainFrame:Show()
519 | end
520 | if TrinketMenu_MenuFrame.WasShown then
521 | TrinketMenu_MenuFrame:Show()
522 | end
523 | end
524 | elseif (event == "PLAYER_REGEN_ENABLED" or event == "PLAYER_UNGHOST" or event == "PLAYER_ALIVE") and not TrinketMenu.IsPlayerReallyDead() then
525 | if TrinketMenu.CombatQueue[0] or TrinketMenu.CombatQueue[1] then
526 | TrinketMenu.EquipTrinketByName(TrinketMenu.CombatQueue[0], 13)
527 | TrinketMenu.EquipTrinketByName(TrinketMenu.CombatQueue[1], 14)
528 | TrinketMenu.CombatQueue[0] = nil
529 | TrinketMenu.CombatQueue[1] = nil
530 | TrinketMenu.UpdateCombatQueue()
531 | end
532 | TrinketMenu_OptMenuOnRight:Enable()
533 | elseif event == "UPDATE_BINDINGS" then
534 | TrinketMenu.KeyBindingsChanged()
535 | elseif event == "PLAYER_REGEN_DISABLED" then
536 | TrinketMenu_OptMenuOnRight:Disable()
537 | elseif event == "PLAYER_LOGIN" then
538 | TrinketMenu.LoadDefaults()
539 | TrinketMenu.Initialize()
540 | self:RegisterEvent("PLAYER_REGEN_ENABLED")
541 | self:RegisterEvent("PLAYER_REGEN_DISABLED")
542 | self:RegisterEvent("PLAYER_UNGHOST")
543 | self:RegisterEvent("PLAYER_ALIVE")
544 | self:RegisterEvent("UNIT_INVENTORY_CHANGED")
545 | self:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
546 | self:RegisterEvent("UPDATE_BINDINGS")
547 | self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN")
548 | if not IsClassic then
549 | self:RegisterEvent("PET_BATTLE_OPENING_START")
550 | self:RegisterEvent("PET_BATTLE_CLOSE")
551 | end
552 | end
553 | end
554 |
555 | function TrinketMenu.UpdateWornTrinkets()
556 | local texture, name = TrinketMenu.ItemInfo(13)
557 | TrinketMenu_Trinket0Icon:SetTexture(texture)
558 | texture, name = TrinketMenu.ItemInfo(14)
559 | TrinketMenu_Trinket1Icon:SetTexture(texture)
560 | TrinketMenu_Trinket0Icon:SetDesaturated(false)
561 | TrinketMenu_Trinket0:SetChecked(false)
562 | TrinketMenu_Trinket1Icon:SetDesaturated(false)
563 | TrinketMenu_Trinket1:SetChecked(false)
564 | TrinketMenu.UpdateWornCooldowns()
565 | if TrinketMenu_MenuFrame:IsVisible() then
566 | TrinketMenu.BuildMenu()
567 | end
568 | end
569 |
570 | function TrinketMenu.SlashHandler(msg)
571 | local _, _, which, profile = string.find(msg, "load (.+) (.+)")
572 | if profile and TrinketMenu.SetQueue then
573 | which = string.lower(which)
574 | if which == "top" or which == "0" then
575 | which = 0
576 | elseif which == "bottom" or which == "1" then
577 | which = 1
578 | end
579 | if type(which) == "number" then
580 | TrinketMenu.SetQueue(which, "SORT", profile)
581 | return
582 | end
583 | end
584 | msg = string.lower(msg)
585 | if not msg or msg == "" then
586 | TrinketMenu.ToggleFrame(TrinketMenu_MainFrame)
587 | elseif string.find(msg, "^opt") or string.find(msg, "^config") then
588 | TrinketMenu.ToggleFrame(TrinketMenu_OptFrame)
589 | elseif msg == "lock" then
590 | TrinketMenuOptions.Locked = "ON"
591 | TrinketMenu.DockWindows()
592 | TrinketMenu.ReflectLock()
593 | elseif msg == "unlock" then
594 | TrinketMenuOptions.Locked = "OFF"
595 | TrinketMenu.DockWindows()
596 | TrinketMenu.ReflectLock()
597 | elseif msg == "reset" then
598 | TrinketMenu.ResetSettings()
599 | elseif msg == "clear" then
600 | wipe(TrinketMenuPerOptions.Hidden)
601 | DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu: Cleared all ignored/hidden trinkets.")
602 | elseif string.find(msg, "alpha") then
603 | local _, _, alpha = string.find(msg, "alpha (.+)")
604 | alpha = tonumber(alpha)
605 | if alpha and alpha > 0 and alpha <= 1.0 then
606 | TrinketMenuPerOptions.Alpha = alpha
607 | else
608 | DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu alpha:")
609 | DEFAULT_CHAT_FRAME:AddMessage("trinket alpha (number) : set alpha from 0.1 to 1.0")
610 | end
611 | TrinketMenu.ReflectAlpha()
612 | elseif string.find(msg, "scale") then
613 | local _, _, menuscale = string.find(msg, "scale menu (.+)")
614 | if tonumber(menuscale) then
615 | TrinketMenu.FrameToScale = TrinketMenu_MenuFrame
616 | TrinketMenu.ScaleFrame(menuscale)
617 | end
618 | local _, _, mainscale = string.find(msg, "scale main (.+)")
619 | if tonumber(mainscale) then
620 | TrinketMenu.FrameToScale = TrinketMenu_MainFrame
621 | TrinketMenu.ScaleFrame(mainscale)
622 | end
623 | if not tonumber(menuscale) and not tonumber(mainscale) then
624 | DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu scale:")
625 | DEFAULT_CHAT_FRAME:AddMessage("/trinket scale main (number) : set exact main scale")
626 | DEFAULT_CHAT_FRAME:AddMessage("/trinket scale menu (number) : set exact menu scale")
627 | DEFAULT_CHAT_FRAME:AddMessage("ie, /trinket scale menu 0.85")
628 | DEFAULT_CHAT_FRAME:AddMessage("Note: You can drag the lower-right corner of either window to scale. This slash command is for those who want to set an exact scale.")
629 | end
630 | TrinketMenu.FrameToScale = nil
631 | TrinketMenuPerOptions.MainScale = TrinketMenu_MainFrame:GetScale()
632 | TrinketMenuPerOptions.MenuScale = TrinketMenu_MenuFrame:GetScale()
633 | elseif string.find(msg, "load") then
634 | DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu load:")
635 | DEFAULT_CHAT_FRAME:AddMessage("/trinket load (top|bottom) profilename\nie: /trinket load bottom PvP")
636 | else
637 | DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00TrinketMenu useage:")
638 | DEFAULT_CHAT_FRAME:AddMessage("/trinket or /trinketmenu : toggle the window")
639 | DEFAULT_CHAT_FRAME:AddMessage("/trinket reset : reset all settings")
640 | DEFAULT_CHAT_FRAME:AddMessage("/trinket clear : clear all ignored/hidden trinkets")
641 | DEFAULT_CHAT_FRAME:AddMessage("/trinket opt : summon options window")
642 | DEFAULT_CHAT_FRAME:AddMessage("/trinket lock|unlock : toggles window lock")
643 | DEFAULT_CHAT_FRAME:AddMessage("/trinket scale main|menu (number) : sets an exact scale")
644 | DEFAULT_CHAT_FRAME:AddMessage("/trinket load top|bottom profilename : loads a profile to top or bottom trinket")
645 | end
646 | end
647 |
648 | function TrinketMenu.ResetSettings()
649 | StaticPopupDialogs["TRINKETMENURESET"] = {
650 | text = "Are you sure you want to reset TrinketMenu to default state and reload the UI?",
651 | button1 = "Yes", button2 = "No", showAlert = 1, timeout = 0, whileDead = 1,
652 | OnAccept = function()
653 | TrinketMenuOptions = nil
654 | TrinketMenuPerOptions = nil
655 | TrinketMenuQueue = nil
656 | ReloadUI()
657 | end
658 | }
659 | StaticPopup_Show("TRINKETMENURESET")
660 | end
661 |
662 | --[[ Window Movement ]]--
663 |
664 | function TrinketMenu.MainFrame_OnMouseUp(self)
665 | local arg1 = GetMouseButtonClicked()
666 | if arg1 == "LeftButton" then
667 | self:StopMovingOrSizing()
668 | TrinketMenuPerOptions.XPos = TrinketMenu_MainFrame:GetLeft()
669 | TrinketMenuPerOptions.YPos = TrinketMenu_MainFrame:GetTop()
670 | elseif TrinketMenuOptions.Locked == "OFF" then
671 | if TrinketMenuPerOptions.MainOrient == "VERTICAL" then
672 | TrinketMenuPerOptions.MainOrient = "HORIZONTAL"
673 | else
674 | TrinketMenuPerOptions.MainOrient = "VERTICAL"
675 | end
676 | TrinketMenu.OrientWindows()
677 | end
678 | end
679 |
680 | function TrinketMenu.MainFrame_OnMouseDown(self)
681 | if GetMouseButtonClicked() == "LeftButton" and TrinketMenuOptions.Locked == "OFF" then
682 | self:StartMoving()
683 | end
684 | end
685 |
686 | --[[ Timers ]]
687 |
688 | function TrinketMenu.InitTimers()
689 | TrinketMenu.TimerPool = { }
690 | TrinketMenu.Timers = { }
691 | end
692 |
693 | function TrinketMenu.CreateTimer(name, func, delay, rep)
694 | TrinketMenu.TimerPool[name] = {func = func, delay = delay, rep = rep, elapsed = delay}
695 | end
696 |
697 | function TrinketMenu.IsTimerActive(name)
698 | for i, j in ipairs(TrinketMenu.Timers) do
699 | if j == name then
700 | return i
701 | end
702 | end
703 | return nil
704 | end
705 |
706 | function TrinketMenu.StartTimer(name, delay)
707 | TrinketMenu.TimerPool[name].elapsed = delay or TrinketMenu.TimerPool[name].delay
708 | if not TrinketMenu.IsTimerActive(name) then
709 | table.insert(TrinketMenu.Timers, name)
710 | TrinketMenu_TimersFrame:Show()
711 | end
712 | end
713 |
714 | function TrinketMenu.StopTimer(name)
715 | local idx = TrinketMenu.IsTimerActive(name)
716 | if idx then
717 | table.remove(TrinketMenu.Timers, idx)
718 | if #TrinketMenu.Timers < 1 then
719 | TrinketMenu_TimersFrame:Hide()
720 | end
721 | end
722 | end
723 |
724 | function TrinketMenu.TimersFrame_OnUpdate(elapsed)
725 | local timerPool
726 | for _, name in ipairs(TrinketMenu.Timers) do
727 | timerPool = TrinketMenu.TimerPool[name]
728 | timerPool.elapsed = timerPool.elapsed - elapsed
729 | if timerPool.elapsed < 0 then
730 | timerPool.func()
731 | if timerPool.rep then
732 | timerPool.elapsed = timerPool.delay
733 | else
734 | TrinketMenu.StopTimer(name)
735 | end
736 | end
737 | end
738 | if TrinketMenu.PeriodicQueueCheck then
739 | TrinketMenu.PeriodicQueueCheck()
740 | end -- Check for auto queue
741 | end
742 |
743 | function TrinketMenu.TimerDebug()
744 | local on = "|cFF00FF00On"
745 | local off = "|cFFFF0000Off"
746 | DEFAULT_CHAT_FRAME:AddMessage("|cFF44AAFFTrinketMenu_TimersFrame is "..(TrinketMenu_TimersFrame:IsVisible() and on or off))
747 | for i in pairs(TrinketMenu.TimerPool) do
748 | DEFAULT_CHAT_FRAME:AddMessage(i.." is "..(TrinketMenu.IsTimerActive(i) and on or off))
749 | end
750 | end
751 |
752 | --[[ OnClicks ]]
753 |
754 | function TrinketMenu.MainTrinket_OnClick(self, button, down)
755 | self:SetChecked(false)
756 | if button == "RightButton" and TrinketMenuOptions.MenuOnRight == "ON" then
757 | if TrinketMenu_MenuFrame:IsVisible() then
758 | TrinketMenu_MenuFrame:Hide()
759 | else
760 | TrinketMenu.BuildMenu()
761 | end
762 | elseif IsShiftKeyDown() and down then
763 | if ChatFrame1EditBox:IsVisible() then
764 | ChatFrame1EditBox:Insert(GetInventoryItemLink("player", self:GetID()))
765 | end
766 | elseif IsAltKeyDown() and not down and TrinketMenu.QueueInit then
767 | local which = self:GetID() - 13
768 | if TrinketMenuQueue.Enabled[which] then
769 | TrinketMenu.CombatQueue[self:GetID() - 13] = nil
770 | TrinketMenuQueue.Enabled[which] = nil
771 | else
772 | TrinketMenuQueue.Enabled[which] = 1
773 | end
774 | TrinketMenu.ReflectQueueEnabled()
775 | -- toggle queue
776 | TrinketMenu.UpdateCombatQueue()
777 | else
778 | TrinketMenu.ReflectTrinketUse(self:GetID())
779 | end
780 | end
781 |
782 | function TrinketMenu.MenuTrinket_OnClick(self, button, down)
783 | self:SetChecked(false)
784 | if IsShiftKeyDown() and ChatFrame1EditBox:IsVisible() then
785 | ChatFrame1EditBox:Insert(TrinketMenu.GetContainerItemLink(TrinketMenu.BaggedTrinkets[self:GetID()].bag, TrinketMenu.BaggedTrinkets[self:GetID()].slot))
786 | elseif IsAltKeyDown() then
787 | local _, _, itemID = string.find(TrinketMenu.GetContainerItemLink(TrinketMenu.BaggedTrinkets[self:GetID()].bag, TrinketMenu.BaggedTrinkets[self:GetID()].slot) or "", "item:(%d+)")
788 | if TrinketMenuPerOptions.Hidden[itemID] then
789 | TrinketMenuPerOptions.Hidden[itemID] = nil
790 | else
791 | TrinketMenuPerOptions.Hidden[itemID] = 1
792 | end
793 | TrinketMenu.BuildMenu()
794 | else
795 | local slot = (button == "LeftButton") and 13 or 14
796 | if TrinketMenu.QueueInit then
797 | local _, _, canCooldown = TrinketMenu.GetContainerItemCooldown(TrinketMenu.BaggedTrinkets[self:GetID()].bag, TrinketMenu.BaggedTrinkets[self:GetID()].slot)
798 | if canCooldown == 0 or TrinketMenuOptions.StopOnSwap == "ON" then -- if incoming trinket can't go on cooldown
799 | TrinketMenuQueue.Enabled[slot - 13] = nil -- turn off autoqueue
800 | TrinketMenu.ReflectQueueEnabled()
801 | end
802 | end
803 | TrinketMenu.EquipTrinketByName(TrinketMenu.BaggedTrinkets[self:GetID()].name, slot)
804 | if not IsShiftKeyDown() and TrinketMenuOptions.KeepOpen == "OFF" then
805 | TrinketMenu_MenuFrame:Hide()
806 | end
807 | end
808 | end
809 |
810 | --[[ Docking ]]
811 |
812 | function TrinketMenu.MenuFrame_OnMouseDown(button)
813 | if button == "LeftButton" and TrinketMenuOptions.Locked == "OFF" then
814 | TrinketMenu_MenuFrame:StartMoving()
815 | if TrinketMenuOptions.KeepDocked == "ON" then
816 | TrinketMenu.StartTimer("DockingMenu")
817 | end
818 | end
819 | end
820 |
821 | function TrinketMenu.MenuFrame_OnMouseUp(button)
822 | if button == "LeftButton" then
823 | TrinketMenu.StopTimer("DockingMenu")
824 | TrinketMenu_MenuFrame:StopMovingOrSizing()
825 | if TrinketMenuOptions.KeepDocked == "ON" then
826 | TrinketMenu.DockWindows()
827 | end
828 | elseif TrinketMenuOptions.Locked == "OFF" then
829 | if TrinketMenuPerOptions.MenuOrient == "VERTICAL" then
830 | TrinketMenuPerOptions.MenuOrient = "HORIZONTAL"
831 | else
832 | TrinketMenuPerOptions.MenuOrient = "VERTICAL"
833 | end
834 | TrinketMenu.BuildMenu()
835 | end
836 | end
837 |
838 | function TrinketMenu.DockingMenu()
839 | local main = TrinketMenu_MainFrame
840 | local menu = TrinketMenu_MenuFrame
841 | local mainscale = TrinketMenu_MainFrame:GetScale()
842 | local menuscale = TrinketMenu_MenuFrame:GetScale()
843 | local near = TrinketMenu.Near
844 | if near(main:GetRight() * mainscale,menu:GetLeft() * menuscale) then
845 | if near(main:GetTop() * mainscale,menu:GetTop() * menuscale) then
846 | TrinketMenuPerOptions.MainDock = "TOPRIGHT"
847 | TrinketMenuPerOptions.MenuDock = "TOPLEFT"
848 | elseif near(main:GetBottom() * mainscale,menu:GetBottom() * menuscale) then
849 | TrinketMenuPerOptions.MainDock = "BOTTOMRIGHT"
850 | TrinketMenuPerOptions.MenuDock = "BOTTOMLEFT"
851 | end
852 | elseif near(main:GetLeft() * mainscale,menu:GetRight() * menuscale) then
853 | if near(main:GetTop() * mainscale,menu:GetTop() * menuscale) then
854 | TrinketMenuPerOptions.MainDock = "TOPLEFT"
855 | TrinketMenuPerOptions.MenuDock = "TOPRIGHT"
856 | elseif near(main:GetBottom() * mainscale,menu:GetBottom() * menuscale) then
857 | TrinketMenuPerOptions.MainDock = "BOTTOMLEFT"
858 | TrinketMenuPerOptions.MenuDock = "BOTTOMRIGHT"
859 | end
860 | elseif near(main:GetRight() * mainscale,menu:GetRight() * menuscale) then
861 | if near(main:GetTop() * mainscale,menu:GetBottom() * menuscale) then
862 | TrinketMenuPerOptions.MainDock = "TOPRIGHT"
863 | TrinketMenuPerOptions.MenuDock = "BOTTOMRIGHT"
864 | elseif near(main:GetBottom() * mainscale,menu:GetTop() * menuscale) then
865 | TrinketMenuPerOptions.MainDock = "BOTTOMRIGHT"
866 | TrinketMenuPerOptions.MenuDock = "TOPRIGHT"
867 | end
868 | elseif near(main:GetLeft() * mainscale,menu:GetLeft() * menuscale) then
869 | if near(main:GetTop() * mainscale,menu:GetBottom() * menuscale) then
870 | TrinketMenuPerOptions.MainDock = "TOPLEFT"
871 | TrinketMenuPerOptions.MenuDock = "BOTTOMLEFT"
872 | elseif near(main:GetBottom() * mainscale,menu:GetTop() * menuscale) then
873 | TrinketMenuPerOptions.MainDock = "BOTTOMLEFT"
874 | TrinketMenuPerOptions.MenuDock = "TOPLEFT"
875 | end
876 | end
877 | TrinketMenu.ClearDocking()
878 | _G["TrinketMenu_MainDock_"..TrinketMenuPerOptions.MainDock]:Show()
879 | _G["TrinketMenu_MenuDock_"..TrinketMenuPerOptions.MenuDock]:Show()
880 | end
881 |
882 | function TrinketMenu.MenuMouseover()
883 | if (not MouseIsOver(TrinketMenu_MainFrame)) and (not MouseIsOver(TrinketMenu_MenuFrame)) and not IsShiftKeyDown() and (TrinketMenuOptions.KeepOpen == "OFF") then
884 | TrinketMenu.StopTimer("MenuMouseover")
885 | TrinketMenu_MenuFrame:Hide()
886 | end
887 | end
888 |
889 | --[[ Cooldowns ]]
890 |
891 | function TrinketMenu.UpdateWornCooldowns(maybeGlobal)
892 | local start, duration, enable = GetInventoryItemCooldown("player", 13)
893 | CooldownFrame_Set(TrinketMenu_Trinket0Cooldown, start, duration, enable)
894 | start, duration, enable = GetInventoryItemCooldown("player", 14)
895 | CooldownFrame_Set(TrinketMenu_Trinket1Cooldown, start, duration, enable)
896 | if not maybeGlobal then
897 | TrinketMenu.WriteWornCooldowns()
898 | end
899 | end
900 |
901 | function TrinketMenu.UpdateMenuCooldowns()
902 | local start, duration, enable
903 | for i = 1, TrinketMenu.NumberOfTrinkets do
904 | start,duration,enable = TrinketMenu.GetContainerItemCooldown(TrinketMenu.BaggedTrinkets[i].bag, TrinketMenu.BaggedTrinkets[i].slot)
905 | CooldownFrame_Set(_G["TrinketMenu_Menu"..i.."Cooldown"], start, duration, enable)
906 | end
907 | TrinketMenu.WriteMenuCooldowns()
908 | end
909 |
910 | --[[ Item use ]]
911 |
912 | function TrinketMenu.ReflectTrinketUse(slot)
913 | _G["TrinketMenu_Trinket"..(slot - 13)]:SetChecked(true)
914 | TrinketMenu.StartTimer("UpdateWornTrinkets")
915 | local _, _, id = string.find(GetInventoryItemLink("player", slot) or "", "item:(%d+)")
916 | if id then
917 | TrinketMenuPerOptions.ItemsUsed[id] = 0 -- 0 is an indeterminate state, cooldown will figure if it's worth watching
918 | end
919 | end
920 |
921 | function TrinketMenu.newUseInventoryItem(slot)
922 | if slot == 13 or slot == 14 and not MerchantFrame:IsVisible() then
923 | TrinketMenu.ReflectTrinketUse(slot)
924 | end
925 | end
926 |
927 | function TrinketMenu.newUseAction(slot)
928 | if IsEquippedAction(slot) then
929 | TrinketMenu_TooltipScan:SetOwner(WorldFrame, "ANCHOR_NONE")
930 | TrinketMenu_TooltipScan:SetAction(slot)
931 | local _, trinket0 = TrinketMenu.ItemInfo(13)
932 | local _, trinket1 = TrinketMenu.ItemInfo(14)
933 | if GameTooltipTextLeft1:GetText() == trinket0 then
934 | TrinketMenu.ReflectTrinketUse(13)
935 | elseif GameTooltipTextLeft1:GetText() == trinket1 then
936 | TrinketMenu.ReflectTrinketUse(14)
937 | end
938 | end
939 | end
940 |
941 | --[[ Tooltips ]]
942 |
943 | function TrinketMenu.WornTrinketTooltip(self)
944 | if TrinketMenuOptions.ShowTooltips == "OFF" then
945 | return
946 | end
947 | local id = self:GetID()
948 | TrinketMenu.TooltipOwner = self
949 | TrinketMenu.TooltipType = "INVENTORY"
950 | TrinketMenu.TooltipSlot = id
951 | TrinketMenu.TooltipBag = TrinketMenu.CombatQueue[id - 13]
952 | TrinketMenu.StartTimer("TooltipUpdate", 0)
953 | end
954 |
955 | function TrinketMenu.MenuTrinketTooltip(self)
956 | if TrinketMenuOptions.ShowTooltips == "OFF" then
957 | return
958 | end
959 | local id = self:GetID()
960 | TrinketMenu.TooltipOwner = self
961 | TrinketMenu.TooltipType = "BAG"
962 | TrinketMenu.TooltipBag = TrinketMenu.BaggedTrinkets[id].bag
963 | TrinketMenu.TooltipSlot = TrinketMenu.BaggedTrinkets[id].slot
964 | TrinketMenu.StartTimer("TooltipUpdate", 0)
965 | end
966 |
967 | function TrinketMenu.ClearTooltip()
968 | GameTooltip:Hide()
969 | TrinketMenu.StopTimer("TooltipUpdate")
970 | TrinketMenu.TooltipType = nil
971 | end
972 |
973 | function TrinketMenu.AnchorTooltip(self)
974 | if TrinketMenuOptions.TooltipFollow == "ON" then
975 | if self.GetLeft and self:GetLeft() and self:GetLeft() < 400 then
976 | GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
977 | else
978 | GameTooltip:SetOwner(self, "ANCHOR_LEFT")
979 | end
980 | else
981 | GameTooltip_SetDefaultAnchor(GameTooltip, self)
982 | end
983 | end
984 |
985 | -- updates the tooltip created in the functions above
986 | function TrinketMenu.TooltipUpdate()
987 | if TrinketMenu.TooltipType then
988 | local cooldown
989 | TrinketMenu.AnchorTooltip(TrinketMenu.TooltipOwner)
990 | if TrinketMenu.TooltipType == "BAG" then
991 | GameTooltip:SetBagItem(TrinketMenu.TooltipBag, TrinketMenu.TooltipSlot)
992 | cooldown = TrinketMenu.GetContainerItemCooldown(TrinketMenu.TooltipBag, TrinketMenu.TooltipSlot)
993 | else
994 | GameTooltip:SetInventoryItem("player", TrinketMenu.TooltipSlot)
995 | cooldown = GetInventoryItemCooldown("player", TrinketMenu.TooltipSlot)
996 | end
997 | TrinketMenu.ShrinkTooltip(TrinketMenu.TooltipOwner) -- if TinyTooltips on, shrink it
998 | if TrinketMenu.TooltipType == "INVENTORY" and TrinketMenu.TooltipBag then
999 | GameTooltip:AddLine("Queued: "..TrinketMenu.TooltipBag)
1000 | end
1001 | GameTooltip:Show()
1002 | if cooldown == 0 then
1003 | -- stop updates if this trinket has no cooldown
1004 | TrinketMenu.TooltipType = nil
1005 | TrinketMenu.StopTimer("TooltipUpdate")
1006 | end
1007 | end
1008 |
1009 | end
1010 |
1011 | -- normal tooltip for options
1012 | function TrinketMenu.OnTooltip(self, line1, line2)
1013 | if TrinketMenuOptions.ShowTooltips == "ON" then
1014 | TrinketMenu.AnchorTooltip(self)
1015 | if line1 then
1016 | GameTooltip:AddLine(line1)
1017 | GameTooltip:AddLine(line2, .8, .8, .8, 1)
1018 | GameTooltip:Show()
1019 | else
1020 | local name = self:GetName() or ""
1021 | for i = 1, #TrinketMenu.CheckOptInfo do
1022 | if name == "TrinketMenu_Opt"..TrinketMenu.CheckOptInfo[i][1] and TrinketMenu.CheckOptInfo[i][3] then
1023 | TrinketMenu.OnTooltip(self, TrinketMenu.CheckOptInfo[i][3], TrinketMenu.CheckOptInfo[i][4])
1024 | end
1025 | end
1026 | for i = 1, #TrinketMenu.TooltipInfo do
1027 | if TrinketMenu.TooltipInfo[i][1] == name and TrinketMenu.TooltipInfo[i][2] then
1028 | TrinketMenu.OnTooltip(self, TrinketMenu.TooltipInfo[i][2], TrinketMenu.TooltipInfo[i][3])
1029 | end
1030 | end
1031 | end
1032 | end
1033 | end
1034 |
1035 | -- strip format reordering in global strings
1036 | TrinketMenu.ITEM_SPELL_CHARGES = string.gsub(ITEM_SPELL_CHARGES, "%%%d%$d", "%%d")
1037 |
1038 | function TrinketMenu.ShrinkTooltip(owner)
1039 | if TrinketMenuOptions.TinyTooltips == "ON" then
1040 | local r, g, b = GameTooltipTextLeft1:GetTextColor()
1041 | local name = GameTooltipTextLeft1:GetText()
1042 | local line, cooldown, charge
1043 | for i = 2, GameTooltip:NumLines() do
1044 | line = _G["GameTooltipTextLeft"..i]
1045 | if line:IsVisible() then
1046 | line = line:GetText() or ""
1047 | if string.find(line, COOLDOWN_REMAINING) then
1048 | cooldown = line
1049 | end
1050 | if string.find(line, TrinketMenu.ITEM_SPELL_CHARGES) then
1051 | charge = line
1052 | end
1053 | end
1054 | end
1055 | TrinketMenu.AnchorTooltip(owner)
1056 | GameTooltip:AddLine(name, r, g, b)
1057 | GameTooltip:AddLine(charge, 1, 1, 1)
1058 | GameTooltip:AddLine(cooldown, 1, 1, 1)
1059 | end
1060 | end
1061 |
1062 | -- returns 1 if the item at bag(,slot) is an engineered trinket
1063 | function TrinketMenu.IsEngineered(bag, slot)
1064 | local item = slot and TrinketMenu.GetContainerItemLink(bag, slot) or GetInventoryItemLink("player", bag)
1065 | if item then
1066 | local _, _, _, _, _, itemType, itemSubtype, _, itemLoc = GetItemInfo(item)
1067 | if itemType == TrinketMenu.TRADE_GOODS and itemSubtype == TrinketMenu.DEVICES and itemLoc == "INVTYPE_TRINKET" then
1068 | return 1
1069 | end
1070 | TrinketMenu_TooltipScan:SetOwner(WorldFrame, "ANCHOR_NONE")
1071 | TrinketMenu_TooltipScan:SetHyperlink(item)
1072 | for i = 1, TrinketMenu_TooltipScan:NumLines() do
1073 | if string.match(_G["TrinketMenu_TooltipScanTextLeft"..i]:GetText() or "", TrinketMenu.REQUIRES_ENGINEERING) then
1074 | return 1
1075 | end
1076 | end
1077 | end
1078 | end
1079 |
1080 | -- returns bag,slot of a free bag space, if one found. engineering true if only looking for an engineering bag
1081 | function TrinketMenu.FindSpace(engineering)
1082 | local bagType
1083 | for i = 4, 0, -1 do
1084 | bagType = (select(7, GetItemInfo(GetInventoryItemLink("player", 19 + i) or "")))
1085 | if (engineering and bagType == TrinketMenu.ENGINEERING_BAG) or (not engineering and bagType == TrinketMenu.BAG) then
1086 | for j = 1, TrinketMenu.GetContainerNumSlots(i) do
1087 | if not TrinketMenu.GetContainerItemLink(i, j) then
1088 | return i, j
1089 | end
1090 | end
1091 | end
1092 | end
1093 | end
1094 |
1095 | --[[ Combat Queue ]]
1096 |
1097 | function TrinketMenu.EquipTrinketByName(name, slot)
1098 | if not name then
1099 | return
1100 | end
1101 | if UnitAffectingCombat("player") or TrinketMenu.IsPlayerReallyDead() or (IsRetail and C_PetBattles.IsInBattle() or false) then
1102 | -- queue trinket
1103 | local queue = TrinketMenu.CombatQueue
1104 | local which = slot - 13 -- 0 or 1
1105 | if queue[which] == name then
1106 | queue[which] = nil
1107 | elseif queue[1 - which] == name then
1108 | queue[1 - which] = nil
1109 | queue[which] = name
1110 | else
1111 | queue[which] = name
1112 | end
1113 | elseif not CursorHasItem() and not SpellIsTargeting() then
1114 | local _, b, s = TrinketMenu.FindItem(name)
1115 | if b then
1116 | if not TrinketMenu.GetContainerItemInfo(b, s).isLocked and not IsInventoryItemLocked(slot) then
1117 | -- neither container item nor inventory item locked, perform swap
1118 | local directSwap = true -- assume a direct swap will happen
1119 | if (select(7, GetItemInfo(GetInventoryItemLink("player", 19 + b) or ""))) == TrinketMenu.ENGINEERING_BAG then
1120 | -- incoming trinket is in an engineering bag
1121 | if not TrinketMenu.IsEngineered(slot) then
1122 | -- outgoing trinket can't go inside it
1123 | local freeBag,freeSlot = TrinketMenu.FindSpace()
1124 | if freeBag then
1125 | PickupInventoryItem(slot)
1126 | TrinketMenu.PickupContainerItem(freeBag, freeSlot)
1127 | TrinketMenu.PickupContainerItem(b, s)
1128 | EquipCursorItem(slot)
1129 | directSwap = nil
1130 | end
1131 | end
1132 | elseif TrinketMenu.IsEngineered(slot) and not TrinketMenu.IsEngineered(b, s) then
1133 | -- outgoing trinket is engineered, incoming trinket is not
1134 | local freeBag, freeSlot = TrinketMenu.FindSpace(1)
1135 | if freeBag then
1136 | -- move outgoing trinket to engineering bag, equip incoming trinket
1137 | PickupInventoryItem(slot)
1138 | TrinketMenu.PickupContainerItem(freeBag, freeSlot)
1139 | TrinketMenu.PickupContainerItem(b, s)
1140 | EquipCursorItem(slot)
1141 | directSwap = nil
1142 | end
1143 | end
1144 | if directSwap then
1145 | TrinketMenu.PickupContainerItem(b, s)
1146 | PickupInventoryItem(slot)
1147 | end
1148 | _G["TrinketMenu_Trinket"..(slot - 13).."Icon"]:SetDesaturated(true)
1149 | TrinketMenu.StartTimer("UpdateWornTrinkets") -- in case it's not equipped (stunned, etc)
1150 | end
1151 | end
1152 | end
1153 | TrinketMenu.UpdateCombatQueue()
1154 | end
1155 |
1156 | function TrinketMenu.UpdateCombatQueue()
1157 | local _, bag, slot
1158 | for which = 0, 1 do
1159 | local trinket = TrinketMenu.CombatQueue[which]
1160 | local icon = _G["TrinketMenu_Trinket"..which.."Queue"]
1161 | icon:Hide()
1162 | if trinket then
1163 | _, bag, slot = TrinketMenu.FindItem(trinket)
1164 | if bag then
1165 | icon:SetTexture(TrinketMenu.GetContainerItemInfo(bag, slot).iconFileID)
1166 | icon:Show()
1167 | end
1168 | elseif TrinketMenu.QueueInit and TrinketMenuQueue and TrinketMenuQueue.Enabled[which] then
1169 | icon:SetTexture("Interface\\AddOns\\TrinketMenu\\Textures\\TrinketMenu-Gear")
1170 | icon:Show()
1171 | end
1172 | end
1173 | end
1174 |
1175 | --[[ Notify ]]
1176 |
1177 | function TrinketMenu.Notify(msg)
1178 | PlaySound(4146)
1179 | if MikSBT then -- send via MSBT if it exists
1180 | MikSBT.DisplayMessage(msg, "Notification", true, 255, 0, 0, nil, nil, nil, nil)
1181 | elseif SCT_Display then -- send via SCT if it exists
1182 | SCT_Display(msg, {r = .2, g = .7, b = .9})
1183 | elseif Parrot then -- send via Parrot if it exists
1184 | Parrot:ShowMessage(msg, "Notification", true, 255, 0, 0, nil, nil, nil, nil)
1185 | elseif xCT then -- send via xCT if it exists
1186 | ct.frames[3]:AddMessage(msg, 255, 0, 0)
1187 | elseif xCT_Plus then -- send via xCT+ if it exists
1188 | xCT_Plus:AddMessage("general", msg, {1, 0, 0})
1189 | elseif SHOW_COMBAT_TEXT == "1" and CombatText_AddMessage then -- or default UI's SCT
1190 | CombatText_AddMessage(msg, CombatText_StandardScroll, .2, .7, .9)
1191 | else
1192 | -- send vis UIErrorsFrame if neither SCT exists
1193 | UIErrorsFrame:AddMessage(msg, .2, .7, .9, 1, UIERRORS_HOLD_TIME)
1194 | end
1195 | if TrinketMenuOptions.NotifyChatAlso == "ON" then
1196 | DEFAULT_CHAT_FRAME:AddMessage("|cff33b2e5"..msg)
1197 | end
1198 | end
1199 |
1200 | function TrinketMenu.CooldownUpdate()
1201 | local inv, bag, slot, start, duration, name, remain
1202 | for i in pairs(TrinketMenuPerOptions.ItemsUsed) do
1203 | start, duration = TrinketMenu.GetItemCooldown(i)
1204 | if start and TrinketMenuPerOptions.ItemsUsed[i] < 3 then
1205 | TrinketMenuPerOptions.ItemsUsed[i] = TrinketMenuPerOptions.ItemsUsed[i] + 1 -- count for 3 seconds before seeing if this is a real cooldown
1206 | elseif start then
1207 | if start > 0 then
1208 | remain = duration - (GetTime() - start)
1209 | if TrinketMenuPerOptions.ItemsUsed[i] < 5 then
1210 | if remain > 29 then
1211 | TrinketMenuPerOptions.ItemsUsed[i] = 30 -- first actual cooldown greater than 30 seconds, tag it for 30+0 notify
1212 | elseif remain > 5 then
1213 | TrinketMenuPerOptions.ItemsUsed[i] = 5 -- first actual cooldown less than 30 but greater than 5, tag for 0 notify
1214 | end
1215 | end
1216 | end
1217 | if TrinketMenuPerOptions.ItemsUsed[i] == 30 and start > 0 and remain < 30 then
1218 | if TrinketMenuOptions.NotifyThirty == "ON" then
1219 | name = GetItemInfo(i)
1220 | if name then
1221 | TrinketMenu.Notify(name.." ready soon!")
1222 | end
1223 | end
1224 | TrinketMenuPerOptions.ItemsUsed[i] = 5 -- tag for just 0 notify now
1225 | elseif TrinketMenuPerOptions.ItemsUsed[i] == 5 and start == 0 then
1226 | if TrinketMenuOptions.Notify == "ON" then
1227 | name = GetItemInfo(i)
1228 | if name then
1229 | TrinketMenu.Notify(name.." ready!")
1230 | end
1231 | end
1232 | end
1233 | if start == 0 then
1234 | TrinketMenuPerOptions.ItemsUsed[i] = nil
1235 | end
1236 | end
1237 | end
1238 | -- update cooldown numbers
1239 | if TrinketMenuOptions.CooldownCount == "ON" then
1240 | if TrinketMenu_MainFrame:IsVisible() then
1241 | TrinketMenu.WriteWornCooldowns()
1242 | end
1243 | if TrinketMenu_MenuFrame:IsVisible() then
1244 | TrinketMenu.WriteMenuCooldowns()
1245 | end
1246 | end
1247 | end
1248 |
1249 | function TrinketMenu.QueueUpdate()
1250 | if TrinketMenu.PeriodicQueueCheck then
1251 | TrinketMenu.PeriodicQueueCheck()
1252 | end
1253 | end
1254 |
1255 | function TrinketMenu.WriteWornCooldowns()
1256 | local start, duration
1257 | start, duration = GetInventoryItemCooldown("player", 13)
1258 | TrinketMenu.WriteCooldown(TrinketMenu_Trinket0Time, start, duration)
1259 | start, duration = GetInventoryItemCooldown("player", 14)
1260 | TrinketMenu.WriteCooldown(TrinketMenu_Trinket1Time, start, duration)
1261 | end
1262 |
1263 | function TrinketMenu.WriteMenuCooldowns()
1264 | local start, duration
1265 | for i = 1, TrinketMenu.NumberOfTrinkets do
1266 | start, duration = TrinketMenu.GetContainerItemCooldown(TrinketMenu.BaggedTrinkets[i].bag, TrinketMenu.BaggedTrinkets[i].slot)
1267 | TrinketMenu.WriteCooldown(_G["TrinketMenu_Menu"..i.."Time"], start, duration)
1268 | end
1269 | end
1270 |
1271 | function TrinketMenu.WriteCooldown(where, start, duration)
1272 | local cooldown = duration - (GetTime() - start)
1273 | if start == 0 or TrinketMenuOptions.CooldownCount == "OFF" then
1274 | where:SetText("")
1275 | elseif cooldown < 3 and not where:GetText() then
1276 | -- this is a global cooldown. don't display it. not accurate but at least not annoying
1277 | else
1278 | where:SetText((cooldown < 60 and math.floor(cooldown + .5).." s") or (cooldown < 3600 and math.ceil(cooldown / 60).." m") or math.ceil(cooldown / 3600).." h")
1279 | end
1280 | end
1281 |
1282 | function TrinketMenu.OnShow()
1283 | TrinketMenuPerOptions.Visible = "ON"
1284 | if TrinketMenuOptions.KeepOpen == "ON" then
1285 | TrinketMenu.BuildMenu()
1286 | end
1287 | end
1288 |
1289 | function TrinketMenu.OnHide()
1290 | TrinketMenu_MenuFrame:Hide()
1291 | TrinketMenuPerOptions.Visible = "OFF"
1292 | end
1293 |
1294 | function TrinketMenu.ReflectAlpha()
1295 | TrinketMenu_MainFrame:SetAlpha(TrinketMenuPerOptions.Alpha)
1296 | TrinketMenu_MenuFrame:SetAlpha(TrinketMenuPerOptions.Alpha)
1297 | end
1298 |
1299 | --[[ Key bindings ]]
1300 |
1301 | function TrinketMenu.KeyBindingsChanged()
1302 | if TrinketMenuOptions.ShowHotKeys == "ON" then
1303 | local key
1304 | for i = 0, 1 do
1305 | key = GetBindingKey("CLICK TrinketMenu_Trinket"..i..":LeftButton")
1306 | _G["TrinketMenu_Trinket"..i.."HotKey"]:SetText(GetBindingText(key or "", nil, 1))
1307 | end
1308 | else
1309 | TrinketMenu_Trinket0HotKey:SetText("")
1310 | TrinketMenu_Trinket1HotKey:SetText("")
1311 | end
1312 | end
1313 |
1314 | --[[ Monitor Range ]]
1315 |
1316 | --[[function TrinketMenu.ReflectRedRange()
1317 | if TrinketMenuOptions.RedRange == "ON" then
1318 | TrinketMenu.StartTimer("RedRange")
1319 | else
1320 | TrinketMenu.StopTimer("RedRange")
1321 | TrinketMenu_Trinket0Icon:SetVertexColor(1, 1, 1)
1322 | TrinketMenu_Trinket1Icon:SetVertexColor(1, 1, 1)
1323 | end
1324 | end
1325 |
1326 | function TrinketMenu.RedRangeUpdate()
1327 | local item
1328 | for i = 13, 14 do
1329 | item = GetInventoryItemLink("player", i)
1330 | if item and C_Item.IsItemInRange(item, "target") == 0 then
1331 | _G["TrinketMenu_Trinket"..(i - 13).."Icon"]:SetVertexColor(1, .3, .3)
1332 | else
1333 | _G["TrinketMenu_Trinket"..(i - 13).."Icon"]:SetVertexColor(1, 1, 1)
1334 | end
1335 | end
1336 | end]]
1337 |
--------------------------------------------------------------------------------