The remote was previously a distribution-only point for pre-built DLLs. This opens the source. - LICENSE: Unlicense, with a GPL-3.0 carve-out for src/dpslog/WeirdDPSMate (a DPSMate fork that keeps its own license) - README.md replaces the stale internal one with the user-facing docs from DLL_README.md, swapping the 'Why No Source Code?' section for build and layout notes. DLL_README.md is dropped; one README now serves both. - RELEASING.md: drop the trim-the-README-per-release dance and the remote/WeirdUtils/ distribution clone, both obsolete now - gitignore agent/editor scratch, build caches, the vendored WSBT addon, and the WeirdThreat/uwu-logs checkouts (separate upstream repos) - Commit outstanding module work: superweirdo, clickthrough portal visuals, transform44 decompiles, worldmarkers demo presets, tools/
557 lines
23 KiB
Lua
557 lines
23 KiB
Lua
-- DPSMate CLEU Adapter
|
|
-- Replaces the string-parsing CHAT_MSG_* event system with structured COMBAT_LOG_EVENT_UNFILTERED
|
|
-- data from the DPSLog module. Registers for COMBAT_LOG_EVENT_UNFILTERED and calls DPSMate.DB
|
|
-- functions directly with extracted values.
|
|
--
|
|
-- Toggle: /dpscleu (switches between CLEU adapter and original string parser)
|
|
-- Requires: DPSLog module (provides COMBAT_LOG_EVENT_UNFILTERED + GetSpellInfo)
|
|
|
|
if not DPSMate or not DPSMate.DB then return end
|
|
if not GetWeirdUtilsVersion or not GetWeirdUtilsVersion("dpslog") then return end
|
|
|
|
local DB = DPSMate.DB
|
|
local Parser = DPSMate.Parser
|
|
local GT = GetTime
|
|
local AAttack = DPSMate.L and DPSMate.L["autoattack"] or "Attack"
|
|
|
|
-- ============================================================================
|
|
-- Chat event list (original parser registers these)
|
|
-- ============================================================================
|
|
|
|
local chatEvents = {
|
|
"CHAT_MSG_COMBAT_PET_HITS", "CHAT_MSG_COMBAT_PET_MISSES",
|
|
"CHAT_MSG_SPELL_PET_DAMAGE",
|
|
"CHAT_MSG_COMBAT_SELF_HITS", "CHAT_MSG_COMBAT_SELF_MISSES",
|
|
"CHAT_MSG_SPELL_SELF_DAMAGE",
|
|
"CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE",
|
|
"CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE",
|
|
"CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE",
|
|
"CHAT_MSG_COMBAT_PARTY_HITS", "CHAT_MSG_SPELL_PARTY_DAMAGE",
|
|
"CHAT_MSG_COMBAT_PARTY_MISSES",
|
|
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",
|
|
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",
|
|
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES",
|
|
"CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS",
|
|
"CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES",
|
|
"CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE",
|
|
"CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES",
|
|
"CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE",
|
|
"CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS",
|
|
"CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES",
|
|
"CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE",
|
|
"CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE",
|
|
"CHAT_MSG_SPELL_SELF_BUFF",
|
|
"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS",
|
|
"CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF",
|
|
"CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS",
|
|
"CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF",
|
|
"CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS",
|
|
"CHAT_MSG_SPELL_PARTY_BUFF",
|
|
"CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS",
|
|
"CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF",
|
|
"CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS",
|
|
"CHAT_MSG_SPELL_BREAK_AURA",
|
|
"CHAT_MSG_SPELL_AURA_GONE_SELF",
|
|
"CHAT_MSG_SPELL_AURA_GONE_OTHER",
|
|
"CHAT_MSG_SPELL_AURA_GONE_PARTY",
|
|
"CHAT_MSG_COMBAT_FRIENDLY_DEATH",
|
|
"CHAT_MSG_COMBAT_HOSTILE_DEATH",
|
|
}
|
|
|
|
-- ============================================================================
|
|
-- Toggle state
|
|
-- ============================================================================
|
|
|
|
local cleuActive = false
|
|
local cleuFrame = CreateFrame("Frame")
|
|
|
|
local function enableCLEU()
|
|
-- Disable string parser
|
|
for _, ev in ipairs(chatEvents) do
|
|
Parser:UnregisterEvent(ev)
|
|
end
|
|
-- Enable CLEU
|
|
cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
|
cleuActive = true
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00DPSMate CLEU Adapter|r: |cff00ff00ON|r (structured events)")
|
|
end
|
|
|
|
local function enableOriginal()
|
|
-- Disable CLEU
|
|
cleuFrame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
|
-- Re-enable string parser
|
|
for _, ev in ipairs(chatEvents) do
|
|
Parser:RegisterEvent(ev)
|
|
end
|
|
cleuActive = false
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00DPSMate CLEU Adapter|r: |cffff4444OFF|r (string parser)")
|
|
end
|
|
|
|
local function toggle()
|
|
if cleuActive then
|
|
enableOriginal()
|
|
else
|
|
enableCLEU()
|
|
end
|
|
end
|
|
|
|
SLASH_DPSCLEU1 = "/dpscleu"
|
|
SlashCmdList["DPSCLEU"] = function(msg)
|
|
if msg == "on" then
|
|
if not cleuActive then enableCLEU() end
|
|
elseif msg == "off" then
|
|
if cleuActive then enableOriginal() end
|
|
elseif msg == "status" then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00DPSMate CLEU Adapter|r: " .. (cleuActive and "|cff00ff00ON|r" or "|cffff4444OFF|r"))
|
|
else
|
|
toggle()
|
|
end
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Helper
|
|
-- ============================================================================
|
|
|
|
local function isGroupMember(name)
|
|
if not name or name == "" then return false end
|
|
if name == UnitName("player") then return true end
|
|
for i = 1, GetNumRaidMembers() do
|
|
if name == UnitName("raid" .. i) then return true end
|
|
end
|
|
for i = 1, GetNumPartyMembers() do
|
|
if name == UnitName("party" .. i) then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- (dead handler removed — real handler is cleuHandler below, wrapped by profiling)
|
|
-- ============================================================================
|
|
|
|
-- ============================================================================
|
|
-- Performance profiling
|
|
-- ============================================================================
|
|
|
|
-- debugprofilestop() returns ms since last debugprofilestart().
|
|
-- We call debugprofilestart() once at combat start, then use debugprofilestop()
|
|
-- as a monotonic clock — taking deltas between before/after each handler call.
|
|
-- gcinfo() returns KB.
|
|
|
|
local profiling = false
|
|
local profCLEU = { events = 0, totalMs = 0, gcStart = 0 }
|
|
local profOrig = { events = 0, totalMs = 0, gcStart = 0 }
|
|
|
|
-- Fine-grained timing buckets (microseconds, accumulated)
|
|
local profDetail = { getInfo = 0, dbCalls = 0, dispatch = 0, total = 0, count = 0 }
|
|
-- Per-DB-function timing (microseconds, accumulated)
|
|
local profDB = {
|
|
DamageDone = 0, DamageTaken = 0, EnemyDamage = 0, DeathHistory = 0,
|
|
Healing = 0, HealingTaken = 0, BuildBuffs = 0, Other = 0, count = 0
|
|
}
|
|
local profCurrent = nil
|
|
|
|
-- Hook the parser's OnEvent to measure original mode
|
|
local origOnEvent = DPSMate.Parser:GetScript("OnEvent")
|
|
local function measuredOrigOnEvent()
|
|
if profiling and profCurrent == profOrig then
|
|
local before = debugprofilestop()
|
|
origOnEvent()
|
|
local after = debugprofilestop()
|
|
profOrig.totalMs = profOrig.totalMs + (after - before)
|
|
profOrig.events = profOrig.events + 1
|
|
else
|
|
origOnEvent()
|
|
end
|
|
end
|
|
DPSMate.Parser:SetScript("OnEvent", measuredOrigOnEvent)
|
|
|
|
-- Wrap the CLEU handler similarly
|
|
local cleuHandler -- forward decl
|
|
|
|
local function measuredCLEUHandler()
|
|
if profiling and profCurrent == profCLEU then
|
|
local before = debugprofilestop()
|
|
cleuHandler()
|
|
local after = debugprofilestop()
|
|
profCLEU.totalMs = profCLEU.totalMs + (after - before)
|
|
profCLEU.events = profCLEU.events + 1
|
|
else
|
|
cleuHandler()
|
|
end
|
|
end
|
|
|
|
local function profReset(tbl)
|
|
tbl.events = 0
|
|
tbl.totalMs = 0
|
|
tbl.gcStart = gcinfo()
|
|
end
|
|
|
|
-- debugprofilestop() returns microseconds on this client
|
|
local lastCLEUAvg = nil
|
|
local lastOrigAvg = nil
|
|
|
|
local function profReport(label, tbl)
|
|
local gcEnd = gcinfo()
|
|
local gcDelta = gcEnd - tbl.gcStart
|
|
local totalMs = tbl.totalMs / 1000
|
|
local avgUs = tbl.events > 0 and (tbl.totalMs / tbl.events) or 0
|
|
|
|
-- Store for comparison
|
|
if label == "CLEU" then
|
|
lastCLEUAvg = avgUs
|
|
else
|
|
lastOrigAvg = avgUs
|
|
end
|
|
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"|cff00ff00[%s]|r %d events, %.1fms total, %.1f us/event, %+.1f KB gc",
|
|
label, tbl.events, totalMs, avgUs, gcDelta))
|
|
|
|
-- Detail breakdown for CLEU
|
|
if label == "CLEU" and profDetail.count > 0 then
|
|
local avgGetInfo = profDetail.getInfo / profDetail.count
|
|
local avgDB = profDetail.dbCalls / profDetail.count
|
|
local avgTotal = profDetail.total / profDetail.count
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"|cff00ff00[CLEU detail]|r getInfo=%.1f us, db+logic=%.1f us, total=%.1f us (%d events)",
|
|
avgGetInfo, avgDB, avgTotal, profDetail.count))
|
|
-- Per-DB-function breakdown
|
|
if profDB.count > 0 then
|
|
local n = profDB.count
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"|cff00ff00[DB funcs]|r DD=%.0f DT=%.0f ED=%.0f DH=%.0f H=%.0f HT=%.0f Buf=%.0f Oth=%.0f us/evt",
|
|
profDB.DamageDone/n, profDB.DamageTaken/n, profDB.EnemyDamage/n,
|
|
profDB.DeathHistory/n, profDB.Healing/n, profDB.HealingTaken/n,
|
|
profDB.BuildBuffs/n, profDB.Other/n))
|
|
end
|
|
profDetail.getInfo = 0
|
|
profDetail.dbCalls = 0
|
|
profDetail.total = 0
|
|
profDetail.count = 0
|
|
profDB.DamageDone = 0; profDB.DamageTaken = 0; profDB.EnemyDamage = 0
|
|
profDB.DeathHistory = 0; profDB.Healing = 0; profDB.HealingTaken = 0
|
|
profDB.BuildBuffs = 0; profDB.Other = 0; profDB.count = 0
|
|
end
|
|
|
|
-- If we have both measurements, show comparison
|
|
if lastCLEUAvg and lastOrigAvg and lastOrigAvg > 0 then
|
|
local pct = ((lastCLEUAvg - lastOrigAvg) / lastOrigAvg) * 100
|
|
local sign = pct < 0 and "" or "+"
|
|
local color = pct < 0 and "|cff00ff00" or "|cffff4444"
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"%s[CLEU vs ORIGINAL]|r %.1f vs %.1f us/event = %s%.1f%%|r %s",
|
|
color, lastCLEUAvg, lastOrigAvg, sign, pct,
|
|
pct < 0 and "(CLEU faster)" or "(ORIGINAL faster)"))
|
|
end
|
|
end
|
|
|
|
-- Always-on CLEU profiling: report stats at every combat end.
|
|
-- /dpsbench toggles A/B mode (alternates CLEU/ORIGINAL each combat for comparison).
|
|
local benchActive = false
|
|
|
|
local benchFrame = CreateFrame("Frame")
|
|
|
|
local function combatStart()
|
|
profCurrent = cleuActive and profCLEU or profOrig
|
|
profReset(profCurrent)
|
|
debugprofilestart()
|
|
profiling = true
|
|
if benchActive then
|
|
local label = cleuActive and "CLEU" or "ORIGINAL"
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff00ff00[DPS Bench]|r measuring %s", label))
|
|
end
|
|
end
|
|
|
|
local function combatEnd()
|
|
if not profiling then return end
|
|
profiling = false
|
|
local label = cleuActive and "CLEU" or "ORIGINAL"
|
|
profReport(label, profCurrent)
|
|
if benchActive then
|
|
toggle()
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"|cff00ff00[DPS Bench]|r next combat: %s", cleuActive and "CLEU" or "ORIGINAL"))
|
|
end
|
|
end
|
|
|
|
benchFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
benchFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
benchFrame:SetScript("OnEvent", function()
|
|
if event == "PLAYER_REGEN_DISABLED" then
|
|
combatStart()
|
|
elseif event == "PLAYER_REGEN_ENABLED" then
|
|
combatEnd()
|
|
end
|
|
end)
|
|
|
|
SLASH_DPSBENCH1 = "/dpsbench"
|
|
SlashCmdList["DPSBENCH"] = function()
|
|
benchActive = not benchActive
|
|
if benchActive then
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(
|
|
"|cff00ff00[DPS Bench]|r A/B enabled. Current mode: %s. Enter combat to begin.",
|
|
cleuActive and "CLEU" or "ORIGINAL"))
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[DPS Bench]|r A/B disabled (stats still reported).")
|
|
end
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Wire up CLEU handler with measurement
|
|
-- ============================================================================
|
|
|
|
-- Replace the raw SetScript with the measured wrapper
|
|
cleuFrame:SetScript("OnEvent", function()
|
|
-- This outer function gets replaced below
|
|
end)
|
|
|
|
-- The actual CLEU handler (extracted so we can call it directly or measured)
|
|
local ShieldFlags = DB.ShieldFlags
|
|
local FailDT = DPSMate.Parser.FailDT
|
|
local FailDB = DPSMate.Parser.FailDB
|
|
|
|
cleuHandler = function()
|
|
if not CombatLogGetCurrentEventInfo then return end
|
|
|
|
local t0 = profiling and debugprofilestop()
|
|
|
|
local sub, srcGUID, srcName, srcFlags, srcRaidFlags,
|
|
dstGUID, dstName, dstFlags, dstRaidFlags,
|
|
p1, p2, p3, p4, p5, p6, p7, p8, p9,
|
|
p10, p11, p12 = CombatLogGetCurrentEventInfo()
|
|
if not sub then return end
|
|
|
|
local t1 = profiling and debugprofilestop()
|
|
|
|
if not srcName or srcName == "" then srcName = "Unknown" end
|
|
if not dstName or dstName == "" then dstName = "Unknown" end
|
|
|
|
-- ========================================================================
|
|
-- DAMAGE events
|
|
-- ========================================================================
|
|
|
|
if sub == "SWING_DAMAGE" then
|
|
local amount, absorbed = p1, p6
|
|
local critical, glancing, crushing = p7, p8, p9
|
|
-- numbers always non-nil from CombatLogGetCurrentEventInfo
|
|
local crit = critical and 1 or 0
|
|
local glanc = glancing and 1 or 0
|
|
local crush = crushing and 1 or 0
|
|
local hit = (crit == 0 and glanc == 0 and crush == 0) and 1 or 0
|
|
|
|
local ta, tb
|
|
if profiling then ta = debugprofilestop() end
|
|
DB:DamageDone(srcName, AAttack, hit, crit, 0, 0, 0, 0, amount, glanc, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.DamageDone = profDB.DamageDone + (tb - ta); ta = tb end
|
|
DB:DamageTaken(dstName, AAttack, hit, crit, 0, 0, 0, 0, amount, srcName, crush, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.DamageTaken = profDB.DamageTaken + (tb - ta); ta = tb end
|
|
DB:EnemyDamage(1, DPSMateEDT, dstName, AAttack, hit, crit, 0, 0, 0, 0, amount, srcName, 0, crush)
|
|
DB:EnemyDamage(2, DPSMateEDD, srcName, AAttack, hit, crit, 0, 0, 0, 0, amount, dstName, 0, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.EnemyDamage = profDB.EnemyDamage + (tb - ta); ta = tb end
|
|
DB:DeathHistory(dstName, srcName, AAttack, amount, hit, crit, "hit", crush)
|
|
if profiling then tb = debugprofilestop(); profDB.DeathHistory = profDB.DeathHistory + (tb - ta); profDB.count = profDB.count + 1 end
|
|
if absorbed > 0 then
|
|
DB:SetUnregisterVariables(absorbed, AAttack, srcName)
|
|
DB:Absorb(AAttack, dstName, srcName)
|
|
end
|
|
|
|
elseif sub == "SWING_MISSED" then
|
|
local missType = p1
|
|
local miss = (missType == "MISS") and 1 or 0
|
|
local parry = (missType == "PARRY") and 1 or 0
|
|
local dodge = (missType == "DODGE") and 1 or 0
|
|
local resist = (missType == "RESIST" or missType == "IMMUNE") and 1 or 0
|
|
local block = (missType == "BLOCK") and 1 or 0
|
|
local absorb = (missType == "ABSORB") and 1 or 0
|
|
|
|
DB:DamageDone(srcName, AAttack, 0, 0, miss + absorb, parry, dodge, resist, 0, 0, block)
|
|
DB:DamageTaken(dstName, AAttack, 0, 0, miss + absorb, parry, dodge, resist, 0, srcName, 0, block)
|
|
if absorb == 1 then
|
|
DB:Absorb(AAttack, dstName, srcName)
|
|
end
|
|
|
|
-- SPELL_DAMAGE: (base 9), spellId, spellName, spellSchool,
|
|
-- amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing
|
|
|
|
elseif sub == "SPELL_DAMAGE" or sub == "RANGE_DAMAGE" or sub == "SPELL_PERIODIC_DAMAGE"
|
|
or sub == "DAMAGE_SHIELD" or sub == "DAMAGE_SPLIT" then
|
|
local spellName, spellSchool = p2, p3
|
|
local amount, absorbed = p4, p9
|
|
local critical, glancing, crushing = p10, p11, p12
|
|
-- numbers always non-nil from CombatLogGetCurrentEventInfo
|
|
local crit = critical and 1 or 0
|
|
local glanc = glancing and 1 or 0
|
|
local crush = crushing and 1 or 0
|
|
local hit = (crit == 0 and glanc == 0 and crush == 0) and 1 or 0
|
|
local abilityName = (sub == "SPELL_PERIODIC_DAMAGE") and (spellName .. "(Periodic)") or spellName
|
|
|
|
local ta, tb
|
|
if profiling then ta = debugprofilestop() end
|
|
DB:DamageDone(srcName, abilityName, hit, crit, 0, 0, 0, 0, amount, glanc, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.DamageDone = profDB.DamageDone + (tb - ta); ta = tb end
|
|
DB:DamageTaken(dstName, abilityName, hit, crit, 0, 0, 0, 0, amount, srcName, crush, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.DamageTaken = profDB.DamageTaken + (tb - ta); ta = tb end
|
|
DB:EnemyDamage(1, DPSMateEDT, dstName, abilityName, hit, crit, 0, 0, 0, 0, amount, srcName, 0, crush)
|
|
DB:EnemyDamage(2, DPSMateEDD, srcName, abilityName, hit, crit, 0, 0, 0, 0, amount, dstName, 0, 0)
|
|
if profiling then tb = debugprofilestop(); profDB.EnemyDamage = profDB.EnemyDamage + (tb - ta); ta = tb end
|
|
DB:DeathHistory(dstName, srcName, abilityName, amount, hit, crit, "hit", crush)
|
|
if profiling then tb = debugprofilestop(); profDB.DeathHistory = profDB.DeathHistory + (tb - ta); profDB.count = profDB.count + 1 end
|
|
if spellSchool then DB:AddSpellSchool(abilityName, spellSchool) end
|
|
if absorbed > 0 then
|
|
DB:SetUnregisterVariables(absorbed, abilityName, srcName)
|
|
DB:Absorb(abilityName, dstName, srcName)
|
|
end
|
|
if FailDT and FailDT[spellName] then
|
|
DB:BuildFail(2, srcName, dstName, abilityName, amount)
|
|
end
|
|
|
|
elseif sub == "SPELL_MISSED" or sub == "RANGE_MISSED"
|
|
or sub == "SPELL_PERIODIC_MISSED" or sub == "DAMAGE_SHIELD_MISSED" then
|
|
local spellName = p2
|
|
local missType = p4
|
|
local miss = (missType == "MISS") and 1 or 0
|
|
local parry = (missType == "PARRY") and 1 or 0
|
|
local dodge = (missType == "DODGE") and 1 or 0
|
|
local resist = (missType == "RESIST" or missType == "IMMUNE") and 1 or 0
|
|
local block = (missType == "BLOCK") and 1 or 0
|
|
local absorb = (missType == "ABSORB") and 1 or 0
|
|
local isPeriodic = (sub == "SPELL_PERIODIC_MISSED")
|
|
local abilityName = isPeriodic and (spellName .. "(Periodic)") or spellName
|
|
|
|
DB:DamageDone(srcName, abilityName, 0, 0, miss + absorb, parry, dodge, resist, 0, 0, block)
|
|
DB:DamageTaken(dstName, abilityName, 0, 0, miss + absorb, parry, dodge, resist, 0, srcName, 0, block)
|
|
if absorb == 1 then
|
|
DB:Absorb(abilityName, dstName, srcName)
|
|
end
|
|
|
|
elseif sub == "ENVIRONMENTAL_DAMAGE" then
|
|
local envType, amount = p1, p2
|
|
DB:DamageTaken(dstName, envType or "Environment", 1, 0, 0, 0, 0, 0, amount, envType or "Environment", 0, 0)
|
|
DB:DeathHistory(dstName, envType or "Environment", envType or "Environment", amount, 1, 0, "hit", 0)
|
|
|
|
-- ========================================================================
|
|
-- HEAL events
|
|
-- ========================================================================
|
|
|
|
elseif sub == "SPELL_HEAL" or sub == "SPELL_PERIODIC_HEAL" then
|
|
local spellName = p2
|
|
local amount, overheal, absorbed, critical = p4, p5, p6, p7
|
|
local crit = critical and 1 or 0
|
|
local hit = crit == 0 and 1 or 0
|
|
local effective = amount - overheal
|
|
if effective < 0 then effective = 0 end
|
|
|
|
local ta, tb
|
|
if profiling then ta = debugprofilestop() end
|
|
DB:Healing(1, DPSMateHealingTaken, srcName, spellName, hit, crit, effective)
|
|
DB:Healing(2, DPSMateOverhealing, srcName, spellName, hit, crit, overheal)
|
|
if profiling then tb = debugprofilestop(); profDB.Healing = profDB.Healing + (tb - ta); ta = tb end
|
|
DB:HealingTaken(1, DPSMateHealingTaken, srcName, spellName, hit, crit, effective, dstName)
|
|
if profiling then tb = debugprofilestop(); profDB.HealingTaken = profDB.HealingTaken + (tb - ta); ta = tb end
|
|
DB:DeathHistory(dstName, srcName, spellName, effective, hit, crit, "heal", 0)
|
|
if profiling then tb = debugprofilestop(); profDB.DeathHistory = profDB.DeathHistory + (tb - ta); profDB.count = profDB.count + 1 end
|
|
|
|
-- ========================================================================
|
|
-- AURA events (+ absorb shield lifecycle)
|
|
-- ========================================================================
|
|
|
|
elseif sub == "SPELL_AURA_APPLIED" then
|
|
local spellName, auraType = p2, p4
|
|
if auraType == "DEBUFF" then
|
|
DB:BuildBuffs(srcName, dstName, spellName, false)
|
|
if Parser.CC[spellName] then
|
|
DB:BuildActiveCC(dstName, spellName)
|
|
end
|
|
if FailDB and FailDB[spellName] then
|
|
DB:BuildFail(3, "Environment", dstName, spellName, 0)
|
|
end
|
|
else
|
|
DB:BuildBuffs(srcName, dstName, spellName, true)
|
|
if ShieldFlags[spellName] then
|
|
DB:ConfirmAbsorbApplication(spellName, dstName, GT())
|
|
end
|
|
end
|
|
|
|
elseif sub == "SPELL_AURA_REMOVED" then
|
|
local spellName, auraType = p2, p4
|
|
DB:DestroyBuffs(dstName, spellName)
|
|
if auraType == "DEBUFF" then
|
|
DB:RemoveActiveCC(dstName, spellName)
|
|
else
|
|
if ShieldFlags[spellName] then
|
|
DB:UnregisterAbsorb(spellName, dstName)
|
|
end
|
|
end
|
|
|
|
elseif sub == "SPELL_AURA_BROKEN_SPELL" or sub == "SPELL_AURA_BROKEN" then
|
|
local spellName = p2
|
|
DB:RemoveActiveCC(dstName, spellName)
|
|
if Parser.CC[spellName] then
|
|
DB:CCBreaker(dstName, spellName, srcName)
|
|
end
|
|
|
|
-- ========================================================================
|
|
-- CAST events
|
|
-- ========================================================================
|
|
|
|
elseif sub == "SPELL_CAST_SUCCESS" then
|
|
local spellName = p2
|
|
if Parser.Kicks and Parser.Kicks[spellName] then
|
|
DB:RegisterPotentialKick(srcName, spellName, GT())
|
|
end
|
|
if ShieldFlags[spellName] then
|
|
DB:AwaitingAbsorbConfirmation(srcName, spellName, dstName, GT())
|
|
end
|
|
|
|
-- ========================================================================
|
|
-- INTERRUPT / DISPEL events
|
|
-- ========================================================================
|
|
|
|
elseif sub == "SPELL_INTERRUPT" then
|
|
local spellName = p2
|
|
local extraSpellName = p5
|
|
DB:Kick(srcName, dstName, spellName, extraSpellName)
|
|
|
|
elseif sub == "SPELL_DISPEL" then
|
|
local spellName = p2
|
|
local extraSpellName = p5
|
|
if isGroupMember(srcName) then
|
|
DB:Dispels(srcName, spellName, dstName, extraSpellName)
|
|
end
|
|
|
|
-- ========================================================================
|
|
-- DEATH events
|
|
-- ========================================================================
|
|
|
|
elseif sub == "UNIT_DIED" or sub == "UNIT_DESTROYED" then
|
|
DB:UnregisterDeath(dstName)
|
|
|
|
elseif sub == "SPELL_SUMMON" then
|
|
if not Parser.petToOwnerMap then Parser.petToOwnerMap = {} end
|
|
if not Parser.petToOwnerMap[dstName] then Parser.petToOwnerMap[dstName] = {} end
|
|
Parser.petToOwnerMap[dstName][srcName] = true
|
|
end
|
|
|
|
if profiling and t0 then
|
|
local t2 = debugprofilestop()
|
|
profDetail.getInfo = profDetail.getInfo + (t1 - t0)
|
|
profDetail.dbCalls = profDetail.dbCalls + (t2 - t1)
|
|
profDetail.total = profDetail.total + (t2 - t0)
|
|
profDetail.count = profDetail.count + 1
|
|
end
|
|
end
|
|
|
|
-- Set the measured wrapper as the actual handler
|
|
cleuFrame:SetScript("OnEvent", measuredCLEUHandler)
|
|
|
|
-- ============================================================================
|
|
-- Start in CLEU mode by default
|
|
-- ============================================================================
|
|
|
|
enableCLEU()
|