-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathBigWigs.lua
393 lines (338 loc) · 9.09 KB
/
BigWigs.lua
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
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
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
local _, FS = ...
local BW = FS:RegisterModule("BigWigs")
--------------------------------------------------------------------------------
-- Spell name and icon extractors
-- Taken from BigWigs
local spells = setmetatable({}, {__index =
function(self, key)
local value
if type(key) == "string" then
value = key
elseif key > 0 then
value = GetSpellInfo(key)
else
value = EJ_GetSectionInfo(-key)
end
self[key] = value
return value
end
})
local icons = setmetatable({}, {__index =
function(self, key)
local value
if type(key) == "number" then
if key > 0 then
value = GetSpellTexture(key)
if not value then
BW:Print(format("An invalid spell id (%d) is being used in a bar/message.", key))
end
else
local _, _, _, abilityIcon = EJ_GetSectionInfo(-key)
if abilityIcon and abilityIcon:trim():len() > 0 then
value = abilityIcon
else
value = false
end
end
elseif not key:find("\\") then
value = "Interface\\Icons\\" .. key
else
value = key
end
self[key] = value
return value
end
})
BW.spells = spells
BW.icons = icons
--------------------------------------------------------------------------------
-- Config infos
local bigwigs_default = {
profile = {
allow_remote = true
}
}
local bigwigs_config = {
title = {
type = "description",
name = "|cff64b4ffBigWigs Integration",
fontSize = "large",
order = 0,
},
desc = {
type = "description",
name = "Allows other modules to easily inject custom timers and alerts.\n",
fontSize = "medium",
order = 1,
},
--[[placholder = {
type = "description",
name = "|cff999999This module does not have any configuration option.",
order = 50
},]]
remote = {
type = "toggle",
name = "Allow remote activation",
desc = "Allow trusted raid members to remotely inject timers and alerts.",
width = "full",
get = function() return BW.settings.allow_remote end,
set = function(_, v) BW.settings.allow_remote = v end,
order = 6
},
ref = {
type = "header",
name = "Module reference",
order = 1000
},
api = FS.Config:MakeDoc("Public API", 2000, {
{":Message ( key , msg , color )", "Display a simple message."},
{":Emphasized ( key , msg , r , g , b )", "Display an emphasized message."},
{":Sound ( key , sound )", "Play the given sound."},
{":Say ( key , what , channel , target )", "Say the given message on the given channel. Defaults to SAY."},
{":Bar ( key , length , text , icon )", "Display a timer bar."},
{":StopBar ( key )", "Remove a bar created with :Bar()."},
{":Proximity ( key , range , player , isReverse )", "Open the proximity display."},
{":CloseProximity ( key )", "Close the proximity display."},
}, "FS.BigWigs")
}
--------------------------------------------------------------------------------
-- Interception
local intercepts = {}
local BW_SendMessage
local SendMessage_Hook
do
local function apply_hooks(self, hooks, i, msg, ...)
if msg == nil then
return false
elseif msg == false then
return true
else
local hook = hooks[i]
if not hook then
BW_SendMessage(self, msg, ...)
elseif not apply_hooks(self, hooks, i + 1, hook(msg, ...)) then
apply_hooks(self, hooks, i + 1, msg, ...)
end
return true
end
end
local NO_HOOKS = {}
function SendMessage_Hook(self, msg, ...)
local hooks = intercepts[msg] or NO_HOOKS
apply_hooks(self, hooks, 1, msg, ...)
end
end
function BW:Intercept(msg, filter)
local hooks = intercepts[msg]
if not hooks then
hooks = {}
intercepts[msg] = hooks
end
table.insert(hooks, filter)
end
function BW:ClearIntercepts()
wipe(intercepts)
end
--------------------------------------------------------------------------------
-- Module initialization
function BW:OnInitialize()
self.db = FS.db:RegisterNamespace("BigWigs", bigwigs_default)
self.settings = self.db.profile
FS:GetModule("Config"):Register("BigWigs", bigwigs_config)
end
function BW:OnEnable()
-- Force BigWigs loading
C_Timer.After(0, function()
LoadAddOn("BigWigs_Core")
if BigWigs then
BW_SendMessage = BigWigs.SendMessage
BigWigs.SendMessage = SendMessage_Hook
BigWigsLoader.SendMessage = SendMessage_Hook
BigWigs:Enable()
BigWigsLoader.RegisterMessage({}, "BigWigs_CoreDisabled", function(...)
BigWigs:Enable()
end)
else
BW:Disable()
end
end)
self:RegisterMessage("FS_MSG_BIGWIGS")
self:RegisterEvent("ENCOUNTER_END")
end
function BW:ENCOUNTER_END()
self:CancelAllActions()
self:CloseProximity()
self:ClearIntercepts()
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_StopBars", nil)
end
--------------------------------------------------------------------------------
-- Action Scheduler
do
local actions = {}
local once = {}
function BW:ScheduleAction(key, delay, fn, ...)
-- Default value for action key
if not key then
key = "none"
end
-- The action timer
local timer
local args = { ... }
timer = C_Timer.NewTimer(delay, function()
once[key] = nil
actions[timer] = nil
fn(unpack(args))
end)
-- Register the timer
actions[timer] = key
return timer
end
function BW:ScheduleActionOnce(key, delay, fn, ...)
local action = once[key]
if not action then
action = self:ScheduleAction(key, delay, fn, ...)
once[key] = action
end
return action
end
function BW:CancelActions(key)
if key.Cancel then
key:Cancel()
local action_key = actions[key]
once[action_key] = nil
return
end
-- Timer to cancel
local canceling
once[key] = nil
-- Search for timer with matching key
for timer, akey in pairs(actions) do
if akey == key then
if not canceling then canceling = {} end
table.insert(canceling, timer)
end
end
-- No timer found
if not canceling then return end
-- Timer to cancel
for _, timer in ipairs(canceling) do
timer:Cancel()
actions[timer] = nil
end
end
BW.CancelAction = BW.CancelActions
function BW:CancelAllActions()
for timer, _ in pairs(actions) do
timer:Cancel()
end
wipe(actions)
wipe(once)
end
end
--------------------------------------------------------------------------------
-- BigWigs bindings
function BW:Message(key, msg, color, icon, sound)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_Message", nil, key, msg, color, icon and icons[icon])
if sound then self:Sound(key, sound) end
end
function BW:Emphasized(key, msg, r, g, b, sound)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_EmphasizedMessage", msg, r, g, b)
if sound then self:Sound(key, sound) end
end
-- Long, Info, Alert, Alarm, Warning
function BW:Sound(key, sound)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_Sound", nil, key, sound)
end
function BW:Say(key, what, channel, target)
SendChatMessage(what, channel or "SAY", nil, target)
end
function BW:Flash(key)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_Flash", nil, key)
end
function BW:Pulse(key, icon)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_Pulse", nil, key, icons[icon or key])
end
-- Bars
do
local bar_text = {}
function BW:Bar(key, length, text, icon)
if not BigWigs then return end
-- Determine bar text
local textType = type(text)
local text = textType == "string" and text or spells[text or key]
-- Create BW bar
BigWigs:SendMessage("BigWigs_StartBar", nil, key, text, length, icons[icon or textType == "number" and text or key])
-- Save the text for canceling
bar_text[key] = text
self:ScheduleAction(key, length, function()
bar_text[key] = nil
end)
end
function BW:StopBar(key)
if not BigWigs then return end
local text = bar_text[key] or key
BigWigs:SendMessage("BigWigs_StopBar", nil, type(text) == "number" and spells[text] or text)
end
end
-- Countdown
do
local function schedule_number(key, t, n)
if t - n > 0 then
BW:ScheduleAction(key, t - n, function()
BigWigs:SendMessage("BigWigs_PlayCountdownNumber", nil, n)
end)
end
end
function BW:Countdown(key, time)
if not BigWigs then return end
for i = 5, 1, -1 do
schedule_number(key, time, i)
end
end
end
-- Proximity
function BW:Proximity(key, range, player, isReverse)
if not BigWigs then return end
if type(key) == "number" then
BigWigs:SendMessage("BigWigs_ShowProximity", "fs", range, key, player, isReverse, spells[key], icons[key])
else
BigWigs:SendMessage("BigWigs_ShowProximity", "fs", range, nil, player, isReverse)
end
end
function BW:CloseProximity(key)
if not BigWigs then return end
BigWigs:SendMessage("BigWigs_HideProximity", "fs")
end
--------------------------------------------------------------------------------
-- Messaging API
do
local function execute_action(action, ...)
if BW[action] then
BW[action](BW, ...)
end
end
local function schedule_action(action)
if action.delay then
BW:ScheduleAction(action[2], action.delay, execute_action, unpack(action))
else
execute_action(unpack(action))
end
end
function BW:FS_MSG_BIGWIGS(_, data, channel, sender)
if not self.settings.allow_remote then return end
if not FS:UnitIsTrusted(sender) or type(data) ~= "table" then return end
if type(data[1]) == "table" then
for i = 1, #data do
schedule_action(data[i])
end
else
schedule_action(data)
end
end
end