Initial push

This commit is contained in:
Robin 2021-01-13 15:12:12 +01:00
commit fe3deb1965
9 changed files with 1683 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "Libs/LibCombatlog"]
path = Libs/LibCombatlog
url = https://git.grml.de/rilgamon/LibCombatlog.git

201
DataStore.lua Normal file
View File

@ -0,0 +1,201 @@
local name, addon = ...
local stores = {}
local methods_store = {}
local methods_source = {}
local methods_dest = {}
local testUnits = { 'TARGET' }
local UnitGUID, UnitClass, CopyTable = UnitGUID, UnitClass, CopyTable
local function findClass(guid)
for i = 1, #testUnits do
if(UnitGUID(testUnits[i])==guid) then
local _, class = UnitClass(testUnits[i])
return class
end
end
end
local function setClass(src, unitName, unitGuid)
if(unitName and not src['class']) then
local _, class = UnitClass(unitName)
if(not class) then
class = findClass(unitGuid)
end
if(class) then
src['class'] = class
end
end
end
local defaultSpell = {
['count'] = 0,
['crits'] = 0,
['total'] = 0,
['totalHeal'] = 0,
['totalAbsorbed'] = 0,
['totalOverheal'] = 0,
['min'] = 0,
['max'] = 0
}
local defaultSource = {
['dest'] = {},
['total'] = 0,
['totalHeal'] = 0,
['totalOverheal'] = 0,
['totalAbsorbed'] = 0,
}
local function GetDefaultSource(data, offset)
local offset = offset or 5
local src = CopyTable(defaultSource)
if(data) then
src['guid'] = data[offset]
src['name'] = data[offset + 1]
src['flags'] = data[offset + 2]
setClass(src, data[offset + 1], data[offset])
if(not src['name']) then
print("no src name", offset)
print(unpack(data))
end
end
return src
end
local defaultDestination = {
['spells'] = {},
['spellsHeal'] = {},
['spellsAbsorbed'] = {},
['total'] = 0,
['totalHeal'] = 0,
['totalAbsorbed'] = 0,
}
local function GetDefaultDestination(data)
local dest = CopyTable(defaultDestination)
dest['guid'] = data[9]
dest['name'] = data[10]
dest['flags'] = data[11]
setClass(dest, data[10], data[9])
return dest
end
--dest2:addAbsorbSpell(extraSpellID, extraSpellName, extraSchool, amount)
local function addSpell(data)
-- spellId[4], spellName, spellSchool, amount, overhealing, absorbed, critical
-- spellId[4], spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand
local unit = data[1]
local total = data[2]
local spells
if(total == 'totalAbsorbed') then
spells = unit['spellsAbsorbed']
elseif(total == 'totalHeal') then
spells = unit['spellsHeal']
else
spells = unit['spells']
end
local isHeal = data[3]
-- local data = {...}
if(data[4]) then
local amount = data[7]
-- if(not spells[data[4]]) then print('new spell', data[5]) end
local spell = spells[data[4]] or CopyTable(defaultSpell)
spell['spellName'] = data[5]
spell['spellSchool'] = data[6]
spell[total] = spell[total] + amount
spell['count'] = spell['count'] + 1
if(isHeal) then
--overhealing, absorbed, critical
if(data[8]) then
spell['totalOverheal'] = spell['totalOverheal'] + data[8]
end
if(data[10]) then
spell['crits'] = spell['crits'] + 1
end
else
--overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand
if(data[13]) then
spell['crits'] = spell['crits'] + 1
end
end
if(amount > spell['max']) then
spell['max'] = amount
end
if(amount < spell['min'] or spell['min'] == 0) then
spell['min'] = amount
end
-- spell['eventinfo'] = spell['eventinfo'] or {}
-- spell['eventinfo'][#spell['eventinfo'] + 1] = data
spells[data[4]] = spell
unit:addTotal(total, amount)
else
print('no spellId')
end
return spells
end
function methods_source:addTotal(total, amount)
self[total] = self[total] + amount
end
function methods_dest:addTotal(total, amount)
self[total] = self[total] + amount
end
function methods_dest:addAbsorbSpell(...)
local data = {self, 'totalAbsorbed', false, ...}
-- self['spellsAbsorbed'] =
addSpell(data)
end
function methods_dest:addSpell(...)
local data = {self, 'total', false, ...}
-- self['spells'] =
addSpell(data)
end
function methods_dest:addHealSpell(...)
local data = {self, 'totalHeal', true, ...}
-- self['spellsHeal'] =
addSpell(data)
end
function methods_source:GetDestination(destGuid)
if(destGuid) then
local dest
for k, v in pairs(self['dest']) do
if(k == destGuid) then
dest = v
break
end
end
dest = dest or GetDefaultDestination(self['data'])
for k, v in pairs(methods_dest) do
dest[k] = v
end
dest['sourceGuid'] = self['guid']
self['dest'][destGuid] = dest
return dest
end
end
function methods_store:GetSourceEmpty(data)
local guid = "Unknown"
self['source'][guid] = self['source'][guid] or GetDefaultSource(data)
local src = self['source'][guid]
src['name'] = "<Unknown>"
src['guid'] = "Unknown"
src['data'] = data
for k, v in pairs(methods_source) do
src[k] = v
end
return src
end
function methods_store:GetSource(guid, data, offset, ignore)
if(guid and (ignore or data[4] == false)) then
self['source'][guid] = self['source'][guid] or GetDefaultSource(data, offset)
local src = self['source'][guid]
src['data'] = data
for k, v in pairs(methods_source) do
src[k] = v
end
return src
end
end
function addon:GetStore(seg)
if(not stores[seg]) then
-- print('new store')
stores[seg] = seg
for k, v in pairs(methods_store) do
stores[seg][k] = v
end
end
return stores[seg]
end

335
GuidInfo.lua Normal file
View File

@ -0,0 +1,335 @@
local name, addon = ...
local GetPlayerInfoByGUID, UnitFullName, UnitClassification, UnitGUID, GetNormalizedRealmName, UnitClass = GetPlayerInfoByGUID, UnitFullName, UnitClassification, UnitGUID, GetNormalizedRealmName, UnitClass
local MAX_RAID_MEMBERS, COMBATLOG_OBJECT_TYPE_PLAYER = MAX_RAID_MEMBERS, COMBATLOG_OBJECT_TYPE_PLAYER
local guidInfo = {}
--[[
UNITNAME_SUMMON_TITLE1 = "Begleiter von %s";
UNITNAME_SUMMON_TITLE10 = "Reittier von %s";
UNITNAME_SUMMON_TITLE11 = "Lichtbrunnen von %s";
UNITNAME_SUMMON_TITLE12 = "Butler von %s";
UNITNAME_SUMMON_TITLE13 = "%s'aka";
UNITNAME_SUMMON_TITLE14 = "Portal von %s";
UNITNAME_SUMMON_TITLE15 = "Hass von %s";
UNITNAME_SUMMON_TITLE16 = "Statue von %s";
UNITNAME_SUMMON_TITLE17 = "Geist von %s";
UNITNAME_SUMMON_TITLE18 = "Kriegsbanner von %s";
UNITNAME_SUMMON_TITLE19 = "Herzerwärmer von %s";
UNITNAME_SUMMON_TITLE2 = "Wächter von %s";
UNITNAME_SUMMON_TITLE20 = "Angeheuert von %s";
UNITNAME_SUMMON_TITLE21 = "Gekauft von %s";
UNITNAME_SUMMON_TITLE22 = "Stolz von %s";
UNITNAME_SUMMON_TITLE23 = "Verzerrtes Abbild von %s";
UNITNAME_SUMMON_TITLE24 = "Nudelwagen von %s";
UNITNAME_SUMMON_TITLE25 = "Innerer Dämon von %s";
UNITNAME_SUMMON_TITLE26 = "Leibwächter von %s";
UNITNAME_SUMMON_TITLE27 = "%s";
UNITNAME_SUMMON_TITLE28 = "Knappe von %s";
UNITNAME_SUMMON_TITLE29 = "Champion von %s";
UNITNAME_SUMMON_TITLE3 = "Diener von %s";
UNITNAME_SUMMON_TITLE30 = "Der Verräter";
UNITNAME_SUMMON_TITLE31 = "Eruptive Reflexion von %s";
UNITNAME_SUMMON_TITLE32 = "Hoffnungslose Reflexion von %s";
UNITNAME_SUMMON_TITLE33 = "Bösartige Reflexion von %s";
UNITNAME_SUMMON_TITLE34 = "Klagende Reflexion von %s";
UNITNAME_SUMMON_TITLE35 = "Assistentin von %s";
UNITNAME_SUMMON_TITLE36 = "Vollstrecker von %s";
UNITNAME_SUMMON_TITLE37 = "Rekrut von %s";
UNITNAME_SUMMON_TITLE38 = "Fan von %s";
UNITNAME_SUMMON_TITLE39 = "Böser Zwilling von %s";
UNITNAME_SUMMON_TITLE4 = "Totem von %s";
UNITNAME_SUMMON_TITLE40 = "Gier von %s";
UNITNAME_SUMMON_TITLE41 = "Verlorener Verstand von %s";
UNITNAME_SUMMON_TITLE42 = "Paktgebundener Beschützer von %s";
UNITNAME_SUMMON_TITLE43 = "Mechanoid von %s";
UNITNAME_SUMMON_TITLE44 = "%s, Diener von N'Zoth";
UNITNAME_SUMMON_TITLE45 = "Assassine von %s";
UNITNAME_SUMMON_TITLE46 = "Wildsamen von %s";
UNITNAME_SUMMON_TITLE47 = "Provost von %s";
UNITNAME_SUMMON_TITLE48 = "Repariert von %s";
UNITNAME_SUMMON_TITLE5 = "Gefährte von %s";
UNITNAME_SUMMON_TITLE6 = "Runenklinge von %s";
UNITNAME_SUMMON_TITLE7 = "Konstrukt von %s";
UNITNAME_SUMMON_TITLE8 = "Gegner von %s";
UNITNAME_SUMMON_TITLE9 = "Fahrzeug von %s";
]]
local methods_guid = {}
local scanIds = { 1, 2, 3, 7, 9, 26, 29}
local scanTip = CreateFrame("GameTooltip", format("%s_ScanTooltip",name), nil, "GameTooltipTemplate")
scanTip:SetOwner( WorldFrame, "ANCHOR_NONE" )
function methods_guid:scanTooltip()
if(self:HasOwner()) then return end
local guid = self['guid']
local text = _G[format("%s_ScanTooltipTextLeft2",name)]
scanTip:SetOwner(WorldFrame, 'ANCHOR_NONE')
scanTip:SetHyperlink('unit:' .. guid or '')
if(text) then
local text2 = text:GetText()
if(text2) then
for i = 1, #scanIds do
local check = _G[format("UNITNAME_SUMMON_TITLE%i",scanIds[i])]:gsub("%%s", "(.+)"):gsub("[%[%]]", "%%%1")
self['tooltip'] = text2
if(string.find(text2, check)) then
self['tooltip'] = text2
local a,b,c = string.find(text2, check)
if(c) then
local g = UnitGUID(c)
if(g) then
local gio = addon:GetGuidInfo(g)
-- local gip = addon:GetGuidInfo(guid)
self:SetOwner(gio)
return
-- print('found',c,gio['name'], gip['name'])
end
end
end
-- print(text:GetText(), check, guid)
end
end
end
end
local function GetGuid(unit)
if(unit) then
local guid = UnitGUID(unit)
if(guid and guid ~= "") then
return guid
end
end
end
function methods_guid:IsParty()
return self['isParty']
end
function methods_guid:SetName(newName)
self['name'] = newName
local nameSplit, serverSplit = strsplit('-',self['name'],2)
if(not serverSplit) then
serverSplit = GetNormalizedRealmName()
end
self['shortName'] = nameSplit
self['shortRealm'] = serverSplit
end
function methods_guid:IsPet()
return self['isPet']
end
function methods_guid:HasOwner()
return self['ownerName'] or false
end
function methods_guid:SetOwner(gi)
-- print("set owner", self['name'], gi['name'])
self['isPet'] = true
if(gi) then
self['ownerName'] = gi['name']
self['ownerGuid'] = gi['guid']
if(gi:IsParty())then
self['isParty'] = true
end
end
end
local function checkPet(unit)
local guid = GetGuid(unit)
if(guid) then
local unitName, unitRealm = UnitFullName(unit)
local _, unitClass = UnitClass(unit)
local o = addon:GetGuidInfo(guid, nil, unitRealm and format("%s-%s", unitName, unitRealm) or unitName, unitClass)
o['isParty'] = true
local pet = format("%sPET", unit)
local pguid = GetGuid(pet)
if(pguid) then
local p = addon:GetGuidInfo(pguid)
p['isParty'] = true
p:SetOwner(o)
end
return guid
end
end
local function assocOwner(guid, petguid)
local gio = addon:GetGuidInfo(guid)
local gip = addon:GetGuidInfo(petguid)
gip:SetOwner(gio)
end
local function group_helper(guids, endcount, unitbase)
for i = 1, endcount do
local guid = UnitGUID(format("%s%i", unitbase, i))
if(guid) then
guids[guid] = true
local petguid = UnitGUID(format("%s%ipet", unitbase, i))
if(petguid) then
assocOwner(guid, petguid)
guids[petguid] = true
end
end
end
return guids
end
function addon:GetGroupGuid(guids)
guids = guids or {}
if(IsInRaid()) then
guids = group_helper(guids, MAX_RAID_MEMBERS, 'raid')
elseif(IsInGroup()) then
guids = group_helper(guids, 4, 'party')
local guid = UnitGUID('player')
if(guid) then
guids[guid] = true
local petguid = UnitGUID('pet')
if(petguid) then
assocOwner(guid, petguid)
guids[petguid] = true
end
end
else
local guid = UnitGUID('player')
if(guid) then
guids[guid] = true
local petguid = UnitGUID('pet')
if(petguid) then
assocOwner(guid, petguid)
guids[petguid] = true
end
end
end
return guids
end
function addon:CheckUnit(unit)
if(unit) then
return checkPet(unit)
end
end
function addon:UNIT_TARGET(event, unit)
local trg = format("%starget", unit)
local guid = GetGuid(trg)
if(guid) then
local _, class = UnitClass(trg)
local fullName, realm = UnitFullName(trg)
local gi = addon:GetGuidInfo(guid, nil, realm and format("%s-%s", fullName, realm) or fullName, class)
local clf = UnitClassification(trg)
-- print(trg, clf, UnitLevel(trg))
if(clf == 'elite') then
if(UnitLevel(trg) == -1) then
gi['isBoss'] = true
end
end
-- print('gi',gi['class'])
if(not gi['class']) then
-- print('find class')
local _, class = UnitClass(trg)
if(class) then
print('found class',class)
gi['class'] = class
end
end
end
end
local function purgeGroupMember()
-- if(true) then return end -- dont purge to keep data intact
local guids = addon:GetGroupGuid()
guids = addon:GetSegmentsGuid(guids)
for guid, v in pairs(guidInfo) do
if(not guids[k]) then
guidInfo[guid]['isParty'] = nil
end
end
end
function addon:RAID_ROSTER_UPDATE()
purgeGroupMember()
for i = 1, MAX_RAID_MEMBERS do
checkPet(format("raid%i", i))
end
end
function addon:GROUP_ROSTER_UPDATE()
purgeGroupMember()
for i = 1, 4 do
checkPet(format('party%i', i))
end
checkPet('player')
end
local purgeTime = {
['Player'] = 3600 * 24,
['Pet'] = 3600,
['Creature'] = 3600
}
function addon:PurgeGuidInfo()
local guids = addon:GetGroupGuid()
--[[ for k, v in pairs(guids) do
local gi = addon:GetGuidInfo(k)
if(gi) then
local localizedClass, englishClass, localizedRace, englishRace, sexGuid, nameGuid, realmGuid = GetPlayerInfoByGUID(k)
-- print(nameGuid, englishClass, k, gi:IsPet())
end
end]]
guids = addon:GetSegmentsGuid(guids)
for k, v in pairs(guidInfo) do
if(not guids[k]) then
-- print(guidInfo[k]['name'],'purged')
guidInfo[k] = nil
end
end
return guidInfo
end
function addon:GetGuidInfoDB()
return guidInfo
end
function addon:SetGuidInfoDB(db)
if(db and type(db) == 'table') then
guidInfo = db
end
return guidInfo
end
function addon:GetGuidInfo(guid, unitFlag, unitName, unitClass)
if(guid and guid ~= '') then
if(not guidInfo[guid] or not guidInfo[guid]['name']) then
if(guid == 'Unknown') then
guidInfo[guid] = {
['added'] = time(),
['isParty'] = false,
['isPet'] = false,
['name'] = "<Unknown>",
['guid'] = guid,
['class'] = 'WARRIOR',
}
else --if(UnitFlag and bit.band(UnitFlag, COMBATLOG_OBJECT_TYPE_PLAYER) ~= 0) then
local localizedClass, englishClass, localizedRace, englishRace, sexGuid, nameGuid, realmGuid = GetPlayerInfoByGUID(guid)
-- print("gg",guid, unitFlag, unitName, " = ", nameGuid, realmGuid)
-- print(UnitName, nameGuid, realmGuid,format("%s-%s", nameGuid, realmGuid),format("%s-%s", nameGuid, realmGuid) ~= UnitName)
if(nameGuid) then
if(not realmGuid or realmGuid=='') then
realmGuid = GetNormalizedRealmName()
end
guidInfo[guid] = {
['added'] = time(),
['name'] = realmGuid and format("%s-%s", nameGuid, realmGuid) or nameGuid,
['guid'] = guid,
['class'] = englishClass,
['classLocal'] = localizedClass,
['race'] = englishRace,
['raceLocal'] = localizedRace,
}
end
end
if(not guidInfo[guid]) then
guidInfo[guid] = {
['added'] = time(),
['name'] = unitName,
['guid'] = guid,
['flags'] = unitFlag
}
end
end
for k, v in pairs(methods_guid) do
guidInfo[guid][k] = v
end
if(unitClass and not guidInfo[guid]['class']) then
guidInfo[guid]['class'] = unitClass
end
if(guidInfo[guid]['name'] and not guidInfo[guid]['shortName']) then
guidInfo[guid]:SetName(guidInfo[guid]['name'])
end
if(not guidInfo[guid]['classColor']) then
guidInfo[guid]['classColor'] = addon:GetClassColors(guidInfo[guid]['class'])
end
-- guidInfo[guid]:scanTooltip()
return guidInfo[guid]
end
end

1
Libs/LibCombatlog Submodule

@ -0,0 +1 @@
Subproject commit b20f7ecfb0b98006d158ed372d0025fb9ec887bc

470
Quicklog.lua Normal file
View File

@ -0,0 +1,470 @@
local name, addon = ...
addon.f = CreateFrame("Frame")
local bit = bit
local segStarted = false
local COMBATLOG_OBJECT_AFFILIATION_OUTSIDER = COMBATLOG_OBJECT_AFFILIATION_OUTSIDER
local function purgeDB(tbl)
for k, v in pairs(tbl) do
if(type(v) == 'table') then
tbl[k] = purgeDB(v)
elseif(type(v) == 'function') then
tbl[k] = nil
end
end
return tbl
end
local dbdefaults = {
['maxSegments'] = 5,
['maxTooltipSpells'] = 6,
['maxTooltipUnits'] = 5,
['currentSegment'] = 0,
['dbversion'] = 1
}
local dbfunc = {}
function dbfunc:Get(key, id)
if(key) then
if(key == 'segments') then
return self['segments']
elseif(key == 'segment' and type(id) == 'number' and id > 0 and self['segments'][id]) then
return self['segments'][id]
else
if(type(self['settings'][key])~='nil') then
return self['settings'][key]
else
if(type(dbdefaults[key])~='nil') then
return dbdefaults[key]
end
end
end
end
end
function dbfunc:Set(key, value, id)
if(key) then
if(key == 'segments' and type(value) == 'table') then
self['segments'] = value
elseif(key == 'segment' and type(id) == 'number' and id > 0 and self['segments'][id] and type(value) == 'table') then
self['segments'][id] = value
else
if(value == dbdefaults[key]) then
self['settings'][key] = nil
else
self['settings'][key] = value
end
end
end
end
function addon:PLAYER_LOGOUT(event)
QuicklogDB['GuidDB'] = addon:PurgeGuidInfo()
QuicklogDB = purgeDB(QuicklogDB)
-- QuicklogDB['GuidDB'] = nil
end
local function processPet(UnitFlag, UnitName, guid, clot)
if(guid) then
local gi = addon:GetGuidInfo(guid, UnitFlag, UnitName)
if(gi['isPet'] ~= nil) then
return gi['isPet']
end
if(UnitFlag and bit.band(UnitFlag, COMBATLOG_OBJECT_TYPE_PET) > 0) then
gi['isPet'] = true
return true
else
gi['isPet'] = false
end
end
end
local pet_clots = {COMBATLOG_OBJECT_TYPE_PET, COMBATLOG_OBJECT_TYPE_GUARDIAN, COMBATLOG_OBJECT_TYPE_OBJECT}
function addon:IsPet(UnitFlag, UnitName, guid)
local gi = addon:GetGuidInfo(guid, UnitFlag, UnitName)
for i = 1, #pet_clots do
processPet(UnitFlag, UnitName, guid, pet_clots[i])
if(gi['isPet'] == true) then break end
end
return gi['isPet']
end
function addon:IsInParty(UnitFlag, UnitName, guid)
--print("UF", UnitFlag, guid, data)
if(guid) then
local gi = addon:GetGuidInfo(guid, UnitFlag, UnitName)
if(gi) then
if(gi['isParty'] ~= nil) then
return gi['isParty']
end
if(UnitFlag and bit.band(UnitFlag, COMBATLOG_OBJECT_AFFILIATION_OUTSIDER) == 0) then
gi['isParty'] = true
return true
else
gi['isParty'] = false
end
end
end
end
local function init(seg, data)
print('initSeg', data and #data)
if(data) then
-- print(unpack(data))
end
seg['startevent'] = data
return seg
end
local computeAllowed = {
'DAMAGE','HEAL','ABSORBED',
}
local function canCompute(typ)
for i = 1, #computeAllowed do
if(computeAllowed[i] == typ) then
return true
end
end
end
local function NoSource(data)
if(data[3] == "ENVIRONMENTAL_DAMAGE" or data[3] == "ENVIRONMENTAL_HEAL") then
-- print('aoe',data[3])
local store = addon:GetStore(addon:GetSegment())
return store:GetSource(data[9], data, 9, true)
end
end
local function computeEvent(data, prefix, suffix)
-- local prefix, suffix = unpack(addon:SplitCLEvent(data[3]))
if(canCompute(suffix)) then
local res = addon:GetSegment()
local store = addon:GetStore(res)
local source = store:GetSource(data[5], data)
if(not source) then
source = NoSource(data)
if(not source) then
source = store:GetSourceEmpty(data)
end
end
local dest = source:GetDestination(data[9])
if(suffix == 'DAMAGE') then
local spellId, spellName, spellSchool, environmentalType
local amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand
if(prefix == 'ENVIRONMENTAL') then
environmentalType, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand = select(13, unpack(data))
spellId, spellName, spellSchool = 'ENVIRONMENTAL', format('ENVIRONMENTAL (%s)', environmentalType), environmentalType
elseif(prefix == 'SWING') then
amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand = select(13, unpack(data))
spellId, spellName, spellSchool = 'SWING', ACTION_SWING, school
else
spellId, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand = select(13, unpack(data))
end
if(overkill > -1) then
amount = amount - overkill
end
if(resisted or blocked) then
local destSource = store:GetSource(dest['guid'], data)
if(resisted and resisted > 0) then
destSource:addTotal('totalAbsorbed', resisted)
end
if(blocked and blocked > 0) then
destSource:addTotal('totalAbsorbed', blocked)
end
end
if(amount > 0) then
source:addTotal('total', amount)
if(spellId) then
dest:addSpell(spellId, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand)
if(resisted or blocked) then
local destSource = store:GetSource(dest['guid'], data)
local destSourceDest = destSource:GetDestination(dest['guid'])
if(resisted and resisted > 0) then
destSourceDest:addAbsorbSpell('RESISTED', 'RESISTED', 1, resisted)
end
if(blocked and blocked > 0) then
destSourceDest:addAbsorbSpell('BLOCKED', 'BLOCKED', 1, blocked)
end
end
end
else
print("no amount")
print(unpack(data))
end
elseif(suffix == 'ABSORBED') then
local spellId, spellName, spellSchool, extraGUID, extraName, extraFlags, extraRaidFlags, extraSpellID, extraSpellName, extraSchool, amount
if(#data == 24) then
spellId, spellName, spellSchool, extraGUID, extraName, extraFlags, extraRaidFlags, extraSpellID, extraSpellName, extraSchool, amount = select(13, unpack(data))
else
extraGUID, extraName, extraFlags, extraRaidFlags, extraSpellID, extraSpellName, extraSchool, amount = select(13, unpack(data))
spellId, spellName, spellSchool = 'SWING', ACTION_SWING, nil
end
if(amount > 0 and extraGUID) then
if(type(data[13]) ~= 'number') then
local extraSource = store:GetSource(extraGUID, data, 13, true)
local dest2 = extraSource:GetDestination(data[9])
extraSource:addTotal('totalAbsorbed', amount)
-- dest2:addTotal('totalAbsorbed', amount)
if(extraSpellID) then
dest2:addAbsorbSpell(extraSpellID, extraSpellName, extraSchool, amount)
end
else
-- print("es", data[13], data[14], data[15])
end
end
elseif(suffix == 'HEAL') then
local spellId, spellName, spellSchool, amount, overhealing, absorbed, critical = select(13, unpack(data))
if(overhealing > 0) then
amount = amount - overhealing
source:addTotal('totalOverheal', overhealing)
end
if(absorbed > 0) then
amount = amount - absorbed
end
if(amount > 0) then
source:addTotal('totalHeal', amount)
if(spellId) then
dest:addHealSpell(spellId, spellName, spellSchool, amount, overhealing, absorbed, critical)
-- dest:addTotal('totalHeal', amount)
else
print("no sid")
end
end
end
-- store:Store()
else
print('skip', data[3], suffix)
end
data = nil
end
local function startSegment(data)
segStarted = true
addon:NewSegment(init, data)
addon:UpdateWindows()
end
local function stopSegment(...)
if(segStarted) then
addon:UpdateWindows()
segStarted = false
addon:PurgeGuidInfo()
addon:GetSegment():stop()
else
print("stop not", ...)
end
end
local throttleUpdate,trottleDelay = time(), 0.4
function addon:summon(data, prefix, suffix)
local summon = addon:GetGuidInfo(data[9], data[11], data[10])
if(not summon:HasOwner()) then
summon:scanTooltip()
local owner = addon:GetGuidInfo(data[5], data[7], data[6])
summon:SetOwner(owner)
end
-- summon['isPet'] = true
-- summon['ownerFlags'] = data[7]
-- summon['ownerName'] = data[6]
-- summon['ownerGuid'] = data[5]
-- addon:IsInParty(data[11], data[10], data[9])
end
local function prepData(data, offset)
local offset = offset or 5
if(data[offset + 1]) then
local gis = addon:GetGuidInfo(data[offset], data[offset + 2], data[offset + 1])
if(segStarted and gis['isBoss']) then
QuicklogDB['segments'][#QuicklogDB['segments']]['hasBoss'] = true
QuicklogDB['segments'][#QuicklogDB['segments']]['BossNames'][data[offset]] = data[offset + 1]
end
-- print('petc')
if(gis['isPet'] == nil) then
-- print('petc not yet',data[offset + 2], data[offset + 1], data[offset])
addon:IsPet(data[offset + 2], data[offset + 1], data[offset])
end
if(gis:IsPet()) then
-- print('pet found', gis['name'], gis['ownerName'])
if(not gis['ownerGuid']) then
-- print('pet found, no owner', gis['name'], gis['ownerName'])
gis:scanTooltip()
end
if(gis['ownerGuid']) then
-- print('rewrite', gis['name'], gis['ownerName'])
data[offset + 2] = gis['ownerFlags']
data[offset + 1] = gis['ownerName']
data[offset] = gis['ownerGuid']
end
else
-- print("no pet", gis['name'])
end
end
return data
end
function addon:dmg(data, prefix, suffix)
--[[ [1] = event,
[2] = time,
[3] = type,
[4] = hideCaster,
[5] = sourceGUID,
[6] = sourceName,
[7] = sourceFlags,
[8] = sourceRaidFlags,
[9] = destGUID,
[10] = destName,
[11] = destFlags,
[12] = destRaidFlags,
]]
if(not segStarted and not data[6]) then
-- print('environmental/aoe?', data[3], data[10])
return
end
-- if(addon:IsInParty(data[7],data[5]) or addon:IsInParty(data[11], data[9])) then
data = prepData(data, 5)
data = prepData(data, 9)
if(not segStarted) then
local gis = addon:GetGuidInfo(data[5], data[7], data[6])
if(gis and not gis['died'] and not (suffix == 'HEAL') and not(prefix == 'ENVIRONMENTAL')) then
local gid = addon:GetGuidInfo(data[9], data[11], data[10])
-- if(addon:IsInParty(data[7], data[6], data[5])) then
if(gis:IsParty()) then
if(gis['guid'] and gid['guid'] and gis['guid'] ~= gid['guid']) then
startSegment(data)
end
end
end
end
if(segStarted) then
computeEvent(data, prefix, suffix)
if(time()>throttleUpdate) then
throttleUpdate = data[2] + trottleDelay
addon:UpdateWindows()
end
end
end
function addon:BOSS_KILL(event, encounterID, encounterName)
print("boss kill", encounterID, encounterName)
end
function addon:ENCOUNTER_END(event, encounterID, encounterName, difficultyID, groupSize, success)
print(event, encounterID, encounterName, difficultyID, groupSize)
addon:UpdateWindows()
stopSegment(event, encounterID, encounterName, difficultyID, groupSize, success)
self:UnregisterEvent(event)
self:RegisterEvent('ENCOUNTER_START')
end
function addon:ENCOUNTER_START(event, encounterID, encounterName, difficultyID, groupSize)
print(event, encounterID, encounterName, difficultyID, groupSize)
if(not segStarted) then
startSegment()
end
local seg = addon:GetSegment()
seg['isEncounter'] = true
seg['encounter'] = {encounterID, encounterName, difficultyID, groupSize}
self:RegisterEvent("ENCOUNTER_END")
self:UnregisterEvent(event)
end
function addon:SCENARIO_COMPLETED(event, questID, xp, money)
print("scenario end", event, questID, xp, money)
stopSegment(event, questID, xp, money)
end
function addon:UNIT_EXITED_VEHICLE(event, unit)
-- print("uev", event, unit)
if(unit=='player') then
stopSegment(event, unit)
end
end
function addon:UNIT_NAME_UPDATE(event, unit)
local gi = addon:GetGuidInfo(UnitGUID(unit))
if(gi) then
gi:SetName(UnitName(unit))
end
end
function addon:PLAYER_ENTERING_WORLD(event, isInitialLogin, isReloadingUi)
print("PEW")
if(not isInitialLogin and not isReloadingUi) then
stopSegment(event, isInitialLogin, isReloadingUi)
end
end
function addon:cmbStatus(event)
-- print(event)
if(event=='PLAYER_REGEN_ENABLED') then
if(segStarted and not addon:GetSegment()['isEncounter']) then
if(not UnitIsDeadOrGhost('PLAYER')) then
stopSegment(event)
end
end
elseif(event=='PLAYER_REGEN_DISABLED') then
if(not segStarted) then
startSegment()
end
end
end
function addon:died(data)
-- print(unpack(data))
if(data[9] and data[10]) then
local gi = addon:GetGuidInfo(data[9], data[11], data[10])
gi['died'] = gi['died'] or {}
gi['died'][#gi['died'] + 1] = data
gi['dead'] = true
end
end
function addon:resurrect(data)
-- local gis = addon:GetGuidInfo(data[5], data[7], data[6])
-- print('res', gis['name'])
if(data[9] and data[10]) then
local gi = addon:GetGuidInfo(data[9], data[11], data[10])
-- print('res dest', gi['name'])
gi['resurrect'] = gi['resurrect'] or {}
gi['resurrect'][#gi['resurrect'] + 1] = data
gi['dead'] = nil
end
end
addon['f']:SetScript("OnEvent", function(self, event, arg1, ...)
if(event == "ADDON_LOADED" and arg1 == name) then
QuicklogDB = QuicklogDB or {
['segments'] = {},
['settings'] = {},
}
for k,v in pairs(dbfunc) do
QuicklogDB[k] = v
end
if(QuicklogDB['GuidDB']) then
addon:SetGuidInfoDB(QuicklogDB['GuidDB'])
end
self:UnregisterEvent(event)
local seg = addon:GetSegment()
-- seg['end'] = time()
if(not seg['end']) then
print('seg is running')
segStarted = true
else
print('no seg running')
addon:PurgeGuidInfo()
end
LibStub("LibCombatLog"):Embed(addon)
addon:RegisterCLEvent({'UNIT_DIED', 'UNIT_DESTROYED', 'UNIT_DISSIPATES'}, 'died')
addon:RegisterCLSuffix({'DAMAGE','HEAL','ABSORBED'}, 'dmg')
addon:RegisterCLSuffix({'SUMMON', 'CREATE'}, 'summon')
addon:RegisterCLSuffix({'RESURRECT'}, 'resurrect')
addon:RegisterCLStatus('cmbStatus')
addon:UpdateWindows()
elseif(type(addon[event]) == 'function') then
addon[event](self, event, arg1, ...)
else
print('else',event, arg1, ...)
end
end)
addon['f']:RegisterEvent("ADDON_LOADED")
addon['f']:RegisterEvent("PLAYER_LOGOUT")
addon['f']:RegisterEvent("RAID_ROSTER_UPDATE")
addon['f']:RegisterEvent("GROUP_ROSTER_UPDATE")
addon['f']:RegisterEvent("UNIT_TARGET")
addon['f']:RegisterEvent("ENCOUNTER_START")
addon['f']:RegisterEvent("UNIT_NAME_UPDATE")
--[[addon['f']:RegisterEvent("PLAYER_GAINS_VEHICLE_DATA") -- ?
addon['f']:RegisterEvent("PLAYER_LOSES_VEHICLE_DATA") -- ?
addon['f']:RegisterEvent("SCENARIO_COMPLETED") -- ?
addon['f']:RegisterEvent("PLAYER_ENTERING_WORLD") -- ?
addon['f']:RegisterEvent("WORLD_QUEST_COMPLETED_BY_SPELL") -- ?
addon['f']:RegisterEvent("QUEST_COMPLETE") -- ?
addon['f']:RegisterEvent("PLAYER_CONTROL_GAINED") -- ?
addon['f']:RegisterEvent("TASK_PROGRESS_UPDATE") -- ?
addon['f']:RegisterEvent("INSTANCE_ENCOUNTER_OBJECTIVE_COMPLETE") -- ?
addon['f']:RegisterEvent("SCENARIO_UPDATE") -- ?
]]
addon['f']:RegisterEvent("UNIT_EXITED_VEHICLE") -- Marasius

12
Quicklog.toc Normal file
View File

@ -0,0 +1,12 @@
## Interface: 90002
## Name: Quicklog
## SavedVariables: QuicklogDB
## Description: Combatlog display
Libs/LibCombatlog/Libstub/Libstub.lua
Libs/LibCombatlog/LibCombatlog.lua
GuidInfo.lua
Quicklog.lua
DataStore.lua
Segments.lua
Statusbars.lua
Window.lua

104
Segments.lua Normal file
View File

@ -0,0 +1,104 @@
local name, addon = ...
function addon:GetSegment(sid)
if(not sid or not QuicklogDB['segments'][sid]) then
sid = #QuicklogDB['segments']
end
return QuicklogDB['segments'][sid]
end
local segfunc = {}
function segfunc:add(data)
self['events'][#self['events']+1] = data
end
function segfunc:refresh(purge)
QuicklogDB['segments'][#QuicklogDB['segments']] = self
if(purge) then
for i = 1, #QuicklogDB['segments'] do
for k, v in pairs(QuicklogDB['segments'][i]) do
if(type(v) == 'function') then
-- QuicklogDB['segments'][i][k] = nil
end
end
for a, b in pairs(QuicklogDB['segments'][i]['source']) do
QuicklogDB['segments'][i]['source'][a]['store'] = nil
for c, d in pairs(b) do
if(type(d) == 'function' or c == 'data') then
QuicklogDB['segments'][i]['source'][a][c] = nil
end
end
for e, f in pairs(b['dest']) do
QuicklogDB['segments'][i]['source'][a]['dest'][e]['source'] = nil
for g, h in pairs(f) do
if(type(h) == 'function') then
-- QuicklogDB['segments'][i]['source'][a]['dest'][e][g] = nil
end
end
end
end
end
-- for k, v in pairs(segfunc) do
-- QuicklogDB['segments'][#QuicklogDB['segments']][k] = nil
-- end
end
end
function segfunc:stop()
print('stop seg')
self['end'] = time()
self:refresh(true)
end
function segfunc:GetBoss()
for k, v in pairs(self['BossNames']) do
return {k, self['BossNames'][k]}
end
end
function segfunc:GetSegmentGuid(guids)
guids = guids or {}
for c, d in pairs(self['source']) do
if(addon:IsInParty(d['flags'], d['name'], d['guid'])) then
for k, v in pairs(d['dest']) do
guids[k] = true
end
guids[c] = true
end
end
return guids
end
function addon:GetSegmentsGuid(guids)
guids = guids or {}
for i = 1, #QuicklogDB['segments'] do
local seg = QuicklogDB['segments'][i]
for k, v in pairs(segfunc) do
seg[k] = v
end
guids = seg:GetSegmentGuid(guids)
end
return guids
end
local function Renumerate()
for i = 1, #QuicklogDB['segments'] do
QuicklogDB['segments'][i]['num'] = i
end
end
function addon:NewSegment(init, data)
QuicklogDB['segments'][#QuicklogDB['segments'] + 1] = {
['begin'] = time(),
['source'] = {},
['BossNames'] = {}
}
-- QuicklogDB['segments'][#QuicklogDB['segments']]['res'] = CopyTable(defaultEvent)
while(#QuicklogDB['segments'] > QuicklogDB:Get('maxSegments')) do
-- print('rm segment')
tremove(QuicklogDB['segments'], 1)
end
for k, v in pairs(segfunc) do
QuicklogDB['segments'][#QuicklogDB['segments']][k] = v
end
Renumerate()
if(type(init) == 'function') then
return init(self:GetSegment(#QuicklogDB['segments']), data)
end
return self:GetSegment(#QuicklogDB['segments'])
end

146
Statusbars.lua Normal file
View File

@ -0,0 +1,146 @@
local name, addon = ...
local f = CreateFrame('FRAME', nil, UIParent)
local bars = {}
local function layoutProto(self)
-- print('val', self:GetValue(), self:GetMinMaxValues())
if(tonumber(self:GetValue())==0) then
self:Hide()
else
self:Show()
end
end
local layouts = {
['defaultLayout'] = {
['texture'] = "Interface\\TargetingFrame\\UI-StatusBar",
['tile'] = false,
['width'] = 160,
['height'] = 16,
['value'] = 100,
['color'] = { 1, 1, 1, 1 },
['script'] = layoutProto,
}
}
local tip = CreateFrame("GameTooltip", format("%s_tooltip", name), nil, "GameTooltipTemplate")
tip:SetScale(0.75)
local function OnEnter(self)
tip:ClearLines()
tip:SetOwner(self, "ANCHOR_CURSOR");
self.tooltip = tip
local p = self:GetParent()
if(p.StatusBarOnEnter and type(p.StatusBarOnEnter) == 'function') then
p:StatusBarOnEnter(self)
end
tip:Show()
end
local function OnLeave(self)
local p = self:GetParent()
if(p.StatusBarOnLeave and type(p.StatusBarOnLeave) == 'function') then
p:StatusBarOnLeave(self)
end
self.tooltip:Hide()
self.tooltip = nil
end
local bar_methods = {}
function bar_methods:Release()
self['active'] = false
self['class'] = nil
self:Hide()
end
function bar_methods:SetText(text, text2)
if(text) then
self['fontstring']:SetText(text)
end
if(text2) then
self['fontstring2']:SetText(text2)
end
end
function addon:GetClassColors(class, undef)
if(class) then
if(RAID_CLASS_COLORS[class]) then
local col = RAID_CLASS_COLORS[class]
return {col['r'], col['g'], col['b'], col['a'] or 1, undef}
end
end
return self:GetClassColors('WARRIOR', true)
end
function bar_methods:SetColorByClass(class)
local r, g, b, a, u = unpack(addon:GetClassColors(class))
if(not u) then
self['class'] = class
else
self['class'] = nil
end
self:SetStatusBarColor(r, g, b, a)
end
function bar_methods:GetText()
return self['fontstring']:GetText()
end
function bar_methods:GetText2()
return self['fontstring2']:GetText()
end
function bar_methods:SetLayout(layout)
if(not layout or not layouts[layout]) then
layout = 'defaultLayout'
end
local d = layouts['defaultLayout']
local l = layouts[layout]
self:SetScript("OnEnter", OnEnter)
self:SetScript("OnLeave", OnLeave)
self:SetStatusBarTexture(l['texture'] or d['texture'])
self:GetStatusBarTexture():SetHorizTile(l['tile'] or d['tile'])
self:SetValue(l['value'] or d['value'])
self:SetWidth(l['width'] or d['width'])
self:SetHeight(l['height'] or d['height'])
self:SetScript("OnValueChanged", l['script'] or d['script'])
self:SetPoint("CENTER")
self:SetStatusBarColor((l['color'] and unpack(l['color']) or unpack(d['color'])))
self['fontstring'] = self:CreateFontString(nil, "OVERLAY", "TextStatusBarText")
self['fontstring']:ClearAllPoints()
self['fontstring']:SetAllPoints(self)
self['fontstring']:SetText(" *.*")
self['fontstring']:SetJustifyH('LEFT')
self['fontstring2'] = self:CreateFontString(nil, "OVERLAY", "TextStatusBarText")
self['fontstring2']:ClearAllPoints()
self['fontstring2']:SetAllPoints(self)
self['fontstring2']:SetText(" 0")
self['fontstring2']:SetJustifyH('RIGHT')
self:Show()
return self
end
function addon:IsStatusBarActive(bid)
if(bars[bid] and bars[bid]['active']) then
return true
end
end
function addon:CreateStatusBar(layout)
-- print("Create bar",format("%s_Statusbar_%i",name,#bars + 1))
local bar = CreateFrame("StatusBar",format("%s_Statusbar_%i",name,#bars + 1),f)
for method, func in pairs(bar_methods) do
bar[method] = func
end
return bar:SetLayout(layout)
end
function addon:GetStatusBar(bid)
if(not bid or type(bid) ~= 'number' or bid > #bars) then
for i = 1, #bars do
if(not bars[i]['active']) then
bid = i
break
end
end
if(not bid) then
bid = #bars + 1
end
end
-- if(addon:IsStatusBarActive(bid)) then
if(not bars[bid]) then
bars[bid] = addon:CreateStatusBar()
end
bars[bid]['active'] = true
-- else
-- print("Bar not active")
-- end
-- print("Bar", bid, bars[bid])
return bars[bid]
end

411
Window.lua Normal file
View File

@ -0,0 +1,411 @@
local name, addon = ...
local f = CreateFrame("Frame", nil, UIParent)
local window_methods = {}
local displays = { 'DAMAGE', 'HEAL', 'ABSORBED' }
local display_methods = {}
local defaultWindow = {
['active'] = true,
['show'] = true,
['bars'] = {},
['display'] = 'DAMAGE',
}
local windows = {}
local function sort_total(a, b)
return a['total'] > b['total']
end
local function sort_totalHeal(a, b)
return a['totalHeal'] > b['totalHeal']
end
local function sort_totalAbsorbed(a, b)
return a['totalAbsorbed'] > b['totalAbsorbed']
end
local sorts = {
['total'] = sort_total,
['totalHeal'] = sort_totalHeal,
['totalAbsorbed'] = sort_totalAbsorbed,
}
local function releaseBars(bars, num)
while(num < #bars) do
local bar = bars[num + 1]
tremove(bars, num + 1)
bar['lastPos'] = nil
bar['class'] = nil
bar:Release()
end
return bars
end
local function GetSegmentId(seg)
for i = 1, #QuicklogDB['segments'] do
if(QuicklogDB['segments'][i] == seg) then
return i
end
end
return #QuicklogDB['segments']
end
local function defaultDisplay(win, total)
local seg = win['seg']
if(seg) then
local store = addon:GetStore(seg)
-- print('s',seg)
local src = {}
local maxtotal = 0
for c, d in pairs(seg['source']) do
if(d[total] > 0 and addon:IsInParty(d['flags'], d['name'], d['guid'])) then
if(d[total]>maxtotal) then
maxtotal = d[total]
end
src[#src + 1] = d
end
end
-- print('src', #src)
sort(src, sorts[total])
local last = win
local h1 = win:GetHeight()
local maxBars = win:GetMaxBars()
-- print("bars",#src, maxBars)
for i = 1, #src do
local d = src[i]
local bar = win:GetBar(i)
local guid = d['guid']
bar['guid'] = guid
local gib = addon:GetGuidInfo(guid)
if(bar['class'] ~= gib['class']) then
bar:SetColorByClass(gib['class'])
end
if(bar['lastPos'] ~= i) then
bar['lastPos'] = i
bar:ClearAllPoints()
bar:SetPoint("TOPLEFT", win, "TOPLEFT", 14, (bar:GetHeight() * i * - 1) + 2)
end
bar:SetMinMaxValues(0, maxtotal)
bar:SetValue(d[total])
bar:SetText(gib['shortName'] and gib['shortName'] or gib['name'], d[total])
last = bar
if(i >= maxBars) then
break
end
end
win['settings']['bars'] = releaseBars(win['settings']['bars'], #src)
end
end
function display_methods:DAMAGE(win)
defaultDisplay(win, 'total')
end
function display_methods:HEAL(win)
defaultDisplay(win, 'totalHeal')
end
function display_methods:ABSORBED(win)
defaultDisplay(win, 'totalAbsorbed')
end
function window_methods:GetMaxBars()
local h1 = self:GetHeight()
local bar = self:GetBar(1)
local h2 = bar:GetHeight()
local e = h1 - 16 - (h2/2)
local n = (e) / (h2)
local m = floor(n) -- 8 = Insets, 2 y-offset
-- print('heights',h1, h2, 'e', e, 'h', h2*m, 'max',m , n, m*16)
return m
end
function window_methods:GetBar(bid)
if(self['settings']['bars'][bid]) then
return self['settings']['bars'][bid]
else
self['settings']['bars'][#self['settings']['bars'] + 1] = addon:GetStatusBar()
self['settings']['bars'][#self['settings']['bars']]:SetParent(self)
return self['settings']['bars'][#self['settings']['bars']]
end
end
local function defaultTooltip(tooltip, src, total, spells)
local dip = {}
tooltip:AddDoubleLine("Total", src[total], 1, 1, 1, 1, 1, 1)
for guid, dest in pairs(src['dest']) do
if(dest[total]>0) then
dip[#dip + 1] = dest
end
end
if(#dip > 0) then
sort(dip, sorts[total])
for i = 1, #dip do
local dest = dip[i]
local gib = addon:GetGuidInfo(dest['guid'])
if(gib) then
local r, g, b, a, u = unpack(gib['classColor'])
tooltip:AddDoubleLine(gib['name'] and gib['name'] or '<Unbekannt>', dest[total], r, g, b, 1, 1, 1)
if(dest[spells]) then
local tip = {}
for _, spell in pairs(dest[spells]) do
if(spell[total]>0) then
tip[#tip + 1] = spell
end
end
if(#tip > 0) then
sort(tip, sorts[total])
for i = 1, #tip do
local spell = tip[i]
tooltip:AddDoubleLine(format(" %s",spell['spellName']), spell[total])
if(i >= QuicklogDB:Get('maxTooltipSpells')) then
break
end
end
end
tip = nil
end
end
if(i >= QuicklogDB:Get('maxTooltipUnits')) then
break
end
end
end
dip = nil
end
function window_methods:StatusBarOnEnter(bar)
local seg = self['seg']
local store = addon:GetStore(seg)
local src = store:GetSource(bar['guid'], nil, nil, true)
if(not src or not src['name']) then bar:Release() return end
local display = self['settings']['display']
bar['tooltip']:AddLine(format("%s - %s", display, src['name']),1,1,1)
if(display == 'DAMAGE') then
defaultTooltip(bar['tooltip'], src, 'total', 'spells')
elseif(display == 'HEAL') then
defaultTooltip(bar['tooltip'], src, 'totalHeal', 'spellsHeal')
elseif(display == 'ABSORBED') then
defaultTooltip(bar['tooltip'], src, 'totalAbsorbed', 'spellsAbsorbed')
end
end
local function OnResize(self)
local maxBars = self:GetMaxBars()
for i = 1, #self['settings']['bars'] do
local bar = self['settings']['bars'][i]
if(i>maxBars) then
bar:Hide()
else
bar:Show()
end
end
end
function window_methods:StatusBarOnLeave(bar)
--
end
function window_methods:Refresh()
local display = self['settings']['display']
self['title']['text']:SetText(display)
self['footer']['text']:SetText(format("# %i/%i",GetSegmentId(self['seg']),#QuicklogDB['segments']))
if(type(display_methods[display]) == 'function') then
self['seg'] = self['seg'] or addon:GetSegment()
display_methods[display](nil, self)
end
OnResize(self)
-- print(self:GetName(), 'refresh', display)
end
function window_methods:SetSegment(seg)
self['seg'] = seg
self:Refresh()
end
function window_methods:UpdateWindow()
if(not self['seg']) then
self:SetSegment(addon:GetSegment())
else
self:Refresh()
end
-- print("update",self:GetName())
end
function window_methods:Clear()
for i = 1, #self['settings']['bars'] do
local bar = self['settings']['bars'][i]
if(bar) then
bar['src'] = nil
bar:Release()
end
tremove(self['settings']['bars'], i)
end
end
local function StartResize(self, button)
local p = self:GetParent()
p:StartSizing()
self['isMoving'] = true
self['hasMoved'] = false
end
local function StopResize(self)
if(self['isMoving']) then
local p = self:GetParent()
p:StopMovingOrSizing()
self['isMoving'] = false
self['hasMoved'] = true
end
end
local function GetDisplayId(display)
for i=1, #displays do
if(displays[i] == display) then
return i
end
end
return 1
end
local function TitleNavClick(self, button)
local win = self:GetParent():GetParent()
local display = win['settings']['display']
local cur = GetDisplayId(display)
win:Clear()
if(self['nav'] == "LEFT") then
cur = cur - 1
if(cur < 1) then
cur = #displays
end
else
cur = cur + 1
if(cur > #displays) then
cur = 1
end
end
win['settings']['display'] = displays[cur]
win:Refresh()
end
local function FooterNavClick(self, button)
local win = self:GetParent():GetParent()
local cur = GetSegmentId(win['seg'])
win:Clear()
if(self['nav'] == "LEFT") then
cur = cur - 1
if(cur < 1) then
cur = #QuicklogDB['segments']
end
else
cur = cur + 1
if(cur > #QuicklogDB['segments']) then
cur = 1
end
end
win:SetSegment(QuicklogDB['segments'][cur])
win:Refresh()
end
local function titleDragStart(self)
self:GetParent():StartMoving()
end
local function titleDragStop(self)
self:GetParent():StopMovingOrSizing()
end
local function GetWinBar(self, barName, drag, clickFunc)
local title = CreateFrame("Frame", "$parent_"..barName, self, "BackdropTemplate")
self:EnableMouse(true)
title:SetSize(200, 20)
title:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
-- edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true,
tileSize = 32,
edgeSize = 32,
insets = { left = 2, right = 2, top = 2, bottom = 2 }
})
title:EnableMouse(true)
if(drag) then
title:RegisterForDrag("LeftButton")
title:SetScript("OnDragStart", titleDragStart)
title:SetScript("OnDragStop", titleDragStop)
end
title:SetBackdropBorderColor(1, 1, 1, 1)
local b = CreateFrame("BUTTON", "$parent_Left", title, "BackdropTemplate")
b:SetSize(20,20)
b:SetPoint("TOPLEFT", title, "TOPLEFT")
b:SetNormalTexture("Interface\\BUTTONS\\UI-SpellbookIcon-PrevPage-Up")
b:SetPushedTexture("Interface\\BUTTONS\\UI-SpellbookIcon-PrevPage-Down")
b:SetDisabledTexture("Interface\\BUTTONS\\UI-SpellbookIcon-PrevPage-Disabled")
b:SetScript("OnClick", clickFunc)
b['nav'] = "LEFT"
local d = CreateFrame("BUTTON", "$parent_Right", title, "BackdropTemplate")
d:SetSize(20,20)
d:SetPoint("TOPLEFT", b, "TOPRIGHT",-8)
d:SetNormalTexture("Interface\\BUTTONS\\UI-SpellbookIcon-NextPage-Up")
d:SetPushedTexture("Interface\\BUTTONS\\UI-SpellbookIcon-NextPage-Down")
d:SetDisabledTexture("Interface\\BUTTONS\\UI-SpellbookIcon-NextPage-Disabled")
d:SetScript("OnClick", clickFunc)
d['nav'] = "RIGHT"
local c = title:CreateFontString(nil,"OVERLAY","CombatLogFont")
c:ClearAllPoints()
c:SetAllPoints(title)
c:SetPoint("TOPLEFT", d, "TOPRIGHT")
c:SetJustifyH("LEFT")
c:SetText(name)
title['text'] = c
return title
end
function window_methods:AddFooterBar()
self['footer'] = GetWinBar(self, 'Footer', false, FooterNavClick)
self['footer']:SetPoint("TOPLEFT", self, "BOTTOMLEFT")
end
function window_methods:AddTitleBar()
self['title'] = GetWinBar(self, 'Title', true, TitleNavClick)
self['title']:SetPoint("BOTTOMLEFT", self, "TOPLEFT")
end
function addon:GetWindow(windowname)
for i = 1, #windows do
if(windows[i] and windows[i]:GetName() == windowname) then
-- print("Window", windowname)
return windows[i]
end
end
windows[#windows + 1] = CreateFrame("Frame", format("%s_Window_%i", name, #windows + 1),f,"BackdropTemplate")
local win = windows[#windows]
for fname, func in pairs(window_methods) do
win[fname] = func
end
win:AddTitleBar()
win:AddFooterBar()
self['resize'] = CreateFrame("Frame", nil, win)
local btn = self['resize']
btn:SetSize(20,20)
btn:SetPoint("BOTTOMRIGHT",win,"BOTTOMRIGHT")
btn:SetScript("OnMouseDown", StartResize)
btn:SetScript("OnMouseUp", StopResize)
win:SetBackdrop({
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
-- edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true,
tileSize = 32,
edgeSize = 32,
insets = { left = 8, right = 8, top = 8, bottom = 8 }
})
win:SetBackdropColor(0, 0, 0, 1)
win['settings'] = CopyTable(defaultWindow)
win:HookScript("OnSizeChanged", OnResize)
win:SetPoint("CENTER",UIParent,"CENTER")
win:SetSize(200, 400)
win:SetMovable(true)
win:SetResizable(true)
win:SetMinResize(200,200)
win:SetMaxResize(200,800)
win:SetClampedToScreen(true)
win:Show()
win:UpdateWindow()
return win
end
function addon:CreateWindow(windowname)
return self:GetWindow(windowname)
end
function addon:UpdateWindows(seg)
if(#windows == 0) then
self:CreateWindow('DAMAGE')
-- self:CreateWindow('HEAL')
end
for i = 1, #windows do
local win = windows[i]
if(win['settings']['active'] and win:IsVisible()) then
if(seg) then
win:SetSegment(seg)
else
win:SetSegment(addon:GetSegment())
end
win:UpdateWindow()
end
end
end