-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpellIconOverlay.lua
More file actions
285 lines (244 loc) · 9.48 KB
/
Copy pathSpellIconOverlay.lua
File metadata and controls
285 lines (244 loc) · 9.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
168
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
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
local folderName, addon = ...
-- SpellIconOverlay module
-- Adds overlay icon to spellbook spells included in single button assist
local rotationSpellsCache = nil
local isHooked = false
local eventFrame = CreateFrame("Frame")
local function UpdateRotationSpellsCache()
if C_AssistedCombat and C_AssistedCombat.GetRotationSpells then
local spells = C_AssistedCombat.GetRotationSpells()
rotationSpellsCache = {}
if spells then
for _, id in ipairs(spells) do
rotationSpellsCache[id] = true
end
end
else
rotationSpellsCache = false
end
end
local function IsSpellInRotation(spellID)
if rotationSpellsCache == nil then
UpdateRotationSpellsCache()
end
if rotationSpellsCache then
return rotationSpellsCache[spellID]
end
return false
end
-- Action Bar Overlay Logic
local actionBarButtonPrefixes = {
"ActionButton",
"MultiBarBottomLeftButton",
"MultiBarBottomRightButton",
"MultiBarRightButton",
"MultiBarLeftButton",
"MultiBar5Button",
"MultiBar6Button",
"MultiBar7Button",
}
local isActionSpellOnActionBar = false
local function UpdateActionBarButtonOverlay(button)
if not button then return end
-- No need to check for enabled state here, as the teardown unregisters all events leading to this function.
if not button.LudiusPlusOverlayFrame then
-- Create a frame to hold the overlay so we can control strata/level
-- Set to MEDIUM strata, level 100 to appear above AssistedCombatHighlightFrame (MEDIUM, level 99)
button.LudiusPlusOverlayFrame = CreateFrame("Frame", nil, button)
button.LudiusPlusOverlayFrame:SetFrameStrata("MEDIUM")
button.LudiusPlusOverlayFrame:SetFrameLevel(100)
button.LudiusPlusOverlayFrame:SetSize(16, 16)
-- Create the icon texture on the frame
button.LudiusPlusOverlay = button.LudiusPlusOverlayFrame:CreateTexture(nil, "OVERLAY", nil, 7)
button.LudiusPlusOverlay:SetAtlas("UI-RefreshButton")
-- Rotate 90 degrees counter-clockwise
button.LudiusPlusOverlay:SetRotation(math.rad(90))
button.LudiusPlusOverlay:SetAllPoints(button.LudiusPlusOverlayFrame)
-- Shadow
button.LudiusPlusShadow = button.LudiusPlusOverlayFrame:CreateTexture(nil, "OVERLAY", nil, 6)
button.LudiusPlusShadow:SetAtlas("Garr_BuildingShadowOverlay")
button.LudiusPlusShadow:SetAlpha(0.7)
button.LudiusPlusShadow:SetSize(25, 25)
button.LudiusPlusShadow:SetPoint("CENTER", button.LudiusPlusOverlay, "CENTER", 0, 0)
end
-- Update position (always, to handle position changes)
local position = (LP_config and LP_config.spellIconOverlay_actionBarPosition) or "BOTTOMLEFT"
button.LudiusPlusOverlayFrame:ClearAllPoints()
button.LudiusPlusOverlayFrame:SetPoint(position, button, position, 0, 0)
local showOverlay = false
if LP_config and LP_config.spellIconOverlay_showOnActionBars then
if not LP_config.spellIconOverlay_onlyWhenAssistUsed or isActionSpellOnActionBar then
local action = button.action
if action then
local type, id = GetActionInfo(action)
if type == "spell" and id then
-- Check if it is the single button assist spell itself, because we don't want the overlay for that one.
if not (button.AssistedCombatRotationFrame and button.AssistedCombatRotationFrame:IsShown()) then
if IsSpellInRotation(id) then
showOverlay = true
end
end
end
end
end
end
button.LudiusPlusOverlayFrame:SetShown(showOverlay)
end
local function CheckIfActionSpellIsOnActionBar()
isActionSpellOnActionBar = false
for _, prefix in ipairs(actionBarButtonPrefixes) do
for i = 1, 12 do
local button = _G[prefix .. i]
if button then
if button.AssistedCombatRotationFrame and button.AssistedCombatRotationFrame:IsShown() then
isActionSpellOnActionBar = true
return
end
end
end
end
end
local function UpdateAllActionBarOverlays()
CheckIfActionSpellIsOnActionBar()
for _, prefix in ipairs(actionBarButtonPrefixes) do
for i = 1, 12 do
local button = _G[prefix .. i]
if button then
UpdateActionBarButtonOverlay(button)
end
end
end
end
local function UpdateSpellbookOverlay(button)
if not button.Button then return end
-- If disabled but already hooked due to previous enablement, ensure hidden and return early to avoid creating textures
if not (LP_config and LP_config.spellIconOverlay_showInSpellbook) then
if button.Button.LudiusPlusOverlay then
button.Button.LudiusPlusOverlay:Hide()
if button.Button.LudiusPlusShadow then
button.Button.LudiusPlusShadow:Hide()
end
end
return
end
if not button.Button.LudiusPlusOverlay then
button.Button.LudiusPlusOverlay = button.Button:CreateTexture(nil, "OVERLAY", nil, 7)
button.Button.LudiusPlusOverlay:SetAtlas("UI-RefreshButton")
-- Rotate 90 degrees counter-clockwise
button.Button.LudiusPlusOverlay:SetRotation(math.rad(90))
button.Button.LudiusPlusOverlay:SetSize(16, 16)
-- Shadow
button.Button.LudiusPlusShadow = button.Button:CreateTexture(nil, "OVERLAY", nil, 6)
button.Button.LudiusPlusShadow:SetAtlas("Garr_BuildingShadowOverlay")
button.Button.LudiusPlusShadow:SetAlpha(0.7)
button.Button.LudiusPlusShadow:SetSize(25, 25)
button.Button.LudiusPlusShadow:SetPoint("CENTER", button.Button.LudiusPlusOverlay, "CENTER", 0, 0)
end
-- Update position (always, to handle position changes)
local position = (LP_config and LP_config.spellIconOverlay_spellbookPosition) or "BOTTOMLEFT"
button.Button.LudiusPlusOverlay:ClearAllPoints()
button.Button.LudiusPlusOverlay:SetPoint(position, button.Button, position, 0, 0)
local showOverlay = false
if button.spellBookItemInfo then
local spellID = button.spellBookItemInfo.spellID
if spellID then
-- Try API first
if IsSpellInRotation(spellID) then
showOverlay = true
end
end
end
button.Button.LudiusPlusOverlay:SetShown(showOverlay)
if button.Button.LudiusPlusShadow then
button.Button.LudiusPlusShadow:SetShown(showOverlay)
end
end
local function EventFrameScript(self, event, ...)
if event == "ADDON_LOADED" then
local addonName = ...
if addonName == "LudiusPlus" then
addon.SetupOrTeardownSpellIconOverlay()
elseif addonName == "Blizzard_PlayerSpells" then
if SpellBookItemMixin and not isHooked then
hooksecurefunc(SpellBookItemMixin, "UpdateSpellData", function(self)
UpdateSpellbookOverlay(self)
end)
isHooked = true
end
end
if isHooked and C_AddOns.IsAddOnLoaded("LudiusPlus") then
self:UnregisterEvent("ADDON_LOADED")
end
elseif event == "SPELLS_CHANGED" then
UpdateRotationSpellsCache()
UpdateAllActionBarOverlays()
elseif event == "ACTIONBAR_SLOT_CHANGED" or event == "ACTIONBAR_PAGE_CHANGED" or event == "UPDATE_BONUS_ACTIONBAR" or event == "PLAYER_ENTERING_WORLD" then
UpdateAllActionBarOverlays()
end
end
local function SetupSpellIconOverlay()
-- Register event handlers.
eventFrame:RegisterEvent("SPELLS_CHANGED")
eventFrame:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
eventFrame:RegisterEvent("ACTIONBAR_PAGE_CHANGED")
eventFrame:RegisterEvent("UPDATE_BONUS_ACTIONBAR")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:SetScript("OnEvent", EventFrameScript)
-- Hook into SpellBookItemMixin (can only be done once)
if not isHooked then
if C_AddOns.IsAddOnLoaded("Blizzard_PlayerSpells") then
if SpellBookItemMixin then
hooksecurefunc(SpellBookItemMixin, "UpdateSpellData", function(self)
UpdateSpellbookOverlay(self)
end)
isHooked = true
end
else
-- If the module is activated via options when LudiusPlus hasis already loaded, the ADDON_LOADED event is no longer registered.
-- So we need to listen for Blizzard_PlayerSpells loading.
eventFrame:RegisterEvent("ADDON_LOADED")
end
end
-- Initial update
UpdateAllActionBarOverlays()
end
local function TeardownSpellIconOverlay()
-- Unregister events
eventFrame:UnregisterEvent("SPELLS_CHANGED")
eventFrame:UnregisterEvent("ACTIONBAR_SLOT_CHANGED")
eventFrame:UnregisterEvent("ACTIONBAR_PAGE_CHANGED")
eventFrame:UnregisterEvent("UPDATE_BONUS_ACTIONBAR")
eventFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:UnregisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", nil)
-- Hide overlays on action bars
for _, prefix in ipairs(actionBarButtonPrefixes) do
for i = 1, 12 do
local button = _G[prefix .. i]
if button and button.LudiusPlusOverlayFrame then
button.LudiusPlusOverlayFrame:Hide()
end
end
end
end
function addon.SetupOrTeardownSpellIconOverlay()
if LP_config and (LP_config.spellIconOverlay_showInSpellbook or LP_config.spellIconOverlay_showOnActionBars) then
SetupSpellIconOverlay()
else
TeardownSpellIconOverlay()
end
end
function addon.RefreshSpellIconOverlayPositions()
-- Refresh action bar overlays
UpdateAllActionBarOverlays()
-- Refresh spellbook overlays by triggering SpellBookFrame update if it's open
if SpellBookFrame and SpellBookFrame:IsShown() then
-- Force spellbook buttons to update
if SpellBookFrame.UpdateSpells then
SpellBookFrame:UpdateSpells()
end
end
end
-- Initialize when addon loads
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", EventFrameScript)