view 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
line wrap: on
line source
--------------------------------------------
-- KrakTool
-- DamageMeter
-- @project-revision@ @project-hash@
-- @file-revision@ @file-hash@
-- Created: 6/19/2016 10:43 AM
--------------------------------------------
-- dm
--   {...} = actor ( name, guid ) -- returns actor table
--   .showbar (bar )     -- toggle row
--   .hidebar ( bar )    --
--   .ui ()              -- update chart
local KT = LibKT.register(DamageMeter)
local dm = DamageMeter
local db

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 handler
local viewType = 'damageDone'
local meterWidth = 230

dm.init = function()
  dm:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
  dm:RegisterEvent('PLAYER_REGEN_DISABLED')
  dm:RegisterEvent('ENCOUNTER_START')
  dm.bars = dm.bars or {}
  dm.headings = dm.headings or {}
end

dm.ENCOUNTER_START = function()
  dm.new()
end

dm.variables = function()
  SkeletonStatsDB = SkeletonStatsDB or {}
  db = SkeletonStatsDB
  db.segments = db.segments or {}
  db.currentSegment = db.currentSegment or 0
  db.actors = db.actors or {}
  db.viewType = db.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)
  dm.view(viewPos)

  dm.ui()
end

dm.handler = function (viewType)
  handler = prototypes[viewType]
  dm.header:SetText(handler.header)
end

dm.new = function()
  if core.active then
    core.active.finish = GetTime()
  end

  segmentUID = (db.segUID or 0) + 1
  db.segUID = segmentUID

  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,
  b = 0
}
local dummyActor = {
  name = 'Unknown',
  flags = 0,
  class = 'NA',
  classFilename = '',
  race = 'Unknown',
  raceFilename = '',
  sex = 1,
  realm = ''
}

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

  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,
      class = 'PET',
    }
    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

dm.PLAYER_REGEN_DISABLED = function()
  dm.new()
end

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
       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

--- [name]
--    .COMBAT_EVENT = function(event, ...)
--    .init         = function()
--    .calculate    = function(bar, data, actor)
--    .refresh      = function(bar, data, actor

dm.showbar = function(bar)
  bar:Show()
  bar.icon:Show()
  bar.header:Show()
  bar.headerRight:Show()
end

dm.hidebar = function(bar)
  bar:Hide()
  bar.icon:Hide()
  bar.header:Hide()
  bar.headerRight:Hide()
end

dm.ui = function()
  --table.sort(view, sortType)
  local view = core.current.view

  table.wipe(ordered)
  for k,v in pairs(view) do
    if type(v) ~= 'table' then
      view[k] = nil
    else
      tinsert(ordered, v)
    end
  end
  table.sort(ordered, handler.sort)

  handler.init()

  for i = 1, 12 do
    if ordered[i] then
      if not dm.bars[i] then
        dm.bars[i] = dm:CreateTexture('MeterBar'..i, 'BORDER')
        dm.bars[i]:SetHeight(24)
        dm.bars[i]:SetPoint('TOPLEFT', dm, 0, i * -24)
        dm.bars[i].icon = dm:CreateTexture('MeterIcon' .. i, 'OVERLAY')
        dm.bars[i].icon:SetSize(24,24)
        dm.bars[i].icon:SetPoint('TOPLEFT', dm.bars[i], 'TOPLEFT', -12, 0)

        dm.bars[i].header = dm:CreateFontString('MeterHeader'..i, 'OVERLAY', 'MeterHeaderLeft')
        dm.bars[i].header:SetPoint('LEFT', dm.bars[i], 'LEFT', 22, 0)

        dm.bars[i].headerRight = dm:CreateFontString('MeterHeaderRight'..i, 'OVERLAY', 'MeterHeaderRight')
        dm.bars[i].headerRight:SetPoint('TOP', dm.bars[i], 'TOP', 0, -6)
      end

      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

      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
  end
  dm:SetHeight((#ordered + 1) * 24)
  dm:SetWidth(meterWidth)
end
---------------------------------------------------------
-- DAMAGE DONE


---------------------------------------------------------
-- HEALING DONE