Nenue@0: -------------------------------------------- Nenue@0: -- KrakTool Nenue@0: -- DamageMeter Nenue@0: -- @project-revision@ @project-hash@ Nenue@0: -- @file-revision@ @file-hash@ Nenue@0: -- Created: 6/19/2016 10:43 AM Nenue@0: -------------------------------------------- Nenue@0: -- dm Nenue@0: -- {...} = actor ( name, guid ) -- returns actor table Nenue@0: -- .showbar (bar ) -- toggle row Nenue@0: -- .hidebar ( bar ) -- Nenue@0: -- .ui () -- update chart Nenue@1: local KT = LibKT.register(DamageMeter) Nenue@0: local dm = DamageMeter Nenue@1: local db Nenue@0: Nenue@4: local addon, core = ... Nenue@4: core.segments = {} Nenue@4: core.actors = {} Nenue@4: core.pets = {} Nenue@4: core.ordered = {} Nenue@4: core.actorsOrdered = {} Nenue@4: core.current = {} Nenue@4: core.prototypes = {} Nenue@4: Nenue@4: local GROUP_SIZE = 4 Nenue@4: local GROUP_TOKEN = 'party' Nenue@4: local myGUID Nenue@4: local segments, actors, pets, ordered = core.segments, core.actors, core.pets, core.ordered Nenue@4: local prototypes = core.prototypes Nenue@0: local segmentUID Nenue@0: local viewPos Nenue@0: local handler Nenue@0: local viewType = 'damageDone' Nenue@0: local meterWidth = 230 Nenue@0: Nenue@0: dm.init = function() Nenue@0: dm:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED') Nenue@1: dm:RegisterEvent('PLAYER_REGEN_DISABLED') Nenue@0: dm:RegisterEvent('ENCOUNTER_START') Nenue@0: dm.bars = dm.bars or {} Nenue@0: dm.headings = dm.headings or {} Nenue@0: end Nenue@0: Nenue@0: dm.ENCOUNTER_START = function() Nenue@0: dm.new() Nenue@0: end Nenue@0: Nenue@0: dm.variables = function() Nenue@1: SkeletonStatsDB = SkeletonStatsDB or {} Nenue@1: db = SkeletonStatsDB Nenue@1: db.segments = db.segments or {} Nenue@1: db.currentSegment = db.currentSegment or 0 Nenue@1: db.actors = db.actors or {} Nenue@1: db.viewType = db.viewType or 'damageDone' Nenue@0: Nenue@4: Nenue@4: Nenue@4: myGUID = UnitGUID('player') Nenue@4: core.actor(myGUID) Nenue@4: segments = db.segments Nenue@4: viewPos = db.currentSegment Nenue@4: viewType = prototypes[viewType] and viewType or 'damageDone' Nenue@4: Nenue@4: if not segments[#segments] then Nenue@4: dm.new() Nenue@4: end Nenue@0: Nenue@0: dm.handler(viewType) Nenue@4: dm.view(viewPos) Nenue@0: Nenue@0: dm.ui() Nenue@0: end Nenue@0: Nenue@0: dm.handler = function (viewType) Nenue@0: handler = prototypes[viewType] Nenue@0: dm.header:SetText(handler.header) Nenue@0: end Nenue@0: Nenue@0: dm.new = function() Nenue@4: if core.active then Nenue@4: core.active.finish = GetTime() Nenue@4: end Nenue@4: Nenue@1: segmentUID = (db.segUID or 0) + 1 Nenue@1: db.segUID = segmentUID Nenue@4: Nenue@4: local segPos = #segments+1 Nenue@4: core.segments[segPos] = { Nenue@4: view = {}, Nenue@4: start = GetTime(), Nenue@4: uid = segmentUID Nenue@4: } Nenue@4: core.active = core.segments[viewPos].view Nenue@4: print('Starting new segment #', segPos, 'UID', segmentUID, core.active, core.segments[viewPos]) Nenue@4: Nenue@4: dm.view(segPos) Nenue@4: Nenue@0: return viewPos Nenue@0: end Nenue@4: Nenue@4: dm.view = function(pos) Nenue@4: if not segments[pos] then Nenue@4: pos = 1 Nenue@4: end Nenue@4: core.current = segments[pos] Nenue@4: core.current.view = core.current.view or {} Nenue@4: end Nenue@4: Nenue@0: local dummyColor = { Nenue@0: r = 0, Nenue@0: g = 0.5, Nenue@0: b = 0 Nenue@0: } Nenue@0: local dummyActor = { Nenue@0: name = 'Unknown', Nenue@0: flags = 0, Nenue@0: class = 'NA', Nenue@0: classFilename = '', Nenue@0: race = 'Unknown', Nenue@0: raceFilename = '', Nenue@0: sex = 1, Nenue@0: realm = '' Nenue@0: } Nenue@0: Nenue@4: local UNKNOWN_ACTOR = { Nenue@4: name = 'Unknown', Nenue@4: flags = 0, Nenue@4: class = 'NADA' Nenue@4: } Nenue@4: --- Pull stored actor info if possible Nenue@4: core.actor = function (guid, name, flags) Nenue@4: local class, classFilename, race, raceFilename, sex, name, realm Nenue@4: local actor = UNKNOWN_ACTOR Nenue@4: if actors[guid] then Nenue@4: print('cached GUID', guid) Nenue@4: return actors[guid] Nenue@4: end Nenue@0: Nenue@4: if guid:match('^Player') then Nenue@4: if db.actors[guid] then Nenue@4: actor = db.actors[guid] Nenue@4: print('using saved player GUID') Nenue@4: else Nenue@4: Nenue@4: class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid) Nenue@4: actor = { Nenue@4: name = name, Nenue@4: flags = flags, Nenue@4: class = class, Nenue@4: classFilename = classFilename, Nenue@4: race = race, Nenue@4: raceFilename = raceFilename, Nenue@4: sex = sex, Nenue@4: realm = realm Nenue@4: } Nenue@4: print('saving player GUID') Nenue@4: db.actors[guid] = actor Nenue@4: Nenue@4: end Nenue@4: Nenue@4: actors[guid] = actor Nenue@4: elseif guid:match('^Pet') then Nenue@4: print('analyzing pet GUID') Nenue@4: actor = { Nenue@0: name = name, Nenue@4: class = 'PET', Nenue@0: } Nenue@4: if not pets[guid] then Nenue@4: if bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_MINE) > 0 then Nenue@4: pets[guid] = myGUID Nenue@4: actors[myGUID].pets = actors[myGUID].pets or {} Nenue@4: actors[myGUID].pets[guid] = actor Nenue@4: elseif bit.band(flags, COMBATLOG_OBJECT_AFFILIATION_PARTY+COMBATLOG_OBJECT_AFFILIATION_RAID > 0) then Nenue@4: -- todo: handle party/raid pets Nenue@4: end Nenue@4: end Nenue@4: actors[guid] = actor Nenue@4: end Nenue@4: return actor Nenue@0: end Nenue@0: Nenue@1: dm.PLAYER_REGEN_DISABLED = function() Nenue@1: dm.new() Nenue@1: end Nenue@1: Nenue@0: dm.COMBAT_LOG_EVENT_UNFILTERED = function(self, event, timeStemp, subEvent, u1, ...) Nenue@0: local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags = ... Nenue@0: Nenue@4: local storeActor = false Nenue@0: local args = {...} Nenue@0: for key, prototype in pairs(prototypes) do Nenue@0: --print(subEvent) Nenue@0: if prototype[subEvent] then Nenue@4: local result = prototype[subEvent](subEvent, ...) Nenue@4: storeActor = (storeActor or result) Nenue@3: --print('|cFFFFFF00' .. key .. '|r.|cFF00FFFF'..subEvent, '|r', ...) Nenue@0: end Nenue@0: end Nenue@0: Nenue@4: if storeActor then Nenue@4: core.actor(sourceGUID, sourceName, sourceFlags) Nenue@4: core.actor(destGUID, destName, destFlags) Nenue@4: end Nenue@4: Nenue@0: dm.ui() Nenue@0: return true Nenue@0: end Nenue@0: Nenue@0: --- [name] Nenue@0: -- .COMBAT_EVENT = function(event, ...) Nenue@0: -- .init = function() Nenue@0: -- .calculate = function(bar, data, actor) Nenue@0: -- .refresh = function(bar, data, actor Nenue@0: Nenue@0: dm.showbar = function(bar) Nenue@0: bar:Show() Nenue@0: bar.icon:Show() Nenue@0: bar.header:Show() Nenue@0: bar.headerRight:Show() Nenue@0: end Nenue@0: Nenue@0: dm.hidebar = function(bar) Nenue@0: bar:Hide() Nenue@0: bar.icon:Hide() Nenue@0: bar.header:Hide() Nenue@0: bar.headerRight:Hide() Nenue@0: end Nenue@0: Nenue@0: dm.ui = function() Nenue@0: --table.sort(view, sortType) Nenue@4: local view = core.current.view Nenue@0: Nenue@0: table.wipe(ordered) Nenue@0: for k,v in pairs(view) do Nenue@0: if type(v) ~= 'table' then Nenue@0: view[k] = nil Nenue@0: else Nenue@0: tinsert(ordered, v) Nenue@0: end Nenue@0: end Nenue@0: table.sort(ordered, handler.sort) Nenue@0: Nenue@0: handler.init() Nenue@0: Nenue@0: for i = 1, 12 do Nenue@0: if ordered[i] then Nenue@0: if not dm.bars[i] then Nenue@0: dm.bars[i] = dm:CreateTexture('MeterBar'..i, 'BORDER') Nenue@0: dm.bars[i]:SetHeight(24) Nenue@0: dm.bars[i]:SetPoint('TOPLEFT', dm, 0, i * -24) Nenue@0: dm.bars[i].icon = dm:CreateTexture('MeterIcon' .. i, 'OVERLAY') Nenue@0: dm.bars[i].icon:SetSize(24,24) Nenue@0: dm.bars[i].icon:SetPoint('TOPLEFT', dm.bars[i], 'TOPLEFT', -12, 0) Nenue@0: Nenue@0: dm.bars[i].header = dm:CreateFontString('MeterHeader'..i, 'OVERLAY', 'MeterHeaderLeft') Nenue@0: dm.bars[i].header:SetPoint('LEFT', dm.bars[i], 'LEFT', 22, 0) Nenue@0: Nenue@0: dm.bars[i].headerRight = dm:CreateFontString('MeterHeaderRight'..i, 'OVERLAY', 'MeterHeaderRight') Nenue@0: dm.bars[i].headerRight:SetPoint('TOP', dm.bars[i], 'TOP', 0, -6) Nenue@0: end Nenue@4: Nenue@4: local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR Nenue@4: handler.calculate(dm.bars[i], ordered[i], ordered[i], actor) Nenue@0: end Nenue@0: end Nenue@0: Nenue@0: for i, bar in ipairs(dm.bars) do Nenue@0: if ordered[i] then Nenue@4: Nenue@4: local actor = actors[ordered[i].guid] or UNKNOWN_ACTOR Nenue@4: local icon, textLeft, textRight, r, g, b, a, percent = handler.refresh(bar, ordered[i], actor) Nenue@4: Nenue@4: bar:SetColorTexture(r, g, b, a) Nenue@4: Nenue@4: if icon then Nenue@4: bar.icon:Show() Nenue@4: bar.icon:SetTexture(icon[1]) Nenue@4: if icon[2] then Nenue@4: bar.icon:SetTexCoord(unpack(icon[2])) Nenue@4: else Nenue@4: bar.icon:SetTexCoord(1,0,1,0) Nenue@4: end Nenue@4: else Nenue@4: bar.icon:Hide() Nenue@4: end Nenue@4: Nenue@4: if textLeft then Nenue@4: bar.header:Show() Nenue@4: bar.header:SetText(textLeft) Nenue@4: else Nenue@4: bar.header:Hide() Nenue@4: end Nenue@4: if textRight then Nenue@4: bar.headerRight:Show() Nenue@4: bar.headerRight:SetText(textRight) Nenue@4: else Nenue@4: bar.headerRight:Hide() Nenue@4: end Nenue@4: Nenue@4: bar:SetWidth(meterWidth*percent) Nenue@4: bar:Show() Nenue@0: else Nenue@0: dm.hidebar(bar) Nenue@0: end Nenue@0: end Nenue@0: dm:SetHeight((#ordered + 1) * 24) Nenue@0: dm:SetWidth(meterWidth) Nenue@0: end Nenue@0: --------------------------------------------------------- Nenue@0: -- DAMAGE DONE Nenue@0: Nenue@0: Nenue@0: --------------------------------------------------------- Nenue@0: -- HEALING DONE