Publish source: Unlicense, public README, repo hygiene

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/
This commit is contained in:
MarcelineVQ
2026-07-27 21:47:55 -07:00
parent f500147fc7
commit b12fc820ef
42 changed files with 5563 additions and 727 deletions
+84 -21
View File
@@ -145,6 +145,14 @@ end
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
@@ -204,6 +212,32 @@ local function profReport(label, tbl)
"|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
@@ -216,38 +250,42 @@ local function profReport(label, tbl)
end
end
-- /dpsbench -- enables per-combat A/B profiling. Each combat: measure, report, flip.
local benchActive = true
-- 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 benchCombatStart()
if not benchActive then return end
local function combatStart()
profCurrent = cleuActive and profCLEU or profOrig
profReset(profCurrent)
debugprofilestart() -- start the monotonic clock for this combat
debugprofilestart()
profiling = true
local label = cleuActive and "CLEU" or "ORIGINAL"
DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff00ff00[DPS Bench]|r combat started, measuring %s", label))
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 benchCombatEnd()
if not benchActive or not profiling then return end
local function combatEnd()
if not profiling then return end
profiling = false
local label = cleuActive and "CLEU" or "ORIGINAL"
profReport(label, profCurrent)
toggle()
DEFAULT_CHAT_FRAME:AddMessage(string.format(
"|cff00ff00[DPS Bench]|r next combat will use: %s", cleuActive and "CLEU" or "ORIGINAL"))
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
benchCombatStart()
combatStart()
elseif event == "PLAYER_REGEN_ENABLED" then
benchCombatEnd()
combatEnd()
end
end)
@@ -256,11 +294,10 @@ SlashCmdList["DPSBENCH"] = function()
benchActive = not benchActive
if benchActive then
DEFAULT_CHAT_FRAME:AddMessage(string.format(
"|cff00ff00[DPS Bench]|r enabled. Current mode: %s. Enter combat to begin.",
"|cff00ff00[DPS Bench]|r A/B enabled. Current mode: %s. Enter combat to begin.",
cleuActive and "CLEU" or "ORIGINAL"))
else
profiling = false
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[DPS Bench]|r disabled.")
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[DPS Bench]|r A/B disabled (stats still reported).")
end
end
@@ -280,16 +317,17 @@ local FailDB = DPSMate.Parser.FailDB
cleuHandler = function()
if not CombatLogGetCurrentEventInfo then return end
-- Single call — positions differ by prefix type:
-- Swing: p1=amount, p2=overkill, p3=school, ...
-- Spell: p1=spellId, p2=spellName, p3=spellSchool, p4=amount, ...
-- Env: p1=envType, p2=amount, ...
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
@@ -306,11 +344,17 @@ cleuHandler = function()
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)
@@ -346,11 +390,17 @@ cleuHandler = function()
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)
@@ -396,10 +446,15 @@ cleuHandler = function()
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)
@@ -481,6 +536,14 @@ cleuHandler = function()
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
+43 -22
View File
@@ -875,6 +875,7 @@ function DPSMate.DB:OnGroupUpdate()
local num = GetNumRaidMembers()
DPSMate.Parser.TargetParty = {}
DPSMate.Parser.petToOwnerMap = {}
petQualifiedCache = {}
if num<=0 then
type = "party"
num = GetNumPartyMembers()
@@ -993,18 +994,36 @@ function DPSMate.DB:OnGroupUpdate()
DPSMate.Parser:AssociateShaman("None", "None", true)
end
-- Cache: raw pet name -> qualified "PetName (OwnerName)" to avoid repeated pairs() iteration
local petQualifiedCache = {}
function DPSMate.DB:BuildUser(Dname, Dclass)
if not Dname then Dname = "?!NIL Name?!" end
-- Auto-qualify raw pet/totem names via petToOwnerMap (single-owner only)
local pom = DPSMate.Parser.petToOwnerMap
if pom and pom[Dname] then
local count, singleOwner = 0, nil
for o, _ in pairs(pom[Dname]) do
count = count + 1
singleOwner = o
end
if count == 1 then
Dname = Dname .. " (" .. singleOwner .. ")"
-- Fast path: already-known non-pet name — skip regex + petToOwnerMap entirely
local u = DPSUser[Dname]
if u then return u[1] end
-- Check pet name cache (avoids repeated pairs() iteration on petToOwnerMap)
local cached = petQualifiedCache[Dname]
if cached then
u = DPSUser[cached]
if u then return u[1] end
Dname = cached
else
-- Auto-qualify raw pet/totem names via petToOwnerMap (single-owner only)
local pom = DPSMate.Parser.petToOwnerMap
if pom and pom[Dname] then
local count, singleOwner = 0, nil
for o, _ in pairs(pom[Dname]) do
count = count + 1
singleOwner = o
end
if count == 1 then
local qualified = Dname .. " (" .. singleOwner .. ")"
petQualifiedCache[Dname] = qualified
u = DPSUser[qualified]
if u then return u[1] end
Dname = qualified
end
end
end
local _,_, pet,owner = strfind(Dname,"(.+)%s%((.+)%)")
@@ -1102,7 +1121,8 @@ function DPSMate.DB:Threat(cause, spellname, target, value, amount)
target = self:BuildUser(target)
cause = self:BuildUser(cause)
spellname = self:BuildAbility(spellname)
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do
local val = tablemodes[cat]
if not DPSThreat[cat] then DPSThreat[cat] = {} end
if not DPSThreat[cat][cause] then
DPSThreat[cat][cause] = {}
@@ -1743,7 +1763,7 @@ function DPSMate.DB:RegisterAbsorb(owner, ability, abilityTarget)
owner = self:BuildUser(owner)
abilityTarget = self:BuildUser(abilityTarget)
ability = self:BuildAbility(ability)
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSAbsorb[cat] then DPSAbsorb[cat] = {} end
if not DPSAbsorb[cat][abilityTarget] then
DPSAbsorb[cat][abilityTarget] = {}
@@ -1777,7 +1797,7 @@ function DPSMate.DB:UnregisterAbsorb(ability, abilityTarget)
ability = self:BuildAbility(ability)
abilityTarget = self:BuildUser(abilityTarget)
local AbsorbingAbility
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
AbsorbingAbility = self:GetActiveAbsorbAbilityByPlayer(ability, abilityTarget, cat)
if AbsorbingAbility[1] then
path = DPSAbsorb[cat][abilityTarget][AbsorbingAbility[1]][AbsorbingAbility[2]][AbsorbingAbility[3]]["i"]
@@ -1889,7 +1909,7 @@ function DPSMate.DB:Absorb(ability, abilityTarget, incTarget)
abilityTarget = self:BuildUser(abilityTarget)
ability = self:BuildAbility(ability)
local AbsorbingAbility
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
local abilityName = DPSMate:GetAbilityById(ability)
local abilityEntry = abilityName and DPSMateAbility[abilityName]
if not abilityEntry then break end
@@ -2094,7 +2114,7 @@ function DPSMate.DB:Dispels(cause, Dname, target, ability)
target = self:BuildUser(target)
Dname = self:BuildAbility(Dname)
ability = self:BuildAbility(ability)
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSDispel[cat] then DPSDispel[cat] = {} end
if not DPSDispel[cat][cause] then
DPSDispel[cat][cause] = {
@@ -2130,13 +2150,13 @@ function DPSMate.DB:UnregisterDeath(target)
if strfind(target, "%s") then return end
target = self:BuildUser(target)
local p
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do
if DPSDeath[cat] and DPSDeath[cat][target] and DPSDeath[cat][target][1] then
DPSDeath[cat][target][1]["i"][1]=1
DPSDeath[cat][target][1]["i"][2]=GameTime_GT()
if cat==1 and DPSMate.Parser.TargetParty[DPSMate:GetUserById(target)] and DPSDeath[cat][target][1][1] then
p = DPSDeath[cat][target][1][1]
DPSMate:Broadcast(4, DPSMate:GetUserById(target), DPSMate:GetUserById(p[1]), DPSMate:GetAbilityById(p[2]), p[3])
DPSMate:Broadcast(4, DPSMate:GetUserById(target), DPSMate:GetUserById(p[1]), DPSMate:GetAbilityById(p[2]), p[3])
end
end
end
@@ -2148,7 +2168,8 @@ function DPSMate.DB:DeathHistory(target, cause, ability, amount, hit, crit, type
cause = self:BuildUser(cause)
ability = self:BuildAbility(ability)
local hitCritCrush
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do
local val = tablemodes[cat]
if not DPSDeath[cat] then DPSDeath[cat] = {} end
if not DPSDeath[cat][target] then
DPSDeath[cat][target] = {}
@@ -2245,7 +2266,7 @@ function DPSMate.DB:Kick(cause, target, causeAbility, targetAbility)
cause = self:BuildUser(cause)
causeAbility = self:BuildAbility(causeAbility)
targetAbility = self:BuildAbility(targetAbility)
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSInterrupt[cat] then DPSInterrupt[cat] = {} end
if not DPSInterrupt[cat][cause] then
DPSInterrupt[cat][cause] = {
@@ -2310,7 +2331,7 @@ function DPSMate.DB:BuildBuffs(cause, target, ability, bool)
target = self:BuildUser(target)
cause = self:BuildUser(cause)
ability = self:BuildAbility(ability)
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSAurasGained[cat] then DPSAurasGained[cat] = {} end
if not DPSAurasGained[cat][target] then
DPSAurasGained[cat][target] = {}
@@ -2347,7 +2368,7 @@ function DPSMate.DB:DestroyBuffs(target, ability)
target = self:BuildUser(target)
ability = self:BuildAbility(ability)
local TL
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSAurasGained[cat] then DPSAurasGained[cat] = {} end
if not DPSAurasGained[cat][target] then
DPSAurasGained[cat][target] = {}
@@ -2557,7 +2578,7 @@ function DPSMate.DB:BuildFail(type, user, cause, ability, amount)
cause = self:BuildUser(cause)
ability = self:BuildAbility(ability)
local time = GameTime_GT()
for cat, val in pairs(tablemodes) do
for cat = 1, 2 do local val = tablemodes[cat]
if not DPSFail[cat] then DPSFail[cat] = {} end
if not DPSFail[cat][cause] then
DPSFail[cat][cause] = {}