471 lines
14 KiB
Lua
471 lines
14 KiB
Lua
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
|