Mercurial > wow > skeletonkey
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 |