Mercurial > wow > skeletonkey
changeset 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 | 9ac29fe77455 |
files | SkeletonStats/DamageMeter.lua SkeletonStats/SkeletonStats.toc SkeletonStats/Views/DamageDone.lua SkeletonUnit/UnitFrame.lua SkeletonUnit/UnitFrame.xml |
diffstat | 5 files changed, 306 insertions(+), 179 deletions(-) [+] |
line wrap: on
line diff
--- a/SkeletonStats/DamageMeter.lua Tue Jun 21 08:14:22 2016 -0400 +++ b/SkeletonStats/DamageMeter.lua Tue Jun 21 11:56:14 2016 -0400 @@ -13,23 +13,27 @@ local KT = LibKT.register(DamageMeter) local dm = DamageMeter local db -local segments = {} -local actors = {} -local ordered = {} -local actorsOrdered = {} -local prototypes = {} +local addon, core = ... +core.segments = {} +core.actors = {} +core.pets = {} +core.ordered = {} +core.actorsOrdered = {} +core.current = {} +core.prototypes = {} + +local GROUP_SIZE = 4 +local GROUP_TOKEN = 'party' +local myGUID +local segments, actors, pets, ordered = core.segments, core.actors, core.pets, core.ordered +local prototypes = core.prototypes local segmentUID local viewPos -local view local handler local viewType = 'damageDone' -local sortType local meterWidth = 230 -local SortByDamage = function(a, b) -end - dm.init = function() dm:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED') dm:RegisterEvent('PLAYER_REGEN_DISABLED') @@ -50,21 +54,20 @@ db.actors = db.actors or {} db.viewType = db.viewType or 'damageDone' - actors = db.actors - segments = db.segments - viewPos = db.currentSegment - viewType = prototypes[viewType] and viewType or 'damageDone' + + + myGUID = UnitGUID('player') + core.actor(myGUID) + segments = db.segments + viewPos = db.currentSegment + viewType = prototypes[viewType] and viewType or 'damageDone' + + if not segments[#segments] then + dm.new() + end dm.handler(viewType) - - -- resolve segment - if not segments[viewPos] then - viewPos = dm.new() - else - view = segments[viewPos] - print('Using segment #', viewPos) - end - db.currentSegment = viewPos + dm.view(viewPos) dm.ui() end @@ -75,15 +78,35 @@ end dm.new = function() + if core.active then + core.active.finish = GetTime() + end + segmentUID = (db.segUID or 0) + 1 db.segUID = segmentUID - view = {} - viewPos = #segments+1 - segments[viewPos] = view - db.currentSegment = viewPos - print('Starting new segment #', viewPos) + + local segPos = #segments+1 + core.segments[segPos] = { + view = {}, + start = GetTime(), + uid = segmentUID + } + core.active = core.segments[viewPos].view + print('Starting new segment #', segPos, 'UID', segmentUID, core.active, core.segments[viewPos]) + + dm.view(segPos) + return viewPos end + +dm.view = function(pos) + if not segments[pos] then + pos = 1 + end + core.current = segments[pos] + core.current.view = core.current.view or {} +end + local dummyColor = { r = 0, g = 0.5, @@ -100,30 +123,63 @@ realm = '' } -dm.actor = function (guid, name, flags) - --if not actors[guid] then - local class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid) +local UNKNOWN_ACTOR = { + name = 'Unknown', + flags = 0, + class = 'NADA' +} +--- Pull stored actor info if possible +core.actor = function (guid, name, flags) + local class, classFilename, race, raceFilename, sex, name, realm + local actor = UNKNOWN_ACTOR + if actors[guid] then + print('cached GUID', guid) + return actors[guid] + end - --print('|cFFFFFF00guid|r =', name, flags, 'class', class, classFilename) - actors[guid] = { + if guid:match('^Player') then + if db.actors[guid] then + actor = db.actors[guid] + print('using saved player GUID') + else + + class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid) + actor = { + name = name, + flags = flags, + class = class, + classFilename = classFilename, + race = race, + raceFilename = raceFilename, + sex = sex, + realm = realm + } + print('saving player GUID') + db.actors[guid] = actor + + end + + actors[guid] = actor + elseif guid:match('^Pet') then + print('analyzing pet GUID') + actor = { name = name, - flags = flags, - class = class, - classFilename = classFilename, - race = race, - raceFilename = raceFilename, - sex = sex, - realm = realm + class = 'PET', } - --end - return actors[guid] + if not pets[guid] then + if bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_MINE) > 0 then + pets[guid] = myGUID + actors[myGUID].pets = actors[myGUID].pets or {} + actors[myGUID].pets[guid] = actor + elseif bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_PARTY+COMBATLOG_OBJECT_AFFILIATION_RAID > 0) then + -- todo: handle party/raid pets + end + end + actors[guid] = actor + end + return actor end - -prototypes.damageDone = { - header = 'Damage Done', -} - dm.PLAYER_REGEN_DISABLED = function() dm.new() end @@ -131,16 +187,22 @@ dm.COMBAT_LOG_EVENT_UNFILTERED = function(self, event, timeStemp, subEvent, u1, ...) local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags = ... - + local storeActor = false local args = {...} for key, prototype in pairs(prototypes) do --print(subEvent) if prototype[subEvent] then - prototype[subEvent](subEvent, ...) + local result = prototype[subEvent](subEvent, ...) + storeActor = (storeActor or result) --print('|cFFFFFF00' .. key .. '|r.|cFF00FFFF'..subEvent, '|r', ...) end end + if storeActor then + core.actor(sourceGUID, sourceName, sourceFlags) + core.actor(destGUID, destName, destFlags) + end + dm.ui() return true end @@ -167,7 +229,7 @@ dm.ui = function() --table.sort(view, sortType) - + local view = core.current.view table.wipe(ordered) for k,v in pairs(view) do @@ -197,14 +259,47 @@ dm.bars[i].headerRight = dm:CreateFontString('MeterHeaderRight'..i, 'OVERLAY', 'MeterHeaderRight') dm.bars[i].headerRight:SetPoint('TOP', dm.bars[i], 'TOP', 0, -6) end - handler.calculate(dm.bars[i], ordered[i], ordered[i].actor) + + local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR + handler.calculate(dm.bars[i], ordered[i], ordered[i], actor) end end for i, bar in ipairs(dm.bars) do if ordered[i] then - handler.refresh(bar, ordered[i], ordered[i].actor) - dm.showbar(bar) + + local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR + local icon, textLeft, textRight, r, g, b, a, percent = handler.refresh(bar, ordered[i], actor) + + bar:SetColorTexture(r, g, b, a) + + if icon then + bar.icon:Show() + bar.icon:SetTexture(icon[1]) + if icon[2] then + bar.icon:SetTexCoord(unpack(icon[2])) + else + bar.icon:SetTexCoord(1,0,1,0) + end + else + bar.icon:Hide() + end + + if textLeft then + bar.header:Show() + bar.header:SetText(textLeft) + else + bar.header:Hide() + end + if textRight then + bar.headerRight:Show() + bar.headerRight:SetText(textRight) + else + bar.headerRight:Hide() + end + + bar:SetWidth(meterWidth*percent) + bar:Show() else dm.hidebar(bar) end @@ -214,72 +309,6 @@ end --------------------------------------------------------- -- DAMAGE DONE -local dd = prototypes.damageDone -dd.SPELL_DAMAGE = function(subEvent, ...) - local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ... - - if not sourceName then - return - end - - view[sourceName] = view[sourceName] or {} - local p = view[sourceName] - - p.actor = dm.actor(sourceGUID, sourceName, sourceFlags) - dm.actor(destGUID, destName, destFlags) - - p.last = amount - p.damage = (view[sourceName].damage or 0) + amount - p.name = (sourceName or 'Unknown') - - p.child = p.child or {} - p.child[spellName] = p.child[spellName] or {} - p.child[spellName].hit = (p.child[spellName].hit or 0) + 1 -end -dd.SPELL_DAMAGE_PERIODIC = dd.SPELL_DAMAGE -dd.RANGE_DAMAGE = dd.SPELL_DAMAGE - -dd.SWING_DAMAGE = function(subEvent, ...) - local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ... - local spellID, spellName, spellSchool = -1, 'Attack', 1 - dd.SPELL_DAMAGE(subEvent, sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing) -end - -dd.init = function() - dd.maxDamage = 0 -end - -dd.sort = function(a, b) - return a.damage > b.damage -end - -dd.calculate = function(bar, data, actor) - if dd.maxDamage < data.damage then - dd.maxDamage = data.damage - end - -end - -dd.refresh = function(bar, data, actor) - if actor.class and CLASS_ICON_TCOORDS[actor.classFilename] then - bar.icon:Show() - bar.icon:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles") - bar.icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[actor.classFilename])) - else - bar.icon:Hide() - end - bar.header:SetText(data.name) - bar.headerRight:SetText(data.damage .. ' ('..data.last..')') - - local color = dummyColor - if actor.class and RAID_CLASS_COLORS[actor.classFilename] then - color = RAID_CLASS_COLORS[actor.classFilename] - end - - bar:SetColorTexture(color.r, color.g, color.b, 1) - - bar:SetWidth(meterWidth * (data.damage / dd.maxDamage)) -end ---------------------------------------------------------
--- a/SkeletonStats/SkeletonStats.toc Tue Jun 21 08:14:22 2016 -0400 +++ b/SkeletonStats/SkeletonStats.toc Tue Jun 21 11:56:14 2016 -0400 @@ -12,4 +12,5 @@ libKT-1.0\libKT-1.0.xml DamageMeter.xml -DamageMeter.lua \ No newline at end of file +DamageMeter.lua +Views\DamageDone.lua \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonStats/Views/DamageDone.lua Tue Jun 21 11:56:14 2016 -0400 @@ -0,0 +1,83 @@ + +local core = select(2, ...) +local prototypes = core.prototypes +local SOURCE_MASK = COMBATLOG_OBJECT_AFFILIATION_RAID+COMBATLOG_OBJECT_AFFILIATION_PARTY+COMBATLOG_OBJECT_AFFILIATION_MINE + +local dd = { + header = 'Damage Done', +} +dd.SPELL_DAMAGE = function(subEvent, ...) + local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ... + + if not sourceName then + return false + end + + if bit.band(sourceFlags, SOURCE_MASK) == 0 then + --print('discarded non-raid damage event', sourceFlags, sourceName) + return false + end + + local view = core.current.view + view[sourceName] = view[sourceName] or {} + local p = view[sourceName] + + + p.guid = sourceGUID + p.last = amount + p.damage = (p.damage or 0) + amount + p.name = (sourceName or 'Unknown') + + p.child = p.child or {} + p.child[spellName] = p.child[spellName] or {} + p.child[spellName].hit = (p.child[spellName].hit or 0) + 1 + + -- true = store this event's actor + return true +end + +dd.SPELL_DAMAGE_PERIODIC = dd.SPELL_DAMAGE +dd.RANGE_DAMAGE = dd.SPELL_DAMAGE + +dd.SWING_DAMAGE = function(subEvent, ...) + local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ... + local spellID, spellName, spellSchool = -1, 'Attack', 1 + dd.SPELL_DAMAGE(subEvent, sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing) +end + +dd.init = function() + dd.maxDamage = 0 +end + +dd.sort = function(a, b) + return a.damage > b.damage +end + +dd.calculate = function(bar, data, actor) + if dd.maxDamage < data.damage then + dd.maxDamage = data.damage + end + +end + +dd.refresh = function(bar, data, actor) + local icon, textLeft, textRight + local r, g, b, a, percent = 1,1,1,1,1 + if actor.class and CLASS_ICON_TCOORDS[actor.classFilename] then + icon = { "Interface\\TargetingFrame\\UI-Classes-Circles" , CLASS_ICON_TCOORDS[actor.classFilename] } + end + textLeft = data.name + textRight = data.damage .. ' ('..data.last..')' + + + if actor.class and RAID_CLASS_COLORS[actor.classFilename] then + r = RAID_CLASS_COLORS[actor.classFilename].r + g = RAID_CLASS_COLORS[actor.classFilename].g + b = RAID_CLASS_COLORS[actor.classFilename].b + end + percent = (data.damage / dd.maxDamage) + + return icon, textLeft, textRight, r, g, b, a, percent +end + +prototypes.damageDone = dd \ No newline at end of file
--- a/SkeletonUnit/UnitFrame.lua Tue Jun 21 08:14:22 2016 -0400 +++ b/SkeletonUnit/UnitFrame.lua Tue Jun 21 11:56:14 2016 -0400 @@ -19,10 +19,11 @@ local params = setmetatable({}, { __index = function(t, k) print('get', k) - return rawget(t.player, k) + return t.player end, __newindex = function(t, k, v) if type(v) == 'table' then + print('branch', k) v = setmetatable(v, { __index = function(tt, kk) print('get', k, kk) @@ -30,6 +31,7 @@ end, __newindex = function(tt, kk, vv) if type(vv) == 'table' then + print('_branch', k, kk) vv = setmetatable(vv, { __index = function(_tt, _kk) print('_get', k, kk, _kk) @@ -50,12 +52,23 @@ height = 30, health = { height = 24 }, power = { height = 6}, - } + position = {'CENTER', nil, 'CENTER',0,-120 } +} params.pet = { width = 180, - height = 25 + height = 25, + + position = {'TOPLEFT', 'player', 'BOTTOMLEFT',0,-4} } -params.focus = params.pet +params.target = { + + position = {'TOPLEFT', 'player', 'TOPRIGHT',4,0} +} +params.focus = { + width = 180, + height = 25, + position = {'BOTTOMRIGHT', 'target', 'TOPRIGHT',0,4} +} uf.handler = uf -- so uf.event can work @@ -77,7 +90,6 @@ buttons[unit][index] = CreateFrame('Frame', 'KT'..unit..'Buff'..index, self, 'KTAuraButton') buttons[unit][index]:SetSize(BUFF_SIZE, BUFF_SIZE) buttons[unit][index].cooldown:SetHideCountdownNumbers(true) - end return buttons[unit][index] end @@ -88,34 +100,36 @@ end print('|cFFFFFF00unit|r:', unit) + local c = params[unit] + if not _G['KT'..unit..'Frame'] then - CreateFrame('Frame', 'KT'.. unit .. 'Frame', uf) + local new = CreateFrame('Button', 'KT'.. unit .. 'Frame', uf, 'KTUnitFrameTemplate') + new.unit = unit + new.anchorPoint = {new:GetPoint(1)} + new.handler = prototypes[unit] + new.params = c + + --if not db.position[unit] then + db.position[unit] = c.position + --end + new.position = db.position[unit] + + + buttons[unit] = {} + new.buttons = buttons[unit] + new.refresh = prototypes[unit].refresh + new.init = prototypes[unit].init + + new:EnableMouse(true) + new:SetScript('OnMouseUp', prototypes[unit].OnMouseUp) + + new:SetAttribute("type", "target") + new:SetAttribute("unit", unit) + RegisterUnitWatch(new) + units[unit] = new end - local frame = _G['KT'..unit..'Frame'] - frame.unit = unit - frame.anchorPoint = {frame:GetPoint(1)} - frame.handler = prototypes[unit] - - buttons[unit] = {} - units[unit] = frame - - local width = params.player.width - local height = params.player.height - - if params[unit] then - if params[unit].width then - width = params[unit].width - end - if params[unit].height then - height = params[unit].height - end - end - - frame:SetWidth(width) - frame:SetHeight(height) - - return frame + return _G['KT'..unit..'Frame'] end uf.ui = function () @@ -126,6 +140,7 @@ uf.init = function() uf:RegisterEvent('PLAYER_TARGET_CHANGED') + uf:RegisterEvent('PLAYER_FOCUS_CHANGED') uf:RegisterUnitEvent("UNIT_AURA") end @@ -156,7 +171,12 @@ end uf.PLAYER_TARGET_CHANGED = function() - prototypes.player.refresh(units.target) + print('caught target change') + units.target:refresh() +end + +uf.PLAYER_FOCUS_CHANGED = function() + units.focus:refresh() end prototypes.player = {} @@ -168,16 +188,30 @@ self:RegisterEvent("NAME_PLATE_UNIT_REMOVED") self:RegisterEvent("UNIT_TARGET") self:SetScript('OnEvent', uf.event) + + local anchor, parent, relative, x, y = unpack(self.position) + if parent and units[parent] then + parent = units[parent] + else + parent = UIParent + end + + self:SetPoint(anchor, parent, relative, x, y) + self:SetSize(self.params.width, self.params.height) + end --- Runs when event handler decides so player.refresh = function(self) + print(self.unit, UnitExists(self.unit)) if not UnitExists(self.unit) then + print('hiding unit') self:Hide() return end + self:Show() if UnitIsPlayer(self.unit) then local class, classFile = UnitClass(self.unit) if classFile then @@ -198,12 +232,12 @@ else self.healthbar:SetHeight(params[self.unit].health.height + params[self.unit].power.height) end - - + uf.UNIT_AURA(self, 'UNIT_AURA', self.unit) self.handler.UNIT_HEALTH_FREQUENT(self) end + uf.UNIT_AURA = function(self, event, unit) if not units[unit] then return true end @@ -240,7 +274,7 @@ player.UNIT_HEALTH_FREQUENT = function(self, ...) if UnitHealthMax(self.unit) > 0 then - self.healthbar:SetWidth(PLAYER_WIDTH * UnitHealth(self.unit) / UnitHealthMax(self.unit)) + self.healthbar:SetWidth(self.params.width * UnitHealth(self.unit) / UnitHealthMax(self.unit)) self.healthtext:SetText(UnitHealth(self.unit)) else self.healthbar:SetWidth(PLAYER_WIDTH) @@ -251,7 +285,7 @@ player.UNIT_POWER_FREQUENT = function(self) if UnitPowerMax(self.unit) > 0 then - self.powerbar:SetWidth(PLAYER_WIDTH * UnitPower(self.unit) / UnitPowerMax(self.unit)) + self.powerbar:SetWidth(self.params.width * UnitPower(self.unit) / UnitPowerMax(self.unit)) self.powertext:SetText(UnitPower(self.unit)) else self.powerbar:Hide() @@ -271,4 +305,5 @@ end prototypes.pet = player -prototypes.target = player \ No newline at end of file +prototypes.target = player +prototypes.focus = player \ No newline at end of file
--- a/SkeletonUnit/UnitFrame.xml Tue Jun 21 08:14:22 2016 -0400 +++ b/SkeletonUnit/UnitFrame.xml Tue Jun 21 11:56:14 2016 -0400 @@ -4,7 +4,7 @@ <Texture name="KTStatusBar" virtual="true" /> <Frame name="SkeletonUnits" parent="UIParent"></Frame> - <Frame name="KTUnitFrame" parent="UIParent" virtual="true"> + <Button name="KTUnitFrameTemplate" inherits="SecureUnitButtonTemplate" parent="UIParent" virtual="true"> <Size x="250" y="50" /> <Layers> <Layer level="BACKGROUND"> @@ -47,28 +47,7 @@ </FontString> </Layer> </Layers> - </Frame> + </Button> - <Frame name="KTplayerFrame" inherits="KTUnitFrame"> - - <Anchors> - <Anchor point="BOTTOM" x="0" y="260" /> - </Anchors> - </Frame> - <Frame name="KTpetFrame" inherits="KTUnitFrame"> - - <Anchors> - <Anchor point="TOPRIGHT" relativePoint="TOPLEFT" relativeTo="KTplayerFrame" x="-2" /> - </Anchors> - </Frame> - <Frame name="KTtargetFrame" inherits="KTUnitFrame"> - - - <Anchors> - <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="4" y="0" relativeTo="KTplayerFrame" /> - </Anchors> - </Frame> - - <Frame name="KTfocusFrame" inherits="KTUnitFrame" /> </Ui> \ No newline at end of file