comparison SkeletonStats/DamageMeter.lua @ 4:a30285f8191e

Units: make sure unit frames are SecureUnitButton derivatives remove of unnecessary target/focus events Stats: resolve GUID after event handlers have fired keep frame manipulation in uf.ui, get needed values from wrapper functions
author Nenue
date Tue, 21 Jun 2016 11:56:14 -0400
parents 07293831dd7b
children
comparison
equal deleted inserted replaced
3:07293831dd7b 4:a30285f8191e
11 -- .hidebar ( bar ) -- 11 -- .hidebar ( bar ) --
12 -- .ui () -- update chart 12 -- .ui () -- update chart
13 local KT = LibKT.register(DamageMeter) 13 local KT = LibKT.register(DamageMeter)
14 local dm = DamageMeter 14 local dm = DamageMeter
15 local db 15 local db
16 local segments = {} 16
17 local actors = {} 17 local addon, core = ...
18 local ordered = {} 18 core.segments = {}
19 local actorsOrdered = {} 19 core.actors = {}
20 local prototypes = {} 20 core.pets = {}
21 21 core.ordered = {}
22 core.actorsOrdered = {}
23 core.current = {}
24 core.prototypes = {}
25
26 local GROUP_SIZE = 4
27 local GROUP_TOKEN = 'party'
28 local myGUID
29 local segments, actors, pets, ordered = core.segments, core.actors, core.pets, core.ordered
30 local prototypes = core.prototypes
22 local segmentUID 31 local segmentUID
23 local viewPos 32 local viewPos
24 local view
25 local handler 33 local handler
26 local viewType = 'damageDone' 34 local viewType = 'damageDone'
27 local sortType
28 local meterWidth = 230 35 local meterWidth = 230
29
30 local SortByDamage = function(a, b)
31 end
32 36
33 dm.init = function() 37 dm.init = function()
34 dm:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED') 38 dm:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
35 dm:RegisterEvent('PLAYER_REGEN_DISABLED') 39 dm:RegisterEvent('PLAYER_REGEN_DISABLED')
36 dm:RegisterEvent('ENCOUNTER_START') 40 dm:RegisterEvent('ENCOUNTER_START')
48 db.segments = db.segments or {} 52 db.segments = db.segments or {}
49 db.currentSegment = db.currentSegment or 0 53 db.currentSegment = db.currentSegment or 0
50 db.actors = db.actors or {} 54 db.actors = db.actors or {}
51 db.viewType = db.viewType or 'damageDone' 55 db.viewType = db.viewType or 'damageDone'
52 56
53 actors = db.actors 57
54 segments = db.segments 58
55 viewPos = db.currentSegment 59 myGUID = UnitGUID('player')
56 viewType = prototypes[viewType] and viewType or 'damageDone' 60 core.actor(myGUID)
61 segments = db.segments
62 viewPos = db.currentSegment
63 viewType = prototypes[viewType] and viewType or 'damageDone'
64
65 if not segments[#segments] then
66 dm.new()
67 end
57 68
58 dm.handler(viewType) 69 dm.handler(viewType)
59 70 dm.view(viewPos)
60 -- resolve segment
61 if not segments[viewPos] then
62 viewPos = dm.new()
63 else
64 view = segments[viewPos]
65 print('Using segment #', viewPos)
66 end
67 db.currentSegment = viewPos
68 71
69 dm.ui() 72 dm.ui()
70 end 73 end
71 74
72 dm.handler = function (viewType) 75 dm.handler = function (viewType)
73 handler = prototypes[viewType] 76 handler = prototypes[viewType]
74 dm.header:SetText(handler.header) 77 dm.header:SetText(handler.header)
75 end 78 end
76 79
77 dm.new = function() 80 dm.new = function()
81 if core.active then
82 core.active.finish = GetTime()
83 end
84
78 segmentUID = (db.segUID or 0) + 1 85 segmentUID = (db.segUID or 0) + 1
79 db.segUID = segmentUID 86 db.segUID = segmentUID
80 view = {} 87
81 viewPos = #segments+1 88 local segPos = #segments+1
82 segments[viewPos] = view 89 core.segments[segPos] = {
83 db.currentSegment = viewPos 90 view = {},
84 print('Starting new segment #', viewPos) 91 start = GetTime(),
92 uid = segmentUID
93 }
94 core.active = core.segments[viewPos].view
95 print('Starting new segment #', segPos, 'UID', segmentUID, core.active, core.segments[viewPos])
96
97 dm.view(segPos)
98
85 return viewPos 99 return viewPos
86 end 100 end
101
102 dm.view = function(pos)
103 if not segments[pos] then
104 pos = 1
105 end
106 core.current = segments[pos]
107 core.current.view = core.current.view or {}
108 end
109
87 local dummyColor = { 110 local dummyColor = {
88 r = 0, 111 r = 0,
89 g = 0.5, 112 g = 0.5,
90 b = 0 113 b = 0
91 } 114 }
98 raceFilename = '', 121 raceFilename = '',
99 sex = 1, 122 sex = 1,
100 realm = '' 123 realm = ''
101 } 124 }
102 125
103 dm.actor = function (guid, name, flags) 126 local UNKNOWN_ACTOR = {
104 --if not actors[guid] then 127 name = 'Unknown',
105 local class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid) 128 flags = 0,
106 129 class = 'NADA'
107 --print('|cFFFFFF00guid|r =', name, flags, 'class', class, classFilename) 130 }
108 actors[guid] = { 131 --- Pull stored actor info if possible
132 core.actor = function (guid, name, flags)
133 local class, classFilename, race, raceFilename, sex, name, realm
134 local actor = UNKNOWN_ACTOR
135 if actors[guid] then
136 print('cached GUID', guid)
137 return actors[guid]
138 end
139
140 if guid:match('^Player') then
141 if db.actors[guid] then
142 actor = db.actors[guid]
143 print('using saved player GUID')
144 else
145
146 class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid)
147 actor = {
148 name = name,
149 flags = flags,
150 class = class,
151 classFilename = classFilename,
152 race = race,
153 raceFilename = raceFilename,
154 sex = sex,
155 realm = realm
156 }
157 print('saving player GUID')
158 db.actors[guid] = actor
159
160 end
161
162 actors[guid] = actor
163 elseif guid:match('^Pet') then
164 print('analyzing pet GUID')
165 actor = {
109 name = name, 166 name = name,
110 flags = flags, 167 class = 'PET',
111 class = class,
112 classFilename = classFilename,
113 race = race,
114 raceFilename = raceFilename,
115 sex = sex,
116 realm = realm
117 } 168 }
118 --end 169 if not pets[guid] then
119 return actors[guid] 170 if bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_MINE) > 0 then
120 end 171 pets[guid] = myGUID
121 172 actors[myGUID].pets = actors[myGUID].pets or {}
122 173 actors[myGUID].pets[guid] = actor
123 prototypes.damageDone = { 174 elseif bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_PARTY+COMBATLOG_OBJECT_AFFILIATION_RAID > 0) then
124 header = 'Damage Done', 175 -- todo: handle party/raid pets
125 } 176 end
177 end
178 actors[guid] = actor
179 end
180 return actor
181 end
126 182
127 dm.PLAYER_REGEN_DISABLED = function() 183 dm.PLAYER_REGEN_DISABLED = function()
128 dm.new() 184 dm.new()
129 end 185 end
130 186
131 dm.COMBAT_LOG_EVENT_UNFILTERED = function(self, event, timeStemp, subEvent, u1, ...) 187 dm.COMBAT_LOG_EVENT_UNFILTERED = function(self, event, timeStemp, subEvent, u1, ...)
132 local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags = ... 188 local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags = ...
133 189
134 190 local storeActor = false
135 local args = {...} 191 local args = {...}
136 for key, prototype in pairs(prototypes) do 192 for key, prototype in pairs(prototypes) do
137 --print(subEvent) 193 --print(subEvent)
138 if prototype[subEvent] then 194 if prototype[subEvent] then
139 prototype[subEvent](subEvent, ...) 195 local result = prototype[subEvent](subEvent, ...)
196 storeActor = (storeActor or result)
140 --print('|cFFFFFF00' .. key .. '|r.|cFF00FFFF'..subEvent, '|r', ...) 197 --print('|cFFFFFF00' .. key .. '|r.|cFF00FFFF'..subEvent, '|r', ...)
141 end 198 end
199 end
200
201 if storeActor then
202 core.actor(sourceGUID, sourceName, sourceFlags)
203 core.actor(destGUID, destName, destFlags)
142 end 204 end
143 205
144 dm.ui() 206 dm.ui()
145 return true 207 return true
146 end 208 end
165 bar.headerRight:Hide() 227 bar.headerRight:Hide()
166 end 228 end
167 229
168 dm.ui = function() 230 dm.ui = function()
169 --table.sort(view, sortType) 231 --table.sort(view, sortType)
170 232 local view = core.current.view
171 233
172 table.wipe(ordered) 234 table.wipe(ordered)
173 for k,v in pairs(view) do 235 for k,v in pairs(view) do
174 if type(v) ~= 'table' then 236 if type(v) ~= 'table' then
175 view[k] = nil 237 view[k] = nil
195 dm.bars[i].header:SetPoint('LEFT', dm.bars[i], 'LEFT', 22, 0) 257 dm.bars[i].header:SetPoint('LEFT', dm.bars[i], 'LEFT', 22, 0)
196 258
197 dm.bars[i].headerRight = dm:CreateFontString('MeterHeaderRight'..i, 'OVERLAY', 'MeterHeaderRight') 259 dm.bars[i].headerRight = dm:CreateFontString('MeterHeaderRight'..i, 'OVERLAY', 'MeterHeaderRight')
198 dm.bars[i].headerRight:SetPoint('TOP', dm.bars[i], 'TOP', 0, -6) 260 dm.bars[i].headerRight:SetPoint('TOP', dm.bars[i], 'TOP', 0, -6)
199 end 261 end
200 handler.calculate(dm.bars[i], ordered[i], ordered[i].actor) 262
263 local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR
264 handler.calculate(dm.bars[i], ordered[i], ordered[i], actor)
201 end 265 end
202 end 266 end
203 267
204 for i, bar in ipairs(dm.bars) do 268 for i, bar in ipairs(dm.bars) do
205 if ordered[i] then 269 if ordered[i] then
206 handler.refresh(bar, ordered[i], ordered[i].actor) 270
207 dm.showbar(bar) 271 local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR
272 local icon, textLeft, textRight, r, g, b, a, percent = handler.refresh(bar, ordered[i], actor)
273
274 bar:SetColorTexture(r, g, b, a)
275
276 if icon then
277 bar.icon:Show()
278 bar.icon:SetTexture(icon[1])
279 if icon[2] then
280 bar.icon:SetTexCoord(unpack(icon[2]))
281 else
282 bar.icon:SetTexCoord(1,0,1,0)
283 end
284 else
285 bar.icon:Hide()
286 end
287
288 if textLeft then
289 bar.header:Show()
290 bar.header:SetText(textLeft)
291 else
292 bar.header:Hide()
293 end
294 if textRight then
295 bar.headerRight:Show()
296 bar.headerRight:SetText(textRight)
297 else
298 bar.headerRight:Hide()
299 end
300
301 bar:SetWidth(meterWidth*percent)
302 bar:Show()
208 else 303 else
209 dm.hidebar(bar) 304 dm.hidebar(bar)
210 end 305 end
211 end 306 end
212 dm:SetHeight((#ordered + 1) * 24) 307 dm:SetHeight((#ordered + 1) * 24)
213 dm:SetWidth(meterWidth) 308 dm:SetWidth(meterWidth)
214 end 309 end
215 --------------------------------------------------------- 310 ---------------------------------------------------------
216 -- DAMAGE DONE 311 -- DAMAGE DONE
217 local dd = prototypes.damageDone
218 dd.SPELL_DAMAGE = function(subEvent, ...)
219 local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
220
221 if not sourceName then
222 return
223 end
224
225 view[sourceName] = view[sourceName] or {}
226 local p = view[sourceName]
227
228 p.actor = dm.actor(sourceGUID, sourceName, sourceFlags)
229 dm.actor(destGUID, destName, destFlags)
230
231 p.last = amount
232 p.damage = (view[sourceName].damage or 0) + amount
233 p.name = (sourceName or 'Unknown')
234
235 p.child = p.child or {}
236 p.child[spellName] = p.child[spellName] or {}
237 p.child[spellName].hit = (p.child[spellName].hit or 0) + 1
238 end
239 dd.SPELL_DAMAGE_PERIODIC = dd.SPELL_DAMAGE
240 dd.RANGE_DAMAGE = dd.SPELL_DAMAGE
241
242 dd.SWING_DAMAGE = function(subEvent, ...)
243 local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
244 local spellID, spellName, spellSchool = -1, 'Attack', 1
245 dd.SPELL_DAMAGE(subEvent, sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing)
246 end
247
248 dd.init = function()
249 dd.maxDamage = 0
250 end
251
252 dd.sort = function(a, b)
253 return a.damage > b.damage
254 end
255
256 dd.calculate = function(bar, data, actor)
257 if dd.maxDamage < data.damage then
258 dd.maxDamage = data.damage
259 end
260
261 end
262
263 dd.refresh = function(bar, data, actor)
264 if actor.class and CLASS_ICON_TCOORDS[actor.classFilename] then
265 bar.icon:Show()
266 bar.icon:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles")
267 bar.icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[actor.classFilename]))
268 else
269 bar.icon:Hide()
270 end
271 bar.header:SetText(data.name)
272 bar.headerRight:SetText(data.damage .. ' ('..data.last..')')
273
274 local color = dummyColor
275 if actor.class and RAID_CLASS_COLORS[actor.classFilename] then
276 color = RAID_CLASS_COLORS[actor.classFilename]
277 end
278
279 bar:SetColorTexture(color.r, color.g, color.b, 1)
280
281 bar:SetWidth(meterWidth * (data.damage / dd.maxDamage))
282 end
283 312
284 313
285 --------------------------------------------------------- 314 ---------------------------------------------------------
286 -- HEALING DONE 315 -- HEALING DONE