Nenue@6
|
1 --- Turok - Timer/Timer.lua
|
Nenue@6
|
2 -- @file-author@
|
Nenue@6
|
3 -- @project-revision@ @project-hash@
|
Nenue@6
|
4 -- @file-revision@ @file-hash@
|
Nenue@6
|
5 --- Defines common elements for the various timer HUDs
|
Nenue@6
|
6 local ADDON, _A = ...
|
Nenue@6
|
7 local _G, CreateFrame, tconcat, GetInventoryItemsForSlot, GetInventoryItemID = _G, CreateFrame, table.concat, GetInventoryItemsForSlot, GetInventoryItemID
|
Nenue@9
|
8 local T, F, tostring, type, max, tinsert, unpack, UIParent, loadstring, rawset = _A.Addon, _A.LibFog, tostring, type, max, table.insert, unpack, _G.UIParent, loadstring, rawset
|
Nenue@6
|
9 local mod = T.modules.TimerControl
|
Nenue@6
|
10 local P = mod.prototype
|
Nenue@6
|
11 local db
|
Nenue@6
|
12
|
Nenue@9
|
13 local pairs, ipairs, gsub, sub, setmetatable, wipe = pairs, ipairs, string.gsub, string.sub, setmetatable, wipe
|
Nenue@6
|
14 local INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2 =
|
Nenue@6
|
15 INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2
|
Nenue@6
|
16 --@debug@
|
Nenue@6
|
17 local DEBUG = true
|
Nenue@6
|
18 --@end-debug@
|
Nenue@6
|
19 local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
|
Nenue@6
|
20 local print = function(...)
|
Nenue@6
|
21 if not DEBUG then return end
|
Nenue@6
|
22 if _G.Devian and _G.DevianDB.workspace ~= 1 then
|
Nenue@6
|
23 _G.print('Timer', ...)
|
Nenue@6
|
24 end
|
Nenue@6
|
25 end
|
Nenue@9
|
26 local teprint = function(...)
|
Nenue@9
|
27 if not DEBUG then return end
|
Nenue@9
|
28 if _G.Devian and _G.DevianDB.workspace ~= 1 then
|
Nenue@9
|
29 _G.print('TimerEvent',...)
|
Nenue@9
|
30 end
|
Nenue@9
|
31 end
|
Nenue@9
|
32 local tfprint = function(...)
|
Nenue@9
|
33 if not DEBUG then return end
|
Nenue@9
|
34 if _G.Devian and _G.DevianDB.workspace ~= 1 then
|
Nenue@9
|
35 _G.print('TimerFocus',...)
|
Nenue@9
|
36 end
|
Nenue@9
|
37 end
|
Nenue@6
|
38
|
Nenue@6
|
39 local Timer_GetPrintHandler = function(self)
|
Nenue@6
|
40 if self.trace then
|
Nenue@6
|
41 return function(...)
|
Nenue@6
|
42 print(...)
|
Nenue@9
|
43 tfprint(...)
|
Nenue@6
|
44 end else
|
Nenue@6
|
45 return print
|
Nenue@6
|
46 end
|
Nenue@6
|
47 end
|
Nenue@6
|
48 local pb_suppressed = {}
|
Nenue@6
|
49
|
Nenue@6
|
50 function mod:OnInitialize()
|
Nenue@6
|
51
|
Nenue@6
|
52 --@debug@
|
Nenue@6
|
53 TurokData.spirit.timers = Turok.defaults.spirit.timers
|
Nenue@6
|
54 --@end-debug@
|
Nenue@6
|
55 self.db = TurokData.spirit
|
Nenue@6
|
56 db = self.db
|
Nenue@6
|
57 self.active_cooldowns = {}
|
Nenue@6
|
58 self.cast_units = {}
|
Nenue@6
|
59 self.buff_units = {}
|
Nenue@6
|
60 self.loaded_types = {}
|
Nenue@6
|
61 self.loaded_triggers = {}
|
Nenue@6
|
62 self.equipped = {}
|
Nenue@6
|
63 self.containers = {}
|
Nenue@6
|
64 self.timers = {} -- active timers
|
Nenue@6
|
65 self.empty_frames = {} -- foster table for frames released by talent change
|
Nenue@6
|
66
|
Nenue@6
|
67
|
Nenue@6
|
68 T:RegisterChatCommand("tsp", self.Import_Open)
|
Nenue@6
|
69 T:RegisterChatCommand("tka", self.Dialog_Command)
|
Nenue@6
|
70 T:RegisterChatCommand("tki", self.CreateIndex)
|
Nenue@6
|
71 --T:Print("/tsp to import spells. /tka to open create dialog")
|
Nenue@6
|
72 -- suppress cacophony from all cooldowns activating at login
|
Nenue@6
|
73 self.quiet = true
|
Nenue@6
|
74 --self:ScheduleTimer(function() self:Dialog_Command() end, 4)
|
Nenue@6
|
75
|
Nenue@6
|
76 end
|
Nenue@6
|
77
|
Nenue@6
|
78 local mt_single = {
|
Nenue@6
|
79 __mode = "v",
|
Nenue@6
|
80 __newindex = function(t,k,v)
|
Nenue@6
|
81 rawset(t,k,v)
|
Nenue@9
|
82 --_G.print('DB', 'TCMeta: adding leaf', k, '=', v)
|
Nenue@6
|
83 end}
|
Nenue@6
|
84 local mt_double = {
|
Nenue@6
|
85 __index = function(t,k)
|
Nenue@6
|
86 t[k] = setmetatable({}, mt_single)
|
Nenue@9
|
87 --_G.print('DB', 'TCMeta: add layer', k, '=', t[k])
|
Nenue@6
|
88 return t[k]
|
Nenue@6
|
89 end,
|
Nenue@6
|
90 __newindex = function(t,k,v)
|
Nenue@6
|
91 rawset(t,k,v)
|
Nenue@9
|
92 --_G.print('DB', 'TCMeta: adding to top layer', k, '=', v)
|
Nenue@6
|
93 end
|
Nenue@6
|
94 }
|
Nenue@6
|
95 local mt_error = {
|
Nenue@6
|
96 __call =function (t, txt)
|
Nenue@6
|
97 t.disable = true
|
Nenue@6
|
98 tinsert(t, txt)
|
Nenue@6
|
99 end
|
Nenue@6
|
100 }
|
Nenue@6
|
101
|
Nenue@6
|
102 --- Sets and cleans up index data used by event handlers
|
Nenue@6
|
103 local Timer_UpdateIndex = function(self, key)
|
Nenue@6
|
104
|
Nenue@6
|
105 -- Is there already an entry for this key/value?
|
Nenue@6
|
106 if self.frames[key] then
|
Nenue@6
|
107 local lim = #mod.frames[key]
|
Nenue@6
|
108 --[[
|
Nenue@6
|
109 for i = self.frames[key]+1, lim, 1 do
|
Nenue@6
|
110 mod.frames[key][i] = mod.frames[key+1]
|
Nenue@6
|
111 end]]
|
Nenue@6
|
112 --self.frames[key] = nil
|
Nenue@6
|
113 print(' ', cText('mod.frames.')..cWord(key), '=', #mod.frames[key])
|
Nenue@6
|
114 print(' ', cText('self.frames.')..cWord(key), '=', cNum(self.frames[key]))
|
Nenue@6
|
115 end
|
Nenue@6
|
116
|
Nenue@6
|
117 if key then
|
Nenue@6
|
118 local i = #mod.frames[key]+1
|
Nenue@6
|
119 --mod.frames[key][i] = self
|
Nenue@6
|
120 self.frames[key] = i
|
Nenue@6
|
121 print(' ', cText('self.frames.')..cWord(key), '=', #mod.frames[key])
|
Nenue@6
|
122 end
|
Nenue@6
|
123 mod.loaded_types[key] = (#mod.frames[key] == 0) and nil or true
|
Nenue@6
|
124 print(' ',cText(key..'_is_loaded'), '=', cBool(mod.loaded_types[key]))
|
Nenue@6
|
125 end
|
Nenue@6
|
126
|
Nenue@6
|
127 --- Loading initators
|
Nenue@6
|
128 function mod:OnEnable()
|
Nenue@6
|
129 mod.LoadPresets()
|
Nenue@6
|
130 mod.GetIndex()
|
Nenue@6
|
131 -- setup indexes, use nested weak table for status since they implicitly have a key variable
|
Nenue@6
|
132 mod.frames = {}
|
Nenue@6
|
133 for class, p in pairs(mod.prototype.status) do
|
Nenue@6
|
134 print('nested index table', class)
|
Nenue@6
|
135 mod.frames[class] = setmetatable({}, mt_double)
|
Nenue@6
|
136 end
|
Nenue@6
|
137 mod.frames.spellName = setmetatable({}, mt_double)
|
Nenue@6
|
138 for class, p in pairs(mod.prototype.display) do
|
Nenue@6
|
139 mod.frames[class] = setmetatable({}, mt_single)
|
Nenue@6
|
140 end
|
Nenue@6
|
141 for class, p in pairs(mod.prototype.trigger) do
|
Nenue@6
|
142 mod.frames[class] = setmetatable({}, mt_single)
|
Nenue@6
|
143 end
|
Nenue@6
|
144
|
Nenue@6
|
145 local srcIndex = mod.timers
|
Nenue@6
|
146 if T.playerClass and mod.index[T.playerClass] then
|
Nenue@6
|
147 srcIndex = mod.index[T.playerClass]
|
Nenue@6
|
148 print('*** Found index for '..tostring(T.playerClass)..', using that.')
|
Nenue@6
|
149 else
|
Nenue@6
|
150 print(cWord('*** Using global index.'))
|
Nenue@6
|
151 end
|
Nenue@6
|
152 mod.activeSpec = T.specID
|
Nenue@6
|
153
|
Nenue@6
|
154 --- go through that list
|
Nenue@6
|
155 for id, timer in pairs(srcIndex) do
|
Nenue@6
|
156 local result, message = mod:EnableTimer(id, timer)
|
Nenue@6
|
157 end
|
Nenue@6
|
158
|
Nenue@6
|
159 mod.InitTimers()
|
Nenue@6
|
160 --- Delay sound activations so there isn't a giant cacophony on load
|
Nenue@6
|
161 mod:ScheduleTimer(function()
|
Nenue@6
|
162 self.quiet = nil
|
Nenue@6
|
163 end, db.audio_delay or 2)
|
Nenue@6
|
164 end
|
Nenue@6
|
165
|
Nenue@6
|
166 function mod:EnableTimer(id, dvars)
|
Nenue@6
|
167 local print = Timer_GetPrintHandler(dvars)
|
Nenue@6
|
168 print('-{', cPink(dvars.name))
|
Nenue@6
|
169 if not dvars then
|
Nenue@6
|
170 if not mod.index.global[id] then
|
Nenue@6
|
171 return false, "Unable to resolve dvars table."
|
Nenue@6
|
172 end
|
Nenue@6
|
173 dvars = mod.index.global[id]
|
Nenue@6
|
174 end
|
Nenue@6
|
175 if dvars.virtual then
|
Nenue@6
|
176 return
|
Nenue@6
|
177 end
|
Nenue@6
|
178
|
Nenue@6
|
179 local spirit, newFrame = mod:GetTimer(id, dvars)
|
Nenue@6
|
180 if not spirit then return spirit, newFrame end
|
Nenue@6
|
181
|
Nenue@6
|
182 local cvars = spirit.cvars
|
Nenue@6
|
183 local dvars = spirit.dvars
|
Nenue@6
|
184 local trigger = P.trigger[cvars.type]
|
Nenue@6
|
185 local display = P.display[cvars.display]
|
Nenue@6
|
186 local cvars = spirit.cvars
|
Nenue@6
|
187 local index = mod.frames
|
Nenue@6
|
188 local print = Timer_GetPrintHandler(cvars)
|
Nenue@6
|
189
|
Nenue@6
|
190 if spirit.disable then
|
Nenue@6
|
191 return false, "Manually disabled." -- nothing to do, nothing to say
|
Nenue@6
|
192 end
|
Nenue@6
|
193
|
Nenue@6
|
194 --- Interpret STATUS vars
|
Nenue@6
|
195 print(cText(' *** Merging Status Data'))
|
Nenue@6
|
196 spirit.disable = dvars.disable
|
Nenue@6
|
197 local pcount = 1
|
Nenue@6
|
198 for k, handler in pairs(P.status) do
|
Nenue@6
|
199 if cvars[k] then
|
Nenue@6
|
200 if handler.Init then
|
Nenue@6
|
201 print(cWord(' * Firing ')..cKey(k)..cWord('.Init'), cNum(cvars[k]))
|
Nenue@6
|
202 handler.Init(spirit, cvars[k])
|
Nenue@6
|
203 else
|
Nenue@6
|
204 print(' ', cText('skipped'), cKey(k))
|
Nenue@6
|
205 end
|
Nenue@6
|
206 pcount = pcount + 1
|
Nenue@6
|
207 end
|
Nenue@6
|
208 end
|
Nenue@6
|
209
|
Nenue@6
|
210 spirit.Event = trigger.Event
|
Nenue@6
|
211 spirit.Value = trigger.Value
|
Nenue@6
|
212 spirit.SetText = mod.SetText
|
Nenue@6
|
213 spirit.LoadText = mod.LoadText
|
Nenue@6
|
214 spirit.Query = trigger.Query
|
Nenue@6
|
215 spirit.Set = trigger.Set
|
Nenue@6
|
216
|
Nenue@6
|
217 --- Display handler init
|
Nenue@6
|
218 if display.Init then
|
Nenue@6
|
219 print(cText(' * Display Init:'), cKey(dvars.display))
|
Nenue@6
|
220 display.Init(spirit)
|
Nenue@6
|
221 end
|
Nenue@6
|
222
|
Nenue@6
|
223 --- Trigger handler and events Load()
|
Nenue@6
|
224 print(cText(' * Trigger Init:'), cKey(dvars.type))
|
Nenue@6
|
225 trigger.Init(spirit)
|
Nenue@6
|
226
|
Nenue@6
|
227
|
Nenue@6
|
228 if C_PetBattles.IsInBattle() then
|
Nenue@6
|
229 spirit.disable = true
|
Nenue@6
|
230 spirit.debug_info("Hidden for pet battle")
|
Nenue@6
|
231 pb_suppressed[id] = true
|
Nenue@6
|
232 end
|
Nenue@6
|
233
|
Nenue@6
|
234
|
Nenue@6
|
235 if spirit.disable then
|
Nenue@6
|
236 spirit:UnregisterAllEvents()
|
Nenue@6
|
237 spirit.displayState = nil
|
Nenue@6
|
238 spirit.prevState = nil
|
Nenue@6
|
239 spirit:Hide()
|
Nenue@6
|
240 return false, tconcat(spirit.debug_info,"\n")
|
Nenue@6
|
241 else
|
Nenue@6
|
242 print('--', self.disable and cPink('DISABLED') or cNum('ENABLED'), #spirit.debug_info > 0 and tconcat(spirit.debug_info,"\n"), '}')
|
Nenue@6
|
243 return true, tconcat(spirit.debug_info,"\n")
|
Nenue@6
|
244 end
|
Nenue@6
|
245 end
|
Nenue@6
|
246
|
Nenue@6
|
247 function mod:GetTimer(id, dvars)
|
Nenue@6
|
248 local print = Timer_GetPrintHandler(dvars)
|
Nenue@6
|
249 local newFrame
|
Nenue@6
|
250 if not mod.timers[id] then
|
Nenue@6
|
251 print(cKey(' [[CreateTimer'))
|
Nenue@6
|
252 newFrame = true
|
Nenue@6
|
253 --- Compile the cvar table from the various config layers:
|
Nenue@6
|
254 -- Start with timer dvars, overwritten by any container settings, then a disable check, then merge in prototype values
|
Nenue@6
|
255 local cvars = T.Config_Push({}, dvars, nil, cKey('['..id..']')..'.'..cWord('cvars'))
|
Nenue@6
|
256 cvars.name = dvars.name -- push function ignores name keys
|
Nenue@6
|
257
|
Nenue@6
|
258 if dvars.container and db.containers[dvars.container] then
|
Nenue@6
|
259 print(cText(' * Merging Container overrides'))
|
Nenue@6
|
260 T.Config_Push(cvars, db.containers[dvars.container], cvars, cKey('['..id..']')..'.'..cWord('cvars'))
|
Nenue@6
|
261 end
|
Nenue@6
|
262
|
Nenue@6
|
263 --- Stop here if disabled via SavedVars
|
Nenue@6
|
264 if cvars.disable then
|
Nenue@6
|
265 return false, "Manually disabled"
|
Nenue@6
|
266 end
|
Nenue@6
|
267
|
Nenue@6
|
268 --- Localize the stuff we are going to loop over
|
Nenue@6
|
269 local display = P.display[cvars.display]
|
Nenue@6
|
270 local trigger = P.trigger[cvars.type]
|
Nenue@6
|
271 local displayType = cvars.display
|
Nenue@6
|
272 local triggerType = cvars.type
|
Nenue@6
|
273 if not (display and trigger) then
|
Nenue@6
|
274 return nil, "Missing prototype data. Summary: "..tostring(displayType).."="..(display and 'OK' or 'MISSING') ..
|
Nenue@6
|
275 " "..tostring(triggerType).."="..(trigger and 'OK' or 'MISSING')
|
Nenue@6
|
276 end
|
Nenue@6
|
277
|
Nenue@6
|
278 --- Establish the order in which values are merged
|
Nenue@6
|
279 print(cText(' * Merging object CVars'))
|
Nenue@6
|
280 local cvar_class = {cWord('db.'..displayType), cWord('db.'..triggerType), cWord('db.global')}
|
Nenue@6
|
281 local cvar_array = {
|
Nenue@6
|
282 db[displayType],
|
Nenue@6
|
283 db[triggerType],
|
Nenue@6
|
284 db.global,
|
Nenue@6
|
285 }
|
Nenue@6
|
286 local override_class = {cWord('trigger.'..cvars.type), cWord('display.'.. cvars.display)}
|
Nenue@6
|
287 local override_array = {
|
Nenue@6
|
288 display.cvars,
|
Nenue@6
|
289 trigger.cvars }
|
Nenue@6
|
290
|
Nenue@6
|
291 --- Table merge user settings
|
Nenue@6
|
292 for i, p in pairs(cvar_array) do
|
Nenue@6
|
293 print(' '..cNum(i)..' merge ['..cvar_class[i]..']')
|
Nenue@6
|
294 T.Config_Merge(cvars, p, cvars, cKey('['..id..']')..'.'..cWord('cvars'))
|
Nenue@6
|
295 end
|
Nenue@6
|
296
|
Nenue@6
|
297 --- Overwrite with anything defined by the prototype structure because it's important
|
Nenue@6
|
298 local _, odiff
|
Nenue@6
|
299 for i, p in ipairs(override_array) do
|
Nenue@6
|
300 _, odiff = T.Config_Push(cvars, p, cvars, cKey('['..id..']')..'.'..cWord('cvars'))
|
Nenue@6
|
301 end
|
Nenue@6
|
302 local print = Timer_GetPrintHandler(cvars)
|
Nenue@6
|
303
|
Nenue@6
|
304 --- Create the UI frame and seed it with the data we just composed
|
Nenue@6
|
305 local spirit = CreateFrame('Frame', 'TurokTimerFrame'..gsub(dvars.name, "[^%a%d]", ''), UIParent, display.inherits)
|
Nenue@6
|
306 spirit.trace = cvars.trace
|
Nenue@6
|
307 spirit.timerID = id
|
Nenue@6
|
308 spirit.timerName = dvars.name
|
Nenue@6
|
309 spirit.container = dvars.container
|
Nenue@6
|
310 spirit.cvars = cvars
|
Nenue@6
|
311 spirit.dvars = dvars
|
Nenue@6
|
312 spirit.Update = display.Update
|
Nenue@6
|
313 spirit.SetState = display.SetState
|
Nenue@6
|
314 spirit.Report = mod.Report
|
Nenue@6
|
315 spirit.Stats = trigger.Stats
|
Nenue@6
|
316
|
Nenue@6
|
317 --- Set Layout Statics
|
Nenue@6
|
318 T.SetFrameLayout(spirit, cvars)
|
Nenue@6
|
319
|
Nenue@6
|
320 --- Create troubleshooting collection
|
Nenue@6
|
321 spirit.debug_info = setmetatable({}, mt_error)
|
Nenue@6
|
322
|
Nenue@6
|
323 --- Add the frame to corresponding prototype indexes
|
Nenue@6
|
324 spirit.frames = {}
|
Nenue@6
|
325 spirit.events = {}
|
Nenue@6
|
326
|
Nenue@6
|
327 if spirit.display ~= displayType then
|
Nenue@6
|
328 spirit.display = displayType
|
Nenue@6
|
329 Timer_UpdateIndex(spirit, displayType)
|
Nenue@6
|
330 end
|
Nenue@6
|
331 if spirit.type ~= triggerType then
|
Nenue@6
|
332 spirit.type = triggerType
|
Nenue@6
|
333 Timer_UpdateIndex(spirit, triggerType)
|
Nenue@6
|
334 end
|
Nenue@6
|
335 --- Add the frame to global index
|
Nenue@6
|
336 mod.timers[id] = spirit
|
Nenue@6
|
337 end
|
Nenue@6
|
338
|
Nenue@6
|
339 return mod.timers[id], newFrame
|
Nenue@6
|
340 end
|
Nenue@6
|
341
|
Nenue@6
|
342 function mod.InitTimers()
|
Nenue@9
|
343 teprint('INIT TIMERS ====================')
|
Nenue@6
|
344 for id, spirit in pairs(mod.timers) do
|
Nenue@6
|
345 if spirit.disable then
|
Nenue@9
|
346 teprint(id, 'disabled:', tconcat(spirit.debug_info or {}, ', '))
|
Nenue@6
|
347 else
|
Nenue@6
|
348
|
Nenue@9
|
349 teprint(cText('init'), cNum(id), cWord(spirit.name))
|
Nenue@6
|
350 --- Throw a dry event to initialize values
|
Nenue@9
|
351 teprint(cText(' *'), cWord('prototype.'..cKey(spirit.dvars.type)..'.'..cWord('Load')))
|
Nenue@6
|
352 P.trigger[spirit.dvars.type].Event(spirit)
|
Nenue@6
|
353
|
Nenue@6
|
354 --- Set loose
|
Nenue@9
|
355 teprint(cText(' *'), cWord('prototype')..'.'..cKey('events')..'.'..cWord('Load'))
|
Nenue@6
|
356 mod.UpdateEvents(spirit, P.trigger[spirit.dvars.type].events)
|
Nenue@6
|
357 end
|
Nenue@6
|
358 end
|
Nenue@9
|
359 teprint('INIT DONE =========================')
|
Nenue@6
|
360 end
|
Nenue@6
|
361
|
Nenue@6
|
362 function mod:DisableTimer(name, timer)
|
Nenue@6
|
363 local timer_frame = mod.db.timers[name]
|
Nenue@6
|
364 if timer_frame and not timer_frame.disable then
|
Nenue@6
|
365 timer_frame.disable = true
|
Nenue@6
|
366 timer_frame:UnregisterAllEvents()
|
Nenue@6
|
367 timer_frame:Hide()
|
Nenue@6
|
368 end
|
Nenue@6
|
369 end
|
Nenue@6
|
370
|
Nenue@6
|
371 function mod.UpdateEvents(self, events)
|
Nenue@6
|
372 local print = Timer_GetPrintHandler(self)
|
Nenue@6
|
373
|
Nenue@6
|
374 self:SetScript('OnEvent', nil)
|
Nenue@6
|
375 self:UnregisterAllEvents()
|
Nenue@6
|
376
|
Nenue@6
|
377 local proxy, listen = {}, {}
|
Nenue@6
|
378 for event, handler in pairs(events) do
|
Nenue@6
|
379 if mod[event] then
|
Nenue@6
|
380 tinsert(proxy, cNum(event))
|
Nenue@6
|
381 else
|
Nenue@6
|
382 tinsert(listen, cWord(event))
|
Nenue@6
|
383 self:RegisterEvent(event)
|
Nenue@6
|
384 end
|
Nenue@6
|
385 self.events[event] = handler
|
Nenue@6
|
386 end
|
Nenue@6
|
387
|
Nenue@6
|
388 if #proxy > 0 then
|
Nenue@6
|
389 print( ' -', cKey(self.name), cWord('receiving'), tconcat(proxy, ', '))
|
Nenue@6
|
390 end
|
Nenue@6
|
391 if #listen > 0 then
|
Nenue@6
|
392 print( ' -', cKey(self.name), cText('listening'), tconcat(listen, ', '))
|
Nenue@6
|
393 end
|
Nenue@6
|
394
|
Nenue@6
|
395 self:SetScript('OnEvent', self.Event)
|
Nenue@6
|
396 end
|
Nenue@6
|
397
|
Nenue@6
|
398 local match_sub = {
|
Nenue@6
|
399 {'%%c', "' .. tostring(t.caster).. '"},
|
Nenue@6
|
400 {'%%h', "' .. tostring((t.valueFull >= 60) and (math.floor(t.valueFull/60)) or t.value) .. '"},
|
Nenue@9
|
401 {'%%i', "' .. tostring((t.valueFull >= 60) and (math.floor(t.valueFull/60) .. ':' .. ((t.value %% 60) < 10 and '0' or '').. (t.value %% 60)) or ((t.valueFull < 6) and (t.value .. '.' .. math.floor((t.valueFull * 10) %% 10)) or t.value)) .. '"},
|
Nenue@6
|
402 {'%%n', "' .. tostring(t.spellName) .. '"},
|
Nenue@6
|
403 {'%%p', "' .. tostring(t.value) .. '"},
|
Nenue@6
|
404 {'%%d', "' .. tostring(t.chargeDuration or t.duration) .. '"},
|
Nenue@6
|
405 {'%%%.p', "' .. string.sub(tostring((t.valueFull %% 1) * 100),0,1) .. '"},
|
Nenue@6
|
406 {"%%s", "' .. (t.stacks or t.charges or '') .. '"},
|
Nenue@6
|
407 }
|
Nenue@6
|
408
|
Nenue@6
|
409 -- dot syntax implies use as embedded method
|
Nenue@6
|
410 function mod.LoadText(self)
|
Nenue@6
|
411 print(cKey('parsing textRegions for'), self.timerName, self.timerID)
|
Nenue@6
|
412 self.textTypes = {}
|
Nenue@6
|
413 self.textValues = {}
|
Nenue@6
|
414 for name, region in pairs(self.textRegions) do
|
Nenue@6
|
415 print(' ', cWord('textRegions')..'["'.. cType(self.timerName)..'"].'..cType(name))
|
Nenue@6
|
416 if self.cvars[name..'Text'] then
|
Nenue@6
|
417
|
Nenue@6
|
418 -- todo: collect match counts and index the text fields by match types
|
Nenue@6
|
419 local str = self.cvars[name..'Text']
|
Nenue@6
|
420 for i, args in ipairs(match_sub) do
|
Nenue@6
|
421 if str:match(args[1]) then
|
Nenue@6
|
422 if not self.textTypes[args[1]] then
|
Nenue@6
|
423 self.textTypes[args[1]] = {}
|
Nenue@6
|
424 end
|
Nenue@6
|
425 tinsert(self.textTypes[args[1]], region)
|
Nenue@6
|
426 str = str:gsub(args[1], args[2])
|
Nenue@6
|
427 end
|
Nenue@6
|
428 end
|
Nenue@6
|
429 str = "local t = _G.Turok.modules.TimerControl.timers["..self.timerID.."]\n"
|
Nenue@6
|
430 .. "\n return '" .. str .. "'"
|
Nenue@6
|
431 local func = assert(loadstring(str))
|
Nenue@6
|
432 self.textValues[name] = func
|
Nenue@6
|
433 end
|
Nenue@6
|
434 end
|
Nenue@6
|
435
|
Nenue@6
|
436 --mod.SetText(self)
|
Nenue@6
|
437 end
|
Nenue@6
|
438
|
Nenue@6
|
439 --- generic text setter
|
Nenue@6
|
440 local HIDDEN, PASSIVE, ACTIVE = 0, 1, 2
|
Nenue@6
|
441 mod.SetText = function(self)
|
Nenue@6
|
442 if self.displayState ~= ACTIVE then
|
Nenue@6
|
443 for name, region in pairs(self.textRegions) do
|
Nenue@6
|
444 region:SetText(nil)
|
Nenue@6
|
445 end
|
Nenue@6
|
446 return
|
Nenue@6
|
447 end
|
Nenue@6
|
448
|
Nenue@6
|
449 if not self.textValues then
|
Nenue@6
|
450 self.textValues = {}
|
Nenue@6
|
451 mod.LoadText(self, self.cvars)
|
Nenue@6
|
452 end
|
Nenue@6
|
453
|
Nenue@6
|
454 -- hide when above a certain number
|
Nenue@6
|
455
|
Nenue@6
|
456 if self.spiral and self.spiral.subCounter then
|
Nenue@6
|
457 if self.valueFull > 6 then
|
Nenue@6
|
458 if self.textValues.subCounter then
|
Nenue@6
|
459 --print('hiding milliseconds')
|
Nenue@6
|
460 self.textRegions.subCounter:Hide()
|
Nenue@6
|
461 self.textRegionsSub = self.textRegions.subCounter
|
Nenue@6
|
462 self.textValuesSub = self.textValues.subCounter
|
Nenue@6
|
463 self.textRegions.subCounter = nil
|
Nenue@6
|
464 self.textValues.subCounter = nil
|
Nenue@6
|
465 end
|
Nenue@6
|
466 else
|
Nenue@6
|
467 if not self.textValues.subCounter then
|
Nenue@6
|
468 --print('showing milliseconds')
|
Nenue@6
|
469 self.textValues.subCounter = self.textValuesSub
|
Nenue@6
|
470 self.textRegions.subCounter = self.textRegionsSub
|
Nenue@6
|
471 self.textRegions.subCounter:Show()
|
Nenue@6
|
472 end
|
Nenue@6
|
473 end
|
Nenue@6
|
474 end
|
Nenue@6
|
475
|
Nenue@6
|
476 for name, region in pairs(self.textRegions) do
|
Nenue@6
|
477 --print(name)
|
Nenue@6
|
478 --print(name, self.timerName, self.textValues[name](self))
|
Nenue@6
|
479 region:SetText(self.textValues[name](self))
|
Nenue@6
|
480 end
|
Nenue@6
|
481 end
|
Nenue@6
|
482
|
Nenue@6
|
483
|
Nenue@6
|
484 -------------------------------------------------------------------------
|
Nenue@6
|
485 --- Second-tier handlers to cut down on the number of Status:Event() polls
|
Nenue@6
|
486
|
Nenue@6
|
487 --- UNIT_SPELLCAST_*** use args to filter out the number of full handler runs
|
Nenue@6
|
488 function mod:UNIT_SPELLCAST_SUCCEEDED (e, unit, spellName, rank, castID, spellID)
|
Nenue@6
|
489 if not mod.frames.unit[unit] then
|
Nenue@6
|
490 return
|
Nenue@6
|
491 end
|
Nenue@6
|
492
|
Nenue@6
|
493 if #mod.frames.spellName[spellName] > 0 then
|
Nenue@6
|
494 print('spellName-ID relation detected:', cWord(spellName), cNum(spellID))
|
Nenue@6
|
495 for i, frame in pairs(mod.frames.spellName[spellName]) do
|
Nenue@6
|
496 if not frame.frames.spellID then
|
Nenue@6
|
497 frame.frames.spellID = {}
|
Nenue@6
|
498 end
|
Nenue@6
|
499 if not frame.frames.spellID[spellID] then
|
Nenue@6
|
500
|
Nenue@6
|
501 tinsert(mod.frames.spellID[spellID], frame)
|
Nenue@6
|
502 frame.frames.spellID[spellID] = #mod.frames.spellID[spellID]
|
Nenue@6
|
503 print(cText(' updating'), cKey(frame.timerName))
|
Nenue@6
|
504 end
|
Nenue@6
|
505 end
|
Nenue@6
|
506 mod.frames.spellName[spellName] = nil
|
Nenue@6
|
507 end
|
Nenue@6
|
508
|
Nenue@6
|
509
|
Nenue@6
|
510
|
Nenue@6
|
511 if mod.frames.spellID[spellID] then
|
Nenue@6
|
512 for i, timer_frame in pairs(mod.frames.spellID[spellID]) do
|
Nenue@6
|
513 print(cText('caught spell'), cWord(spellName), 'for', timer_frame:GetName())
|
Nenue@6
|
514 timer_frame:Event(e, unit, spellName, rank, castID, spellID)
|
Nenue@6
|
515 end
|
Nenue@6
|
516 end
|
Nenue@6
|
517 end
|
Nenue@6
|
518 mod.UNIT_SPELLCAST_CHANNEL_START = mod.UNIT_SPELLCAST_SUCCEEDED
|
Nenue@6
|
519
|
Nenue@6
|
520 --- Fire a dry event to force status updates on units with changing GUID's
|
Nenue@6
|
521 function mod:PLAYER_TARGET_CHANGED(e, unit)
|
Nenue@6
|
522 print('doing a target swap thing')
|
Nenue@6
|
523 for k, v in pairs( self.frames.unit.target) do
|
Nenue@6
|
524 print(k, v)
|
Nenue@6
|
525 v:Event(nil, 'target')
|
Nenue@6
|
526 end
|
Nenue@6
|
527 end
|
Nenue@6
|
528
|
Nenue@6
|
529 --- Same thing but for talent/spec-driven
|
Nenue@9
|
530 local update_queue = {}
|
Nenue@9
|
531 function mod.ResetTimers(heading)
|
Nenue@9
|
532 print(cText('*** Flushing update queue for'), cWord(heading))
|
Nenue@9
|
533 for id, frame in pairs(update_queue) do
|
Nenue@9
|
534 print(' ', cNum(id), cKey(frame.timerName))
|
Nenue@9
|
535 frame.disable = nil
|
Nenue@9
|
536 wipe(frame.debug_info)
|
Nenue@9
|
537 local res, msg = mod:EnableTimer(id, frame.dvars)
|
Nenue@9
|
538 end
|
Nenue@9
|
539 wipe(update_queue)
|
Nenue@9
|
540 end
|
Nenue@9
|
541
|
Nenue@6
|
542 function mod:PLAYER_TALENT_UPDATE(e, unit)
|
Nenue@6
|
543 print('')
|
Nenue@6
|
544 print('')
|
Nenue@6
|
545 print(cText(e), T.specPage, T.specName)
|
Nenue@6
|
546
|
Nenue@6
|
547 for _, k in ipairs({'talentID', 'talentRow', 'specPage'}) do
|
Nenue@6
|
548 for value, frameSet in pairs(mod.frames.talentID) do
|
Nenue@6
|
549 for id, frame in ipairs(frameSet) do
|
Nenue@6
|
550 print(frame.timerID, frame.timerName)
|
Nenue@6
|
551 update_queue[frame.timerID] = frame
|
Nenue@6
|
552 end
|
Nenue@6
|
553 end
|
Nenue@6
|
554 end
|
Nenue@9
|
555 mod.resetTimers('Talent')
|
Nenue@6
|
556 end
|
Nenue@6
|
557
|
Nenue@6
|
558 function mod:PLAYER_EQUIPMENT_CHANGED(e, slot, hasItem)
|
Nenue@6
|
559 print(e, slot, hasItem)
|
Nenue@9
|
560 if mod.frames.inventoryID and mod.frames.inventoryID[slot] then
|
Nenue@9
|
561 print(' Inventory slot:', cNum(slot))
|
Nenue@9
|
562 for i, slotFrame in ipairs(mod.frames.inventoryID[slot]) do
|
Nenue@9
|
563 print(' ', cNum(i), cText(slotFrame.timerName))
|
Nenue@9
|
564 update_queue[slotFrame.timerID] = slotFrame
|
Nenue@9
|
565 if mod.frames.itemID then
|
Nenue@9
|
566 local itemsForSlot = GetInventoryItemsForSlot(slot, {}, false)
|
Nenue@9
|
567 for _, itemID in pairs(itemsForSlot) do
|
Nenue@9
|
568 if mod.frames.itemID[itemID] then
|
Nenue@9
|
569 print(' Frames for equippable item:', cNum(itemID))
|
Nenue@9
|
570 for j, itemFrame in ipairs(mod.frames.itemID[itemID]) do
|
Nenue@9
|
571 print(' ', cNum(j), cText(itemFrame.timerName))
|
Nenue@9
|
572 update_queue[itemFrame.timerID] = itemFrame
|
Nenue@9
|
573 end
|
Nenue@9
|
574 end
|
Nenue@9
|
575 end
|
Nenue@6
|
576 end
|
Nenue@6
|
577 end
|
Nenue@6
|
578 end
|
Nenue@9
|
579 mod.ResetTimers('Equipment')
|
Nenue@6
|
580 end
|
Nenue@6
|
581 function mod:PET_BATTLE_OPENING_START ()
|
Nenue@6
|
582 for i, v in pairs(mod.timers) do
|
Nenue@6
|
583 if not v.disable then
|
Nenue@6
|
584 print('suppressing', v:GetName())
|
Nenue@6
|
585 v.disable = true
|
Nenue@6
|
586 v:Hide()
|
Nenue@6
|
587 pb_suppressed[i] = true
|
Nenue@6
|
588 end
|
Nenue@6
|
589 end
|
Nenue@6
|
590 end
|
Nenue@6
|
591 function mod:PET_BATTLE_CLOSE()
|
Nenue@6
|
592 for id, v in pairs(mod.timers) do
|
Nenue@6
|
593 if pb_suppressed[id] then
|
Nenue@6
|
594 print('restoring', v:GetName())
|
Nenue@6
|
595 mod:EnableTimer(id)
|
Nenue@6
|
596 pb_suppressed[id] = nil
|
Nenue@6
|
597 end
|
Nenue@6
|
598 end
|
Nenue@6
|
599 end |