-
Notifications
You must be signed in to change notification settings - Fork 17
/
GridStatusLoad.lua
405 lines (359 loc) · 11.8 KB
/
GridStatusLoad.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
394
395
396
397
398
399
400
401
402
403
404
405
-- Statuses Load filter management, by MiCHaEL
local Grid2 = Grid2
local Grid2Frame = Grid2Frame
local next = next
local pairs = pairs
local rawget = rawget
local UnitClass = UnitClass
local UnitExists = UnitExists
local UnitIsFriend = UnitIsFriend
local GetInstanceInfo = GetInstanceInfo
local GetSpellCooldown = Grid2.API.GetSpellCooldown
local UnitGroupRolesAssigned = Grid2.UnitGroupRolesAssigned
local roster_types = Grid2.roster_types
local roster_deads = Grid2.roster_deads
local empty = {}
-------------------------------------------------------------------------
-- Register/Unregister filtered statuses
-------------------------------------------------------------------------
local statuses = { combat = {}, playerClassSpec = {}, groupInstType = {}, instNameID = {}, unitFilter = {}, unitRole = {}, unitAlive = {}, cooldown = {} }
local function RegisterMsgFilter(status, filterType, message, func, enabled)
local registered = statuses[filterType]
if not enabled ~= not registered[status] then
if enabled then
if not next(registered) then Grid2.RegisterMessage(statuses, message, func) end
registered[status] = enabled
else
registered[status] = nil
if not next(registered) then Grid2.UnregisterMessage(statuses, message) end
end
end
end
local function RegisterEventFilter(status, filterType, event, func, enabled)
local registered = statuses[filterType]
if not enabled ~= not registered[status] then
if enabled then
if not next(registered) then Grid2:RegisterEvent(event, func) end
registered[status] = enabled
else
registered[status] = nil
if not next(registered) then Grid2:UnregisterEvent(event) end
end
end
end
-------------------------------------------------------------------------
-- General filters: class/spec/zone/group type
-- statuses are suspended&unregistered from indicators
-------------------------------------------------------------------------
local FilterG_Register, FilterG_Unregister, FilterG_Refresh
do
local indicators = {} -- indicators marked for update
local function RegisterIndicators(self)
local method = self.suspended and "UnregisterStatus" or "RegisterStatus"
for indicator, priority in pairs(self.priorities) do -- wakeup/suspend status from linked indicators
indicator[method](indicator, self, priority)
indicators[indicator] = true
end
end
local function UpdateMarkedIndicators()
for frame, unit in next, Grid2Frame.activatedFrames do
for indicator in next, indicators do
indicator:Update(frame, unit)
end
end
wipe(indicators)
end
local function CheckZoneFilter(filter)
local instanceName,_,_,_,_,_,_,instanceID = GetInstanceInfo()
return filter[instanceName] or filter[instanceID]
end
local function SuspendStatus(self, load)
local prev = self.suspended
if load then
self.suspended =
( load.disabled ) or
( load.playerClass and not load.playerClass[ Grid2.playerClass ] ) or
( load.playerClassSpec and not load.playerClassSpec[ Grid2.playerClassSpec ] ) or
( load.groupType and not load.groupType[ Grid2.groupType ] ) or
( load.instType and not load.instType[ Grid2.instType ] ) or
( load.instNameID and not CheckZoneFilter(load.instNameID) ) or nil
return self.suspended ~= prev
else
self.suspended = nil
return prev
end
end
local function RefreshStatuses(filterType)
local notify
for status, load in pairs(statuses[filterType]) do
if SuspendStatus(status, load) then
RegisterIndicators(status)
notify = true
end
end
UpdateMarkedIndicators()
if notify then
Grid2:SendMessage("Grid_StatusLoadChanged")
end
end
-- message events
local function GroupTypeEvent()
RefreshStatuses('groupInstType')
end
local function PlayerSpecEvent()
RefreshStatuses('playerClassSpec')
end
local function ZoneChangedEvent()
RefreshStatuses('instNameID')
end
-- public
function FilterG_Register(self, load)
RegisterMsgFilter( self, "instNameID", "Grid_ZoneChangedNewArea", ZoneChangedEvent, load and load.instNameID and load )
RegisterMsgFilter( self, "playerClassSpec", "Grid_PlayerSpecChanged", PlayerSpecEvent, load and load.playerClassSpec and load )
RegisterMsgFilter( self, "groupInstType", "Grid_GroupTypeChanged", GroupTypeEvent, load and (load.groupType or load.instType) and load )
return SuspendStatus(self, load)
end
function FilterG_Unregister(self)
RegisterMsgFilter( self, "instNameID", "Grid_ZoneChangedNewArea" )
RegisterMsgFilter( self, "playerClassSpec", "Grid_PlayerSpecChanged" )
RegisterMsgFilter( self, "groupInstType", "Grid_GroupTypeChanged" )
end
function FilterG_Refresh(self, load)
if FilterG_Register(self, load or empty) then
RegisterIndicators(self)
UpdateMarkedIndicators()
end
end
end
-------------------------------------------------------------------------
-- Unit filters: type/class/role/reaction
-- self.filtered[unit] check inside status:IsActive() method is necessary
-------------------------------------------------------------------------
local FilterU_Register, FilterU_Unregister, FilterU_Enable, FilterU_Disable, FilterU_Refresh
do
local function IsSpellInCooldown(spellID)
local start, duration = GetSpellCooldown(spellID)
if start~=0 then
local gcdStart, gcdDuration = GetSpellCooldown(61304)
return start ~= gcdStart or duration ~= gcdDuration
end
return false
end
local cooldowns_mt = { __index = function(t,spellID)
local r = IsSpellInCooldown(spellID)
t[spellID] = r
return r
end }
setmetatable(cooldowns_mt, cooldowns_mt)
local filter_mt = { __index = function(t,u)
if UnitExists(u) then
local load, r = t.source
if load.unitType then
r = not load.unitType[ roster_types[u] ]
end
if not r then
if load.unitRole then
r = not load.unitRole[ UnitGroupRolesAssigned(u) ]
end
if not r then
if load.unitClass then
local _,class = UnitClass(u)
r = not load.unitClass[class]
end
if not r then
if load.unitReaction then
r = not UnitIsFriend('player',u)
if load.unitReaction.hostile then r = not r end
end
if not r then
if load.unitAlive~=nil then
r = not roster_deads[u] == not load.unitAlive
end
if not r then
if load.cooldown then
r = cooldowns_mt[load.cooldown]
end
end
end
end
end
end
t[u] = r
return r
end
t[u] = true
return true
end }
local function ClearUnitFilters(_, unit)
for status, filtered in next, statuses.unitFilter do
filtered[unit] = nil
end
end
local function RefreshAliveFilter(_, unit)
for status, filtered in next, statuses.unitAlive do
filtered[unit] = nil
status:UpdateIndicators(unit)
end
end
local function RefreshRoleFilter()
for status, filtered in next, statuses.unitRole do
wipe(filtered).source = status.dbx.load
status:UpdateAllUnits()
end
end
local function RefreshCooldownFilter()
for status, filtered in next, statuses.cooldown do
local load = status.dbx.load
local spellID = load.cooldown
local cool = IsSpellInCooldown(spellID)
if cool ~= rawget( cooldowns_mt, spellID ) then
cooldowns_mt[spellID] = cool
wipe(filtered).source = load
for unit in next, status.idx do
status:UpdateIndicators(unit)
end
end
end
end
-- public
function FilterU_Register(self, load)
if load.unitType or load.unitReaction or load.unitClass or load.unitRole or load.cooldown or load.unitAlive~=nil then
self.filtered = setmetatable({source = load}, filter_mt)
else
self.filtered = nil
end
end
function FilterU_Unregister(self, load)
self.filtered = nil
end
function FilterU_Enable(self, load)
local filtered = self.filtered
if filtered then
RegisterMsgFilter( self, "unitFilter", "Grid_UnitUpdated", ClearUnitFilters, filtered )
RegisterMsgFilter( self, "unitAlive", "Grid_UnitDeadUpdated", RefreshAliveFilter, load.unitAlive~=nil and filtered )
RegisterMsgFilter( self, "unitRole", "Grid_PlayerRolesAssigned", RefreshRoleFilter, load.unitRole and filtered )
RegisterEventFilter( self, "cooldown", "SPELL_UPDATE_USABLE", RefreshCooldownFilter, load.cooldown and filtered )
end
end
function FilterU_Disable(self, load)
local filtered = self.filtered
if filtered then
RegisterMsgFilter( self, "unitFilter", "Grid_UnitUpdated" )
RegisterMsgFilter( self, "unitAlive", "Grid_UnitDeadUpdated" )
RegisterMsgFilter( self, "unitRole", "Grid_PlayerRolesAssigned" )
RegisterEventFilter( self, "cooldown", "SPELL_UPDATE_USABLE" )
wipe(filtered).source = load
end
end
function FilterU_Refresh(self, load)
FilterU_Disable(self, load)
FilterU_Register(self, load or empty)
self:UpdateDB()
if self.enabled then
FilterU_Enable(self, load or empty)
self:UpdateAllUnits()
end
end
end
-------------------------------------------------------------------------
-- Combat filter
-------------------------------------------------------------------------
local FilterC_Enable, FilterC_Disable, FilterC_Refresh
do
local statuses = statuses.combat
local IsNotActive = Grid2.Dummy
local frame, inCombat
local function CombatEvent(_,event)
inCombat = (event=='PLAYER_REGEN_DISABLED')
for status, load in next,statuses do
local IsActive = status._IsActive
local Update = status.UpdateIndicators
status.IsActive = load.combat == inCombat and IsActive or IsNotActive
for unit in Grid2:IterateGroupedPlayers() do
if IsActive(status,unit) then
Update(status,unit)
end
end
end
end
-- public
function FilterC_Enable(status, load)
if load.combat~=nil then
frame = frame or CreateFrame("Frame", nil, Grid2LayoutFrame)
if not next(statuses) then
frame:SetScript("OnEvent", CombatEvent)
frame:RegisterEvent("PLAYER_REGEN_ENABLED")
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
inCombat = not not InCombatLockdown()
end
statuses[status] = load
if status.IsActive~=IsNotActive then
status._IsActive = status.IsActive
end
if load.combat ~= inCombat then
status.IsActive = IsNotActive
end
end
end
function FilterC_Disable(status)
if statuses[status] then
statuses[status] = nil
if status._IsActive then
status.IsActive = status._IsActive
status._IsActive = nil
end
if not next(statuses) and frame then
frame:SetScript("OnEvent", nil)
frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
frame:UnregisterEvent("PLAYER_REGEN_DISABLED")
end
end
end
function FilterC_Refresh(status, load)
FilterC_Disable(status, load)
status:UpdateDB()
if status.enabled and load then
FilterC_Enable(status, load)
status:UpdateAllUnits()
end
end
end
-----------------------------------------------------------------------
-- status methods
-----------------------------------------------------------------------
local status = Grid2.statusPrototype
function status:RegisterLoad() -- called from Grid2:RegisterStatus() in GridStatus.lua
local load = self.dbx.load
if load then
FilterG_Register(self, load)
FilterU_Register(self, load)
end
end
function status:UnregisterLoad() -- called from Grid2:UnregisterStatus() in GridStatus.lua
local load = self.dbx.load
if load then
FilterG_Unregister(self, load)
FilterU_Unregister(self, load)
end
self.suspended = nil
end
function status:EnableLoad() -- called from status:RegisterIndicator() when the status is enabled
local load = self.dbx.load
if load then
FilterU_Enable(self, load)
FilterC_Enable(self, load)
end
end
function status:DisableLoad() -- called from status:UnregisterIndicator() when the status is disabled
local load = self.dbx.load
if load then
FilterU_Disable(self, load)
FilterC_Disable(self, load)
end
end
function status:RefreshLoad() -- used by Grid2Options
local load = self.dbx.load
FilterG_Refresh(self, load)
FilterU_Refresh(self, load)
FilterC_Refresh(self, load)
end