dpslog: DPSMate CLEU adapter with per-combat A/B profiling

Adds DPSMate_CLEUAdapter.lua -- replaces DPSMate's string-parsing
CHAT_MSG_* system with structured COMBAT_LOG_EVENT data from our DLL.

Adapter maps CLEU subevents directly to DPSMate.DB API calls:
DamageDone, DamageTaken, EnemyDamage, Healing, HealingTaken,
DeathHistory, Kick, Dispels, BuildBuffs, CCBreaker, etc.
Eliminates all strfind pattern matching from the combat log path.

Toggle: /dpscleu (on/off/status)
Benchmark: /dpsbench -- always-on per-combat A/B profiling.
  Resets at combat start, reports at combat end, flips mode for next
  combat. Reports events, total ms, us/event, GC delta, and percentage
  comparison between CLEU and original modes.

Starts in CLEU mode by default.
This commit is contained in:
MarcelineVQ
2026-03-18 01:12:04 -07:00
parent d52d4bc661
commit 86da3bcc03
281 changed files with 179217 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
<Bindings>
<Binding name="DPSMATE_RESET" header="DPSMATE">DPSMate_PopUp:Show()</Binding>
<Binding name="DPSMATE_TOGGLE">DPSMate.Options:ToggleVisibility()</Binding>
<Binding name="DPSMATE_REPORT">if not DPSMate_Report:IsVisible() then DPSMate_Report:Show() else DPSMate_Report:Hide() end</Binding>
</Bindings>
+970
View File
@@ -0,0 +1,970 @@
-- Global Variables
DPSMate = {}
DPSMate.VERSION = 130
DPSMate.LOCALE = GetLocale()
DPSMate.SYNCVERSION = DPSMate.VERSION..DPSMate.LOCALE
DPSMate.Parser = CreateFrame("Frame", nil, UIParent)
DPSMate.L = {}
DPSMate.DB = CreateFrame("Frame", nil, UIParent)
DPSMate.Options = CreateFrame("Frame", nil, UIParent)
DPSMate.Sync = CreateFrame("Frame", nil, UIParent)
DPSMate.Modules = {}
DPSMate.Events = {
--"CHAT_MSG_ADDON",
"PLAYER_AURAS_CHANGED",
-- Damage
"CHAT_MSG_COMBAT_SELF_HITS",
"CHAT_MSG_COMBAT_SELF_MISSES",
"CHAT_MSG_SPELL_SELF_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_HITS",
"CHAT_MSG_SPELL_PARTY_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_MISSES",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES",
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",
-- Pet Damage
"CHAT_MSG_COMBAT_PET_HITS",
"CHAT_MSG_COMBAT_PET_MISSES",
--"CHAT_MSG_SPELL_PET_BUFF",
"CHAT_MSG_SPELL_PET_DAMAGE",
-- EDD (Enemy player) / DeathHistory
"CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS",
"CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES",
"CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE",
"CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE",
-- Damage taken (Also EDD) / DeathHistory
"CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS",
"CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES",
"CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE",
"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS",
"CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES",
"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_PARTY_DAMAGE",
"CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE",
"CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE",
"CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE",
-- Healing/Absorbs/Fail/DeathHistory/Dispels
"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",
-- Absorbs/Auras
"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",
-- Death/DeathHistory
"CHAT_MSG_COMBAT_FRIENDLY_DEATH",
"CHAT_MSG_COMBAT_HOSTILE_DEATH",
}
DPSMate.Registered = true
DPSMate.RegistredModules = {}
DPSMate.ModuleNames = {}
DPSMate.UserId = nil
DPSMate.AbilityId = nil
DPSMate.Key = 1
DPSMate.DelayMsg = {}
DPSMate.BabbleSpell = BabbleSpell
DPSMate.BabbleBoss = BabbleBoss
-- Knife was wrong - 11.06.2018
-- Local Variables
local _G = getglobal
local classcolor = {
rogue = {r=1.0, g=0.96, b=0.41},
priest = {r=1,g=1,b=1},
druid = {r=1,g=0.49,b=0.04},
warrior = {r=0.78,g=0.61,b=0.43},
warlock = {r=0.58,g=0.51,b=0.79},
mage = {r=0.41,g=0.8,b=0.94},
hunter = {r=0.67,g=0.83,b=0.45},
paladin = {r=0.96,g=0.55,b=0.73},
shaman = {r=0,g=0.44,b=0.87},
}
local t = {}
local tinsert = table.insert
local strgsub = string.gsub
local func = function(c) tinsert(t, c) end
local strformat = string.format
local strgfind = string.gfind
local pairs = pairs
local strlen = strlen
local strsub = strsub
local tonumber = tonumber
local getn = getn
local tconcat = table.concat
local SendChatMessage = function(prio, prefix, text, chattype, language, destination)
ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination)
end
local DPSSettings = {}
local DPSHist = {}
local fontRefreshAt = nil
local savedFontSettings = nil
local GT = GetTime
-- Begin functions
function DPSMate:OnLoad()
SLASH_DPSMate1 = "/dps"
SlashCmdList["DPSMate"] = function(msg) DPSMate:SlashCMDHandler(msg) end
DPSMate:UpdatePointer()
-- Snapshot font settings before skinning addons can overwrite them
savedFontSettings = {}
for k, w in pairs(DPSSettings["windows"]) do
savedFontSettings[k] = {
barfont = w["barfont"],
barfontsize = w["barfontsize"],
barfontflag = w["barfontflag"],
titlebarfont = w["titlebarfont"],
titlebarfontsize = w["titlebarfontsize"],
titlebarfontflag = w["titlebarfontflag"],
}
end
DPSMate:InitializeFrames()
DPSMate.Options:InitializeConfigMenu()
if DPSMate.L.UpdateFrameTexts then
DPSMate.L.UpdateFrameTexts()
end
-- Schedule a deferred font refresh so that font settings survive
-- skinning addons (e.g. pfUI) that override fonts after load.
fontRefreshAt = GT() + 1
end
function DPSMate:UpdatePointer()
DPSSettings = DPSMateSettings
DPSHist = DPSMateHistory
end
function DPSMate:SlashCMDHandler(msg)
if (msg) then
local cmd = msg
if cmd == "lock" then
DPSMate.Options:Lock()
elseif cmd == "unlock" then
DPSMate.Options:Unlock()
elseif cmd == "config" then
DPSMate_ConfigMenu:Show()
elseif cmd == "reset" then
DPSMate:SendMessage(DPSMate.L["resetconfirm"])
elseif cmd == "resetconfirm" then
DPSMateUser = {}
DPSMateAbility = {}
DPSMate.DB.abilitylen = 1
DPSMate.DB.userlen = 1
DPSMate.UserId = {}
DPSMate.Options:PopUpAccept(true, true)
DPSMate:SendMessage(DPSMate.L["resetdone"])
elseif cmd == "showAll" then
for _, val in DPSSettings["windows"] do DPSMate.Options:Show(getglobal("DPSMate_"..val["name"])) end
elseif cmd == "hideAll" then
for _, val in DPSSettings["windows"] do DPSMate.Options:Hide(getglobal("DPSMate_"..val["name"])) end
elseif strsub(cmd, 1, 4) == "show" then
local frame = _G("DPSMate_"..strsub(cmd, 6))
if frame then
DPSMate.Options:Show(frame)
else
DPSMate:SendMessage(DPSMate.L["framesavailable"])
for _, val in pairs(DPSSettings["windows"]) do
DPSMate:SendMessage("|c3ffddd80- "..val["name"].."|r")
end
end
elseif strsub(cmd, 1, 4) == "hide" then
local frame = _G("DPSMate_"..strsub(cmd, 6))
if frame then
DPSMate.Options:Hide(frame)
else
DPSMate:SendMessage(DPSMate.L["framesavailable"])
for _, val in pairs(DPSSettings["windows"]) do
DPSMate:SendMessage("|c3ffddd80- "..val["name"].."|r")
end
end
else
DPSMate:SendMessage(DPSMate.L["slashabout"])
DPSMate:SendMessage(DPSMate.L["slashusage"])
DPSMate:SendMessage(DPSMate.L["slashlock"])
DPSMate:SendMessage(DPSMate.L["slashunlock"])
DPSMate:SendMessage(DPSMate.L["slashshowAll"])
DPSMate:SendMessage(DPSMate.L["slashhideAll"])
DPSMate:SendMessage(DPSMate.L["slashshow"])
DPSMate:SendMessage(DPSMate.L["slashhide"])
DPSMate:SendMessage(DPSMate.L["slashconfig"])
DPSMate:SendMessage(DPSMate.L["slashreset"])
end
end
end
function DPSMate:InitializeFrames()
if not DPSSettings["windows"][1] then return end
for k, val in pairs(DPSSettings["windows"]) do
if not _G("DPSMate_"..val["name"]) then
local f=CreateFrame("Frame", "DPSMate_"..val["name"], UIParent, "DPSMate_Statusframe")
f.Key=k
end
local frame = _G("DPSMate_"..val["name"])
frame.fborder = _G("DPSMate_"..val["name"].."_Border")
frame:SetToplevel(true)
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total_Name"):SetText(self.L["total"])
if (val["position"] and val["position"][1]) then
frame:ClearAllPoints()
frame:SetPoint(val["position"][1], UIParent, val["position"][1], val["position"][2], val["position"][3])
end
if (val["savsize"] and val["savsize"][1]) then
frame:SetWidth(val["savsize"][1])
frame:SetHeight(val["savsize"][2])
end
DPSMate.Options:ToggleDrewDrop(1, DPSMate.DB:GetOptionsTrue(1, k), frame)
DPSMate.Options:ToggleDrewDrop(2, DPSMate.DB:GetOptionsTrue(2, k), frame)
frame.fborder:SetAlpha(val["borderopacity"] or 0)
frame.fborder:SetFrameStrata(DPSMate.Options.stratas[val["borderstrata"] or 1])
frame.fborder:SetBackdrop({
bgFile = "",
edgeFile = DPSMate.Options.bordertextures[val["bordertexture"] or "UI-Tooltip-Border"], tile = true, tileSize = 12, edgeSize = 10,
insets = { left = 5, right = 5, top = 3, bottom = 1 }
})
frame.fborder:SetBackdropBorderColor(val["contentbordercolor"][1], val["contentbordercolor"][2], val["contentbordercolor"][3])
local head = _G("DPSMate_"..val["name"].."_Head")
head.font = _G("DPSMate_"..val["name"].."_Head_Font")
head.bg = _G("DPSMate_"..val["name"].."_Head_Background")
head.sync = _G("DPSMate_"..val["name"].."_Head_Sync")
if DPSSettings["sync"] then
head.sync:GetNormalTexture():SetVertexColor(0.67,0.83,0.45,1)
else
head.sync:GetNormalTexture():SetVertexColor(1,0,0,1)
end
if DPSSettings["lock"] then
_G("DPSMate_"..val["name"].."_Resize"):Hide()
end
if not val["titlebar"] then
head:Hide()
end
frame:SetAlpha(val["opacity"])
head.font:SetTextColor(val["titlebarfontcolor"][1],val["titlebarfontcolor"][2],val["titlebarfontcolor"][3])
head.bg:SetTexture(DPSMate.Options.statusbars[val["titlebartexture"]])
head.bg:SetVertexColor(val["titlebarbgcolor"][1], val["titlebarbgcolor"][2], val["titlebarbgcolor"][3])
head.bg:SetAlpha(val["titlebaropacity"] or 1)
head.font:SetFont(DPSMate.Options.fonts[val["titlebarfont"]], val["titlebarfontsize"], DPSMate.Options.fontflags[val["titlebarfontflag"]])
head:SetHeight(val["titlebarheight"])
_G("DPSMate_"..val["name"].."_ScrollFrame_Background"):SetTexture(DPSMate.Options.bgtexture[val["contentbgtexture"]])
_G("DPSMate_"..val["name"].."_ScrollFrame_Background"):SetVertexColor(val["contentbgcolor"][1], val["contentbgcolor"][2], val["contentbgcolor"][3])
_G("DPSMate_"..val["name"].."_ScrollFrame_Background"):SetAlpha(val["bgopacity"] or 1)
frame:SetScale(val["scale"])
_G("DPSMate_"..val["name"].."_Head_Enable"):SetChecked(DPSSettings["enable"])
-- Styles // Bars
local child = _G("DPSMate_"..val["name"].."_ScrollFrame_Child")
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetPoint("TOPLEFT", child, "TOPLEFT")
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetPoint("TOPRIGHT", child, "TOPRIGHT")
if DPSSettings["showtotals"] then
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetHeight(val["barheight"])
else
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetHeight(0.00001)
end
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetStatusBarTexture(DPSMate.Options.statusbars[val["bartexture"]])
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"):SetStatusBarColor(1,1,1,val["totopacity"] or 1)
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total_BG"):SetTexture(DPSMate.Options.statusbars[val["bartexture"]])
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total_BG"):SetAlpha(val["totopacity"] or 1)
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total_Name"):SetFont(DPSMate.Options.fonts[val["barfont"]], val["barfontsize"], DPSMate.Options.fontflags[val["barfontflag"]])
_G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total_Value"):SetFont(DPSMate.Options.fonts[val["barfont"]], val["barfontsize"], DPSMate.Options.fontflags[val["barfontflag"]])
for i=1, 40 do
local bar = _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..i)
bar.name = _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..i.."_Name")
bar.value = _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..i.."_Value")
bar.icon = _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..i.."_Icon")
bar.bg = _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..i.."_BG")
-- Postition
bar:SetPoint("TOPLEFT", child, "TOPLEFT")
bar:SetPoint("TOPRIGHT", child, "TOPRIGHT")
if i>1 then
bar:SetPoint("TOPLEFT", _G("DPSMate_"..val["name"].."_ScrollFrame_Child_StatusBar"..(i-1)), "BOTTOMLEFT", 0, -1*val["barspacing"])
else
if DPSSettings["showtotals"] then
bar:SetPoint("TOPLEFT", _G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"), "BOTTOMLEFT", 0, -1*val["barspacing"])
else
bar:SetPoint("TOPLEFT", _G("DPSMate_"..val["name"].."_ScrollFrame_Child_Total"), "BOTTOMLEFT", 0, -1)
end
end
if val["classicons"] then
bar.name:ClearAllPoints()
bar.name:SetPoint("TOPLEFT", bar, "TOPLEFT", val["barheight"], 0)
bar.name:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT")
bar.icon:SetWidth(val["barheight"])
bar.icon:SetHeight(val["barheight"])
bar.icon:Show()
end
-- Styles
bar.name:SetFont(DPSMate.Options.fonts[val["barfont"]], val["barfontsize"], DPSMate.Options.fontflags[val["barfontflag"]])
bar.name:SetTextColor(val["barfontcolor"][1],val["barfontcolor"][2],val["barfontcolor"][3])
bar.value:SetFont(DPSMate.Options.fonts[val["barfont"]], val["barfontsize"], DPSMate.Options.fontflags[val["barfontflag"]])
bar.value:SetTextColor(val["barfontcolor"][1],val["barfontcolor"][2],val["barfontcolor"][3])
bar:SetStatusBarTexture(DPSMate.Options.statusbars[val["bartexture"]])
bar.bg:SetTexture(DPSMate.Options.statusbars[val["bartexture"]])
bar:SetHeight(val["barheight"])
if val["barbg"] then
bar.bg:SetVertexColor(val["bgbarcolor"][1],val["bgbarcolor"][2],val["bgbarcolor"][3], 0)
else
bar.bg:SetVertexColor(val["bgbarcolor"][1],val["bgbarcolor"][2],val["bgbarcolor"][3], 0.5)
end
end
DPSMate.Options:SelectRealtime(frame, val["realtime"])
if (val["hidden"] == true) then
frame:Hide()
end
end
DPSMate.Options:ToggleTitleBarButtonState()
DPSMate.Options:HideWhenSolo()
if not DPSSettings["enable"] then
self:Disable()
else
self:Enable()
end
-- Report delay button
DPSMate_Report_Delay:SetChecked(DPSSettings["reportdelay"])
DPSMate_MiniMap:SetToplevel(true)
DPSMate_PopUp:SetToplevel(true)
DPSMate_Vote:SetToplevel(true)
DPSMate_Logout:SetToplevel(true)
DPSMate_Report:SetToplevel(true)
DPSMate_ConfigMenu:SetToplevel(true)
end
function DPSMate:ProbZero(val)
if (val==0) then
return 1;
end
return val;
end
function DPSMate:TMax(t)
local max = 0
for _,val in pairs(t) do
if val>max then
max=val
end
end
return max
end
function DPSMate:TableLength(t)
local count = 0
if (t) then
count = getn(t)
if count<=1 then
count = 0
for _,_ in pairs(t) do
count = count + 1
end
end
end
return count
end
function DPSMate:TContains(t, value)
if (t) then
for cat, val in pairs(t) do
if val == value or cat==value then
return true
end
end
end
return false
end
function DPSMate:GetKeyByVal(t, value)
for cat, val in pairs(t) do
if val == value then
return cat
end
end
end
function DPSMate:GetKeyByValInTT(t, x, y)
for cat, val in pairs(t) do
if (type(val) == "table") then
if (x==val[y]) then
return cat
end
end
end
end
function DPSMate:InvertTable(t)
local s={}
for cat, val in pairs(t) do
s[val]=cat
end
return s
end
function DPSMate:CopyTable(t)
local s={}
for cat, val in pairs(t) do
if type(val) == "table" then
s[cat] = self:CopyTable(val)
else
s[cat] = val
end
end
return s
end
function DPSMate:CopyTableStripInstant(t, depth)
local s={}
depth = depth or 0
for cat, val in pairs(t) do
if depth >= 2 and cat == "i" then
-- Skip ["i"] instant-damage dictionaries at ability level
elseif type(val) == "table" then
s[cat] = self:CopyTableStripInstant(val, depth + 1)
else
s[cat] = val
end
end
return s
end
function DPSMate:PruneStaleUsers()
-- Collect all user IDs referenced in active metric data and history
local activeIds = {}
local metrics = {DPSMateDamageDone, DPSMateDamageTaken, DPSMateEDD, DPSMateEDT, DPSMateTHealing, DPSMateEHealing, DPSMateOverhealing, DPSMateHealingTaken, DPSMateEHealingTaken, DPSMateOverhealingTaken, DPSMateAbsorbs, DPSMateDispels, DPSMateDeaths, DPSMateInterrupts, DPSMateAurasGained, DPSMateThreat, DPSMateFails, DPSMateCCBreaker}
-- Check active data (mode [1] and [2])
for _, metric in pairs(metrics) do
if metric then
for mode = 1, 2 do
if metric[mode] then
for uid, _ in pairs(metric[mode]) do
activeIds[uid] = true
end
end
end
end
end
-- Check history segments
for cat, segments in pairs(DPSMateHistory) do
if cat ~= "names" and type(segments) == "table" then
for _, segment in pairs(segments) do
if type(segment) == "table" then
for uid, _ in pairs(segment) do
activeIds[uid] = true
end
end
end
end
end
-- Remove users whose IDs aren't referenced anywhere
local removed = 0
for name, data in pairs(DPSMateUser) do
if data[1] and not activeIds[data[1]] then
DPSMateUser[name] = nil
removed = removed + 1
end
end
if removed > 0 then
self.UserId = nil
end
end
-- Strip ["i"] sub-tables from all modes of all metrics that use them.
-- Covers damage/healing/threat (per-second time buckets) as well as dispels,
-- interrupts, and absorbs (event log arrays stored under ["i"]).
-- Called on login and on logout to keep SavedVariables compact.
--
-- A recursive walk is used: wherever ["i"] is a table it is cleared to {}.
-- Numbers stored under ["i"] are left untouched.
-- Using {} rather than nil keeps combat event writers safe.
local function stripInstantRecursive(t)
for k, v in pairs(t) do
if k == "i" and type(v) == "table" then
t[k] = {}
elseif k ~= "i" and type(v) == "table" then
stripInstantRecursive(v)
end
end
end
function DPSMate:StripInstantFromMode1()
local metrics = {DPSMateDamageDone, DPSMateDamageTaken, DPSMateEDD, DPSMateEDT,
DPSMateTHealing, DPSMateEHealing, DPSMateOverhealing, DPSMateHealingTaken,
DPSMateEHealingTaken, DPSMateOverhealingTaken, DPSMateThreat,
DPSMateDispels, DPSMateInterrupts, DPSMateAbsorbs}
for _, metric in pairs(metrics) do
if metric then
if metric[1] then stripInstantRecursive(metric[1]) end
if metric[2] then stripInstantRecursive(metric[2]) end
end
end
end
-- Collapse AurasGained timestamp arrays in Mode [1] and [2] into compact uptime totals.
-- path[1] (gain times) and path[2] (loss times) grow unboundedly with each buff
-- application. The pre-computed total is stored in path[7] so EvalTable can still
-- display accurate uptime percentages across sessions.
function DPSMate:CollapseAuraTimestamps()
if not DPSMateAurasGained then return end
for mode = 1, 2 do
local modeData = DPSMateAurasGained[mode]
if modeData then
for uid, abilities in pairs(modeData) do
for abilityId, path in pairs(abilities) do
if type(path) == "table" and type(path[1]) == "table" then
local total = path[7] or 0
for i, gainTime in pairs(path[1]) do
if path[2] and path[2][i] then
total = total + (path[2][i] - gainTime)
end
end
path[7] = total
path[1] = {}
path[2] = {}
end
end
end
end
end
end
function DPSMate:GetUserById(id)
if not self.UserId or not self.UserId[id] then
self.UserId = {}
for cat, val in DPSMateUser do
self.UserId[val[1]] = cat
end
end
return self.UserId[id]
end
function DPSMate:GetPetsByOwner(arr)
local lookup = {}
for cat, _ in pairs(arr) do
local name = self:GetUserById(cat)
if name and DPSMateUser[name] and DPSMateUser[name][4] and DPSMateUser[name][6] then
local oid = DPSMateUser[name][6]
if not lookup[oid] then
lookup[oid] = {}
end
table.insert(lookup[oid], cat)
end
end
return lookup
end
function DPSMate:GetAbilityById(id)
if not self.AbilityId or not self.AbilityId[id] then
self.AbilityId = {}
for cat, val in DPSMateAbility do
self.AbilityId[val[1]] = cat
end
end
return self.AbilityId[id]
end
function DPSMate:GetMaxValue(arr, key)
local max = 0
for _, val in arr do
if val[key]>max then
max=val[key]
end
end
return max
end
function DPSMate:GetMinValue(arr, key)
local min
for _, val in arr do
if not min or val[key]<min then
min = val[key]
end
end
return min or 0
end
function DPSMate:ScaleDown(arr, start)
local t = {}
for cat, val in arr do
t[cat] = {(val[1]-start+1), val[2]}
end
return t
end
function DPSMate:RefreshFonts()
if not DPSSettings["windows"][1] then return end
if not savedFontSettings then return end
local fonts = self.Options.fonts
local flags = self.Options.fontflags
for k, c in pairs(DPSSettings["windows"]) do
local saved = savedFontSettings[k]
if saved then
-- Restore user's saved font settings into the live table
c["barfont"] = saved.barfont
c["barfontsize"] = saved.barfontsize
c["barfontflag"] = saved.barfontflag
c["titlebarfont"] = saved.titlebarfont
c["titlebarfontsize"] = saved.titlebarfontsize
c["titlebarfontflag"] = saved.titlebarfontflag
end
local barFont = fonts[c["barfont"]]
local barSize = c["barfontsize"]
local barFlag = flags[c["barfontflag"]]
local titleFont = fonts[c["titlebarfont"]]
local titleSize = c["titlebarfontsize"]
local titleFlag = flags[c["titlebarfontflag"]]
local name = c["name"]
_G("DPSMate_"..name.."_Head_Font"):SetFont(titleFont, titleSize, titleFlag)
_G("DPSMate_"..name.."_ScrollFrame_Child_Total_Name"):SetFont(barFont, barSize, barFlag)
_G("DPSMate_"..name.."_ScrollFrame_Child_Total_Value"):SetFont(barFont, barSize, barFlag)
for i=1, 40 do
_G("DPSMate_"..name.."_ScrollFrame_Child_StatusBar"..i.."_Name"):SetFont(barFont, barSize, barFlag)
_G("DPSMate_"..name.."_ScrollFrame_Child_StatusBar"..i.."_Value"):SetFont(barFont, barSize, barFlag)
end
end
savedFontSettings = nil
end
local framePointerCache = {}
function DPSMate:InvalidateFrameCache()
framePointerCache = {}
end
function DPSMate:SetStatusBarValue()
if not DPSSettings["windows"][1] or self.Options.TestMode then return end
-- Deferred font refresh: wait ~1s after load for skinning addons to finish,
-- then re-apply saved font settings once.
if fontRefreshAt and GT() >= fontRefreshAt then
fontRefreshAt = nil
self:RefreshFonts()
end
local arr, cbt, ecbt, user, val, perc, strt, statusbar, r, g, b, img, len
for k,c in pairs(DPSSettings.windows) do
arr, cbt, ecbt = self:GetMode(k)
user, val, perc, strt = self:GetSettingValues(arr,cbt,k,ecbt)
-- Caching the global lookups
if not framePointerCache[k] then
framePointerCache[k] = {}
framePointerCache[k][1] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_Total_Value")
framePointerCache[k][2] = _G("DPSMate_"..c["name"].."_Head_Font")
framePointerCache[k][3] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child")
framePointerCache[k][4] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_Total")
for i=1, 40 do
framePointerCache[k][4+i] = {}
framePointerCache[k][4+i][1] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_StatusBar"..i)
framePointerCache[k][4+i][2] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_StatusBar"..i.."_Name")
framePointerCache[k][4+i][3] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_StatusBar"..i.."_Value")
framePointerCache[k][4+i][4] = _G("DPSMate_"..c["name"].."_ScrollFrame_Child_StatusBar"..i.."_Icon")
end
end
local FPC = framePointerCache[k];
if DPSSettings["showtotals"] then
FPC[1]:SetText(strt[1]..strt[2])
end
if not c["cbtdisplay"] then
FPC[2]:SetText(self.Options.Options[1]["args"][c["CurMode"]].name.." ["..self.Options:FormatTime(cbt).."]")
end
len = 0
for i=1, 40 do
statusbar = FPC[4+i][1]
if user[i] then
r,g,b,img = self:GetClassColor(user[i])
statusbar:SetStatusBarColor(r,g,b, 1)
local displayName = user[i]
if not DPSMateSettings["mergepets"] and DPSMateUser[user[i]] and DPSMateUser[user[i]][4] then
local ownerID = DPSMateUser[user[i]][6]
if ownerID then
local ownerName = self:GetUserById(ownerID)
if ownerName then displayName = user[i].." ("..ownerName..")" end
end
end
if c["ranks"] then
FPC[4+i][2]:SetText(i..". "..displayName)
else
FPC[4+i][2]:SetText(displayName)
end
FPC[4+i][3]:SetText(val[i])
FPC[4+i][4]:SetTexture("Interface\\AddOns\\DPSMate\\images\\class\\"..img)
statusbar:SetValue(perc[i])
statusbar.user = user[i]
statusbar:Show()
len = len + 1
else
statusbar:Hide()
end
end
FPC[3]:SetHeight((len+1)*(c["barheight"]+c["barspacing"]))
FPC[4]:Show()
if len == 0 then
FPC[4]:Hide()
end
end
end
function DPSMate:strrev(str)
local res, len = {}, strlen(str)
for i=1, len do
res[i] = strsub(str, len-i+1, len-i+1)
end
return tconcat(res);
end
function DPSMate:Commas(n,k)
if DPSSettings["windows"][k]["numberformat"] == 3 then
n = strformat("%.0f", n)
for left, num, right in strgfind(n, '([^%d]*%d)(%d+)') do
return left and left..self:strrev(strgsub(self:strrev(num), '(%d%d%d)','%1,'))
end
end
return n;
end
function DPSMate:FormatNumbers(dmg,total,sort,k)
local oldd, oldt, olds = dmg, total, sort
if DPSSettings["windows"][k]["numberformat"] == 2 then
if dmg>10000 then
dmg = strformat("%.0f", (dmg/1000))
end
if total>10000 then
total = strformat("%.0f", (total/1000))
end
if sort>10000 then
sort = strformat("%.0f", (sort/1000))
end
elseif DPSSettings["windows"][k]["numberformat"] == 4 then
if dmg>10000 then
dmg = strformat("%.1f", (dmg/1000))
end
if total>10000 then
total = strformat("%.1f", (total/1000))
end
if sort>10000 then
sort = strformat("%.1f", (sort/1000))
end
end
return dmg, total, sort, oldd, oldt, olds
end
function DPSMate:ApplyFilter(key, name)
if not name or not DPSMateUser[name] then return false end
if not key then return true end
local class = DPSMateUser[name][2] or "warrior"
local path = DPSSettings["windows"][key]
if path["grouponly"] then
if not DPSMate.Parser.TargetParty[name] and next(DPSMate.Parser.TargetParty) ~= nil then
return false
end
end
if path["filterpeople"] and path["filterpeople"] ~= "" then
-- Certain people
t = {}
strgsub(path["filterpeople"]..",", "(.-),", func)
for cat, val in pairs(t) do
if name == val then
return true
end
end
end
-- classes
for cat, val in pairs(path["filterclasses"]) do
if not val then
if cat == class then
return false
end
end
end
return true
end
function DPSMate:GetSettingValues(arr, cbt, k, ecbt)
k = k or 1
return self.RegistredModules[DPSSettings["windows"][k]["CurMode"]]:GetSettingValues(arr, cbt, k, ecbt)
end
function DPSMate:EvalTable(k)
k = k or 1
return self.RegistredModules[DPSSettings["windows"][k]["CurMode"]]:EvalTable(DPSMateUser[UnitName("player")], k)
end
function DPSMate:GetClassColor(class)
if not class then
class = "warrior"
end
if DPSMateUser[class] then
class = DPSMateUser[class][2] or "warrior"
end
if classcolor[class] then
return classcolor[class].r, classcolor[class].g, classcolor[class].b, class
end
return classcolor["warrior"].r, classcolor["warrior"].g, classcolor["warrior"].b, "warrior"
end
function DPSMate:GetMode(k)
k = k or 1
local Handler = DPSMate.RegistredModules[DPSSettings["windows"][k]["CurMode"]]
local opts = DPSSettings["windows"][k]["options"][2]
-- Check in deterministic order: total first, then currentfight, then segments
if opts["total"] then
return Handler.DB[1], DPSMateCombatTime["total"], DPSMateCombatTime["effective"][1]
end
if opts["currentfight"] then
return Handler.DB[2], DPSMateCombatTime["current"], DPSMateCombatTime["effective"][2]
end
local num
for cat, val in pairs(opts) do
if val and strfind(cat, "segment") then
num = tonumber(strsub(cat, 8))
if (Handler.Hist) and DPSHist[Handler.Hist] and self:TableLength(DPSHist[Handler.Hist]) >= num then
return DPSHist[Handler.Hist][num], DPSMateCombatTime["segments"][num][1], DPSMateCombatTime["segments"][num][2]
else
return {}, 0, 0
end
end
end
-- Fallback: default to total
return Handler.DB[1], DPSMateCombatTime["total"], DPSMateCombatTime["effective"][1]
end
function DPSMate:GetModeByArr(arr, k, Hist)
local opts = DPSSettings["windows"][k]["options"][2]
-- Check in deterministic order: total first, then currentfight, then segments
if opts["total"] then
return arr[1], DPSMateCombatTime["total"], DPSMateCombatTime["effective"][1]
end
if opts["currentfight"] then
return arr[2], DPSMateCombatTime["current"], DPSMateCombatTime["effective"][2]
end
local num
for cat, val in pairs(opts) do
if val and strfind(cat, "segment") then
num = tonumber(strsub(cat, 8))
if (Hist or arr.Hist) and DPSHist[Hist or arr.Hist] and self:TableLength(DPSHist[Hist or arr.Hist]) >= num then
return DPSHist[Hist or arr.Hist][num], DPSMateCombatTime["segments"][num][1], DPSMateCombatTime["segments"][num][2]
else
return {}, 0, 0
end
end
end
-- Fallback: default to total
return arr[1], DPSMateCombatTime["total"], DPSMateCombatTime["effective"][1]
end
function DPSMate:GetModeName(k)
k = k or 1
local opts = DPSSettings["windows"][k]["options"][2]
if opts["total"] then return "Total" end
if opts["currentfight"] then return "Current fight" end
local num
for cat, val in pairs(opts) do
if val and strfind(cat, "segment") then
num = tonumber(strsub(cat, 8))
return DPSHist["names"][num]
end
end
return "Total"
end
function DPSMate:Disable()
if self.Registered then
self.Sync:UnregisterEvent("CHAT_MSG_ADDON")
for _, event in pairs(self.Events) do
self.Parser:UnregisterEvent(event)
end
self.Registered = false
end
end
function DPSMate:Enable()
if not self.Registered then
self.Sync:RegisterEvent("CHAT_MSG_ADDON")
for _, val in pairs(self.RegistredModules) do
if val.Events then
for _, event in pairs(val.Events) do
self.Parser:RegisterEvent(event)
end
end
end
self.Registered = true
end
end
function DPSMate:Broadcast(type, who, what, with, value, failtype)
if DPSSettings["broadcasting"] then
if IsRaidLeader() or IsRaidOfficer() then
local ch = "RAID"
if DPSSettings["bcrw"] then
ch = "RAID_WARNING"
end
if DPSSettings["bccd"] and type == 1 then
SendChatMessage("BULK", "DPSMateChat", self.L["bccdo"](who, what), ch, nil, nil)
return
elseif DPSSettings["bccd"] and type == 6 then
SendChatMessage("BULK", "DPSMateChat", self.L["bccdt"](who, what), ch, nil, nil)
return
elseif DPSSettings["bcress"] and type == 2 then
SendChatMessage("BULK", "DPSMateChat", self.L["bcress"](who, what), ch, nil, nil)
return
elseif DPSSettings["bckb"] and type == 4 then
SendChatMessage("BULK", "DPSMateChat", self.L["bckb"](who, what, with, value), ch, nil, nil)
return
elseif DPSSettings["bcfail"] and type == 3 then
if failtype == 1 then
SendChatMessage("BULK", "DPSMateChat", self.L["bcfailo"](what, who, value, with), ch, nil, nil)
elseif failtype == 3 then
SendChatMessage("BULK", "DPSMateChat", self.L["bcfailt"](who, with), ch, nil, nil)
else
SendChatMessage("BULK", "DPSMateChat", self.L["bcfailth"](who, value, with, what), ch, nil, nil)
end
return
end
end
end
end
function DPSMate:SendMessage(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cFFFF8080"..self.L["name"].."|r: "..msg)
end
function DPSMate:Register(prefix, table, name)
self.ModuleNames[name] = prefix
self.RegistredModules[prefix] = table
end
+259
View File
@@ -0,0 +1,259 @@
## Interface: 11200
## Title: DPSMate |cFFFF8080-Enhanced-|r
## Notes: DPSMate is an advanced combat analyzation tool, providing helpful graphs and statistics to evaluate the fight.
## Notes-deDE: DPSMate ist ein Analysewerkzeug, das hilfreiche Graphen und Statistiken bereitstellt, um den Kampf zu evaluieren.
## Notes-ruRU: DPSMate это продвинутый инструмент анализа боя, предоставляет полезные графики и статистики для оценки боя.
## Author: Shino <Synced> - Kronos, Torio
## OptionalDeps: KLHThreatMeter
## SavedVariables: DPSMateSettings
libs\AceLibrary\AceLibrary.lua
libs\Dewdrop-2.0\Dewdrop-2.0.lua
libs\GraphLib\Graph-1.0\Graph-1.0.lua
libs\ChatThrottleLib.lua
enUS\Babble-Spell-2.3.lua
enUS\Babble-Boss-2.3.lua
enUS\NPCDB-1.0.lua
DPSMate.lua
DPSMate_CombatPatterns.lua
enUS\enUS.lua
DPSMate_Parser.lua
enUS\DPSMate_ParserENUS.lua
locales\Babble-Spell-2.3_deDE.lua
locales\Babble-Boss-2.3_deDE.lua
locales\NPCDB-1.0_deDE.lua
locales\deDE.lua
locales\DPSMate_ParserDEDE.lua
locales\Babble-Spell-2.3_frFR.lua
locales\Babble-Boss-2.3_frFR.lua
locales\NPCDB-1.0_frFR.lua
locales\frFR.lua
locales\DPSMate_ParserFRFR.lua
locales\Babble-Spell-2.3_koKR.lua
locales\Babble-Boss-2.3_koKR.lua
locales\NPCDB-1.0_koKR.lua
locales\koKR.lua
locales\DPSMate_ParserKRKR.lua
locales\Babble-Spell-2.3_ruRU.lua
locales\Babble-Boss-2.3_ruRU.lua
locales\NPCDB-1.0_ruRU.lua
locales\ruRU.lua
locales\DPSMate_ParserRURU.lua
locales\Babble-Spell-2.3_zhCN.lua
locales\Babble-Boss-2.3_zhCN.lua
locales\NPCDB-1.0_zhCN.lua
locales\zhCN.lua
locales\DPSMate_ParserZHCN.lua
DPSMate_Options.lua
DPSMate_Sync.lua
DPSMate_DataBuilder.lua
Damage\DPSMate_DPS.lua
Damage\DPSMate_Damage.lua
Damage\DPSMate_Details_Damage.lua
Damage\DPSMate_Details_Damage.xml
Damage\DPSMate_Details_DamageTotal.lua
Damage\DPSMate_Details_DamageTotal.xml
modules\DPSMate_Absorbs.lua
modules\DPSMate_Details_Absorbs.lua
modules\DPSMate_Details_Absorbs.xml
modules\DPSMate_Details_AbsorbsTotal.lua
modules\DPSMate_Details_AbsorbsTotal.xml
modules\DPSMate_AbsorbsTaken.lua
modules\DPSMate_Details_AbsorbsTaken.lua
modules\DPSMate_Details_AbsorbsTaken.xml
modules\DPSMate_Details_AbsorbsTakenTotal.lua
modules\DPSMate_Details_AbsorbsTakenTotal.xml
modules\DPSMate_Activity.lua
modules\DPSMate_AurasGained.lua
modules\DPSMate_AurasLost.lua
modules\DPSMate_AuraUptimers.lua
modules\DPSMate_Details_Auras.lua
modules\DPSMate_Details_Auras.xml
modules\DPSMate_Details_AurasTotal.lua
modules\DPSMate_Details_AurasTotal.xml
modules\DPSMate_Casts.lua
modules\DPSMate_Details_Casts.lua
modules\DPSMate_Details_Casts.xml
modules\DPSMate_Details_CastsTotal.lua
modules\DPSMate_Details_CastsTotal.xml
modules\DPSMate_CCBreaker.lua
modules\DPSMate_Details_CCBreaker.lua
modules\DPSMate_Details_CCBreaker.xml
modules\DPSMate_Details_CCBreakerTotal.lua
modules\DPSMate_Details_CCBreakerTotal.xml
modules\DPSMate_CureDisease.lua
modules\DPSMate_CureDiseaseReceived.lua
modules\DPSMate_Details_CureDisease.lua
modules\DPSMate_Details_CureDisease.xml
modules\DPSMate_Details_CureDiseaseReceived.lua
modules\DPSMate_Details_CureDiseaseReceived.xml
modules\DPSMate_Details_CureDiseaseTotal.lua
modules\DPSMate_Details_CureDiseaseTotal.xml
modules\DPSMate_CurePoison.lua
modules\DPSMate_CurePoisonReceived.lua
modules\DPSMate_Details_CurePoison.lua
modules\DPSMate_Details_CurePoison.xml
modules\DPSMate_Details_CurePoisonReceived.lua
modules\DPSMate_Details_CurePoisonReceived.xml
modules\DPSMate_Details_CurePoisonTotal.lua
modules\DPSMate_Details_CurePoisonTotal.xml
modules\DPSMate_DamageTaken.lua
modules\DPSMate_DTPS.lua
modules\DPSMate_Details_DamageTaken.lua
modules\DPSMate_Details_DamageTaken.xml
modules\DPSMate_Details_DamageTakenTotal.lua
modules\DPSMate_Details_DamageTakenTotal.xml
modules\DPSMate_Deaths.lua
modules\DPSMate_Details_Deaths.lua
modules\DPSMate_Details_Deaths.xml
modules\DPSMate_Details_DeathsTotal.lua
modules\DPSMate_Details_DeathsTotal.xml
modules\DPSMate_Debug.lua
modules\DPSMate_Decurses.lua
modules\DPSMate_DecursesReceived.lua
modules\DPSMate_Details_Decurses.lua
modules\DPSMate_Details_Decurses.xml
modules\DPSMate_Details_DecursesReceived.lua
modules\DPSMate_Details_DecursesReceived.xml
modules\DPSMate_Details_DecursesTotal.lua
modules\DPSMate_Details_DecursesTotal.xml
modules\DPSMate_Dispels.lua
modules\DPSMate_DispelsReceived.lua
modules\DPSMate_Details_Dispels.lua
modules\DPSMate_Details_Dispels.xml
modules\DPSMate_Details_DispelsReceived.lua
modules\DPSMate_Details_DispelsReceived.xml
modules\DPSMate_Details_DispelsTotal.lua
modules\DPSMate_Details_DispelsTotal.xml
modules\DPSMate_EDD.lua
modules\DPSMate_Details_EDD.lua
modules\DPSMate_Details_EDD.xml
modules\DPSMate_Details_EDDTotal.lua
modules\DPSMate_Details_EDDTotal.xml
modules\DPSMate_EDT.lua
modules\DPSMate_Details_EDT.lua
modules\DPSMate_Details_EDT.xml
modules\DPSMate_Details_EDTTotal.lua
modules\DPSMate_Details_EDTTotal.xml
modules\DPSMate_EffectiveHealing.lua
modules\DPSMate_EffectiveHPS.lua
modules\DPSMate_Details_EHealing.lua
modules\DPSMate_Details_EHealing.xml
modules\DPSMate_Details_EHealingTotal.lua
modules\DPSMate_Details_EHealingTotal.xml
modules\DPSMate_EffectiveHealingTaken.lua
modules\DPSMate_Details_EHealingTaken.lua
modules\DPSMate_Details_EHealingTaken.xml
modules\DPSMate_Details_EHealingTakenTotal.lua
modules\DPSMate_Details_EHealingTakenTotal.xml
modules\DPSMate_Fails.lua
modules\DPSMate_Details_Fails.lua
modules\DPSMate_Details_Fails.xml
modules\DPSMate_Details_FailsTotal.lua
modules\DPSMate_Details_FailsTotal.xml
modules\DPSMate_FriendlyFire.lua
modules\DPSMate_Details_FriendlyFire.lua
modules\DPSMate_Details_FriendlyFire.xml
modules\DPSMate_Details_FriendlyFireTotal.lua
modules\DPSMate_Details_FriendlyFireTotal.xml
modules\DPSMate_FriendlyFireTaken.lua
modules\DPSMate_Details_FriendlyFireTaken.lua
modules\DPSMate_Details_FriendlyFireTaken.xml
modules\DPSMate_Details_FriendlyFireTakenTotal.lua
modules\DPSMate_Details_FriendlyFireTakenTotal.xml
modules\DPSMate_Healing.lua
modules\DPSMate_HPS.lua
modules\DPSMate_Details_Healing.lua
modules\DPSMate_Details_Healing.xml
modules\DPSMate_Details_HealingTotal.lua
modules\DPSMate_Details_HealingTotal.xml
modules\DPSMate_HealingAndAbsorbs.lua
modules\DPSMate_Details_HealingAndAbsorbs.lua
modules\DPSMate_Details_HealingAndAbsorbs.xml
modules\DPSMate_Details_HealingAndAbsorbsTotal.lua
modules\DPSMate_Details_HealingAndAbsorbsTotal.xml
modules\DPSMate_HealingTaken.lua
modules\DPSMate_Details_HealingTaken.lua
modules\DPSMate_Details_HealingTaken.xml
modules\DPSMate_Details_HealingTakenTotal.lua
modules\DPSMate_Details_HealingTakenTotal.xml
modules\DPSMate_Interrupts.lua
modules\DPSMate_Details_Interrupts.lua
modules\DPSMate_Details_Interrupts.xml
modules\DPSMate_Details_InterruptsTotal.lua
modules\DPSMate_Details_InterruptsTotal.xml
modules\DPSMate_LiftMagic.lua
modules\DPSMate_LiftMagicReceived.lua
modules\DPSMate_Details_LiftMagic.lua
modules\DPSMate_Details_LiftMagic.xml
modules\DPSMate_Details_LiftMagicReceived.lua
modules\DPSMate_Details_LiftMagicReceived.xml
modules\DPSMate_Details_LiftMagicTotal.lua
modules\DPSMate_Details_LiftMagicTotal.xml
modules\DPSMate_OHealingTaken.lua
modules\DPSMate_Details_OHealingTaken.lua
modules\DPSMate_Details_OHealingTaken.xml
modules\DPSMate_Details_OverhealingTakenTotal.lua
modules\DPSMate_Details_OverhealingTakenTotal.xml
modules\DPSMate_Overhealing.lua
modules\DPSMate_OHPS.lua
modules\DPSMate_Details_Overhealing.lua
modules\DPSMate_Details_Overhealing.xml
modules\DPSMate_Details_OverhealingTotal.lua
modules\DPSMate_Details_OverhealingTotal.xml
modules\DPSMate_Procs.lua
modules\DPSMate_Details_Procs.lua
modules\DPSMate_Details_Procs.xml
modules\DPSMate_Details_ProcsTotal.lua
modules\DPSMate_Details_ProcsTotal.xml
modules\DPSMate_Threat.lua
modules\DPSMate_TPS.lua
modules\DPSMate_Details_Threat.lua
modules\DPSMate_Details_Threat.xml
modules\DPSMate_Details_ThreatTotal.lua
modules\DPSMate_Details_ThreatTotal.xml
DPSMate_Frame.xml
DPSMate_Options.xml
Bindings.xml
DPSMate_CLEUAdapter.lua
@@ -0,0 +1,588 @@
-- DPSMate CLEU Adapter
-- Replaces the string-parsing CHAT_MSG_* event system with structured COMBAT_LOG_EVENT
-- data from the DPSLog module. Registers for COMBAT_LOG_EVENT 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 + GetSpellInfo)
if not DPSMate or not DPSMate.DB 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")
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")
-- 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
-- ============================================================================
-- CLEU event handler
-- ============================================================================
cleuFrame:SetScript("OnEvent", function()
local sub = arg1
if not sub then return end
local srcGUID = arg2
local srcName = arg3
local dstGUID = arg4
local dstName = arg5
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 = arg6 or 0
local critical = arg12 == 1 and 1 or 0
local glancing = arg13 == 1 and 1 or 0
local crushing = arg14 == 1 and 1 or 0
local hit = (critical == 0 and glancing == 0 and crushing == 0) and 1 or 0
DB:DamageDone(srcName, AAttack, hit, critical, 0, 0, 0, 0, amount, glancing, 0)
DB:DamageTaken(dstName, AAttack, hit, critical, 0, 0, 0, 0, amount, srcName, crushing, 0)
DB:EnemyDamage(1, DPSMateEDT, dstName, AAttack, hit, critical, 0, 0, 0, 0, amount, srcName, 0, crushing)
DB:EnemyDamage(2, DPSMateEDD, srcName, AAttack, hit, critical, 0, 0, 0, 0, amount, dstName, 0, 0)
DB:DeathHistory(dstName, srcName, AAttack, amount, hit, critical, "hit", crushing)
elseif sub == "SWING_MISSED" then
local missType = arg6
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)
elseif sub == "SPELL_DAMAGE" or sub == "RANGE_DAMAGE" or sub == "SPELL_PERIODIC_DAMAGE"
or sub == "DAMAGE_SHIELD" or sub == "DAMAGE_SPLIT" then
local spellName = arg7 or "Unknown"
local amount = arg9 or 0
local school = arg11
local critical = arg15 == 1 and 1 or 0
local glancing = arg16 == 1 and 1 or 0
local crushing = arg17 == 1 and 1 or 0
local hit = (critical == 0 and glancing == 0 and crushing == 0) and 1 or 0
DB:DamageDone(srcName, spellName, hit, critical, 0, 0, 0, 0, amount, glancing, 0)
DB:DamageTaken(dstName, spellName, hit, critical, 0, 0, 0, 0, amount, srcName, crushing, 0)
DB:EnemyDamage(1, DPSMateEDT, dstName, spellName, hit, critical, 0, 0, 0, 0, amount, srcName, 0, crushing)
DB:EnemyDamage(2, DPSMateEDD, srcName, spellName, hit, critical, 0, 0, 0, 0, amount, dstName, 0, 0)
DB:DeathHistory(dstName, srcName, spellName, amount, hit, critical, "hit", crushing)
if school then DB:AddSpellSchool(spellName, school) end
elseif sub == "SPELL_MISSED" or sub == "RANGE_MISSED"
or sub == "SPELL_PERIODIC_MISSED" or sub == "DAMAGE_SHIELD_MISSED" then
local spellName = arg7 or "Unknown"
local missType = arg9
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, spellName, 0, 0, miss + absorb, parry, dodge, resist, 0, 0, block)
DB:DamageTaken(dstName, spellName, 0, 0, miss + absorb, parry, dodge, resist, 0, srcName, 0, block)
elseif sub == "ENVIRONMENTAL_DAMAGE" then
local envType = arg6
local amount = arg7 or 0
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 = arg7 or "Unknown"
local amount = arg9 or 0
local overheal = arg10 or 0
local critical = arg12 == 1 and 1 or 0
local hit = critical == 0 and 1 or 0
local effective = amount - overheal
if effective < 0 then effective = 0 end
DB:Healing(1, DPSMateHealingTaken, srcName, spellName, hit, critical, effective)
DB:Healing(2, DPSMateOverhealing, srcName, spellName, hit, critical, overheal)
DB:HealingTaken(1, DPSMateHealingTaken, srcName, spellName, hit, critical, effective, dstName)
DB:DeathHistory(dstName, srcName, spellName, effective, hit, critical, "heal", 0)
-- ========================================================================
-- AURA events
-- ========================================================================
elseif sub == "SPELL_AURA_APPLIED" then
local spellName = arg7 or "Unknown"
local auraType = arg9
if auraType == "DEBUFF" then
DB:BuildBuffs(srcName, dstName, spellName, false)
if Parser.CC[spellName] then
DB:BuildActiveCC(dstName, spellName)
end
else
DB:BuildBuffs(srcName, dstName, spellName, true)
end
elseif sub == "SPELL_AURA_REMOVED" then
local spellName = arg7 or "Unknown"
DB:DestroyBuffs(dstName, spellName)
local auraType = arg9
if auraType == "DEBUFF" then
DB:RemoveActiveCC(dstName, spellName)
end
elseif sub == "SPELL_AURA_BROKEN_SPELL" or sub == "SPELL_AURA_BROKEN" then
local spellName = arg7 or "Unknown"
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 = arg7 or "Unknown"
if Parser.Kicks and Parser.Kicks[spellName] then
DB:RegisterPotentialKick(srcName, spellName, GT())
end
-- ========================================================================
-- INTERRUPT / DISPEL events
-- ========================================================================
elseif sub == "SPELL_INTERRUPT" then
local spellName = arg7 or "Unknown"
local extraSpellName = arg10 or "Unknown"
DB:Kick(srcName, dstName, spellName, extraSpellName)
elseif sub == "SPELL_DISPEL" then
local spellName = arg7 or "Unknown"
local extraSpellName = arg10 or "Unknown"
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
local spellName = arg7 or "Unknown"
if not Parser.petToOwnerMap then Parser.petToOwnerMap = {} end
if not Parser.petToOwnerMap[dstName] then Parser.petToOwnerMap[dstName] = {} end
Parser.petToOwnerMap[dstName][srcName] = true
end
end)
-- ============================================================================
-- 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 }
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))
-- 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
-- /dpsbench -- enables per-combat A/B profiling. Each combat: measure, report, flip.
local benchActive = true
local benchFrame = CreateFrame("Frame")
local function benchCombatStart()
if not benchActive then return end
profCurrent = cleuActive and profCLEU or profOrig
profReset(profCurrent)
debugprofilestart() -- start the monotonic clock for this combat
profiling = true
local label = cleuActive and "CLEU" or "ORIGINAL"
DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff00ff00[DPS Bench]|r combat started, measuring %s", label))
end
local function benchCombatEnd()
if not benchActive or 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"))
end
benchFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
benchFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
benchFrame:SetScript("OnEvent", function()
if event == "PLAYER_REGEN_DISABLED" then
benchCombatStart()
elseif event == "PLAYER_REGEN_ENABLED" then
benchCombatEnd()
end
end)
SLASH_DPSBENCH1 = "/dpsbench"
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.",
cleuActive and "CLEU" or "ORIGINAL"))
else
profiling = false
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[DPS Bench]|r disabled.")
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)
cleuHandler = function()
local sub = arg1
if not sub then return end
local srcGUID = arg2
local srcName = arg3
local dstGUID = arg4
local dstName = arg5
if not srcName or srcName == "" then srcName = "Unknown" end
if not dstName or dstName == "" then dstName = "Unknown" end
if sub == "SWING_DAMAGE" then
local amount = arg6 or 0
local critical = arg12 == 1 and 1 or 0
local glancing = arg13 == 1 and 1 or 0
local crushing = arg14 == 1 and 1 or 0
local hit = (critical == 0 and glancing == 0 and crushing == 0) and 1 or 0
DB:DamageDone(srcName, AAttack, hit, critical, 0, 0, 0, 0, amount, glancing, 0)
DB:DamageTaken(dstName, AAttack, hit, critical, 0, 0, 0, 0, amount, srcName, crushing, 0)
DB:EnemyDamage(1, DPSMateEDT, dstName, AAttack, hit, critical, 0, 0, 0, 0, amount, srcName, 0, crushing)
DB:EnemyDamage(2, DPSMateEDD, srcName, AAttack, hit, critical, 0, 0, 0, 0, amount, dstName, 0, 0)
DB:DeathHistory(dstName, srcName, AAttack, amount, hit, critical, "hit", crushing)
elseif sub == "SWING_MISSED" then
local missType = arg6
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)
elseif sub == "SPELL_DAMAGE" or sub == "RANGE_DAMAGE" or sub == "SPELL_PERIODIC_DAMAGE"
or sub == "DAMAGE_SHIELD" or sub == "DAMAGE_SPLIT" then
local spellName = arg7 or "Unknown"
local amount = arg9 or 0
local school = arg11
local critical = arg15 == 1 and 1 or 0
local glancing = arg16 == 1 and 1 or 0
local crushing = arg17 == 1 and 1 or 0
local hit = (critical == 0 and glancing == 0 and crushing == 0) and 1 or 0
DB:DamageDone(srcName, spellName, hit, critical, 0, 0, 0, 0, amount, glancing, 0)
DB:DamageTaken(dstName, spellName, hit, critical, 0, 0, 0, 0, amount, srcName, crushing, 0)
DB:EnemyDamage(1, DPSMateEDT, dstName, spellName, hit, critical, 0, 0, 0, 0, amount, srcName, 0, crushing)
DB:EnemyDamage(2, DPSMateEDD, srcName, spellName, hit, critical, 0, 0, 0, 0, amount, dstName, 0, 0)
DB:DeathHistory(dstName, srcName, spellName, amount, hit, critical, "hit", crushing)
if school then DB:AddSpellSchool(spellName, school) end
elseif sub == "SPELL_MISSED" or sub == "RANGE_MISSED"
or sub == "SPELL_PERIODIC_MISSED" or sub == "DAMAGE_SHIELD_MISSED" then
local spellName = arg7 or "Unknown"
local missType = arg9
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, spellName, 0, 0, miss + absorb, parry, dodge, resist, 0, 0, block)
DB:DamageTaken(dstName, spellName, 0, 0, miss + absorb, parry, dodge, resist, 0, srcName, 0, block)
elseif sub == "ENVIRONMENTAL_DAMAGE" then
local envType = arg6
local amount = arg7 or 0
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)
elseif sub == "SPELL_HEAL" or sub == "SPELL_PERIODIC_HEAL" then
local spellName = arg7 or "Unknown"
local amount = arg9 or 0
local overheal = arg10 or 0
local critical = arg12 == 1 and 1 or 0
local hit = critical == 0 and 1 or 0
local effective = amount - overheal
if effective < 0 then effective = 0 end
DB:Healing(1, DPSMateHealingTaken, srcName, spellName, hit, critical, effective)
DB:Healing(2, DPSMateOverhealing, srcName, spellName, hit, critical, overheal)
DB:HealingTaken(1, DPSMateHealingTaken, srcName, spellName, hit, critical, effective, dstName)
DB:DeathHistory(dstName, srcName, spellName, effective, hit, critical, "heal", 0)
elseif sub == "SPELL_AURA_APPLIED" then
local spellName = arg7 or "Unknown"
local auraType = arg9
if auraType == "DEBUFF" then
DB:BuildBuffs(srcName, dstName, spellName, false)
if Parser.CC[spellName] then
DB:BuildActiveCC(dstName, spellName)
end
else
DB:BuildBuffs(srcName, dstName, spellName, true)
end
elseif sub == "SPELL_AURA_REMOVED" then
local spellName = arg7 or "Unknown"
DB:DestroyBuffs(dstName, spellName)
if arg9 == "DEBUFF" then
DB:RemoveActiveCC(dstName, spellName)
end
elseif sub == "SPELL_AURA_BROKEN_SPELL" or sub == "SPELL_AURA_BROKEN" then
local spellName = arg7 or "Unknown"
DB:RemoveActiveCC(dstName, spellName)
if Parser.CC[spellName] then
DB:CCBreaker(dstName, spellName, srcName)
end
elseif sub == "SPELL_CAST_SUCCESS" then
local spellName = arg7 or "Unknown"
if Parser.Kicks and Parser.Kicks[spellName] then
DB:RegisterPotentialKick(srcName, spellName, GT())
end
elseif sub == "SPELL_INTERRUPT" then
local spellName = arg7 or "Unknown"
local extraSpellName = arg10 or "Unknown"
DB:Kick(srcName, dstName, spellName, extraSpellName)
elseif sub == "SPELL_DISPEL" then
local spellName = arg7 or "Unknown"
local extraSpellName = arg10 or "Unknown"
if isGroupMember(srcName) then
DB:Dispels(srcName, spellName, dstName, extraSpellName)
end
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
end
-- Set the measured wrapper as the actual handler
cleuFrame:SetScript("OnEvent", measuredCLEUHandler)
-- ============================================================================
-- Start in CLEU mode by default
-- ============================================================================
enableCLEU()
@@ -0,0 +1,367 @@
-- DPSMate_CombatPatterns.lua
-- Pattern-based combat log matching using WoW global format strings.
-- Automatically adapts to server-specific combat log format changes (e.g., TWoW).
-- Field mappings are auto-detected from format string context, not hardcoded.
DPSMate.CombatPatterns = {}
local CP = DPSMate.CombatPatterns
local strfind = string.find
local strsub = string.sub
local tonumber = tonumber
local tinsert = table.insert
-- Convert a WoW format string (e.g., "You hit %s for %d.") to a Lua pattern
-- e.g., "You hit %s for %d." -> "^You hit (.+) for (%d+)%.$"
function CP:Sanitize(str)
if not str then return nil end
-- Replace format specifiers with placeholders before escaping
str = string.gsub(str, "%%s", "\001")
str = string.gsub(str, "%%d", "\002")
-- Escape Lua pattern magic characters
str = string.gsub(str, "([%(%)%.%%%+%-%*%?%[%]%^%$])", "%%%1")
-- Replace placeholders with capture groups
str = string.gsub(str, "\001", "(.+)")
str = string.gsub(str, "\002", "(%d+)")
return "^" .. str .. "$"
end
-- Strip combat log trailers: (X absorbed), (blocked), (glancing), (crushing), (X resisted)
-- Returns: cleaned_msg, absorbed_amount, blocked(0/1), glancing(bool), crushing(bool)
function CP:StripTrailers(msg)
local absorbed, blocked, glancing, crushing = 0, 0, false, false
local i, j, amt
i, j, amt = strfind(msg, " %((%d+) absorbed%)")
if i then absorbed = tonumber(amt); msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
i, j, amt = strfind(msg, " %((%d+) blocked%)")
if i then blocked = 1; msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
if blocked == 0 then
i, j = strfind(msg, " %(blocked%)")
if i then blocked = 1; msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
end
i, j = strfind(msg, " %(glancing%)")
if i then glancing = true; msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
i, j = strfind(msg, " %(crushing%)")
if i then crushing = true; msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
-- Strip resisted trailer to prevent pattern mismatch
i, j = strfind(msg, " %((%d+) resisted%)")
if i then msg = strsub(msg, 1, i-1) .. strsub(msg, j+1) end
return msg, absorbed, blocked, glancing, crushing
end
-- Try matching a message against a list of pattern entries
-- Each entry: {pattern_string, hitType_string, {field=captureIndex, ...}}
-- Returns: hitType, result_table (with named fields) on match, or nil
function CP:TryMatch(msg, patterns)
if not patterns then return nil end
for _, entry in ipairs(patterns) do
local pattern = entry[1]
if pattern then
local c = {strfind(msg, pattern)}
if c[1] then
local result = {}
local fields = entry[3]
for field, idx in pairs(fields) do
result[field] = c[idx + 2] -- +2 to skip start/end positions
end
if result.amount then result.amount = tonumber(result.amount) end
return entry[2], result
end
end
end
return nil
end
-- Auto-detect field names for each format specifier based on surrounding text context.
-- Returns a table mapping field_name -> capture_index, or nil if format is empty/invalid.
-- overrides: optional table mapping detected_name -> desired_name (e.g., {target="source"})
function CP:DetectFields(fmt, overrides)
if not fmt then return nil end
-- Parse specifiers and the text segments between them
local specs = {}
local n = 0
local pos = 1
while true do
local i, j, specType = strfind(fmt, "%%([sd])", pos)
if not i then break end
n = n + 1
specs[n] = {
type = specType,
before = strsub(fmt, pos, i - 1),
}
pos = j + 1
end
if n == 0 then return nil end
-- Set "after" text for each spec (text between this spec and the next, or trailing)
for i = 1, n - 1 do
specs[i].after = specs[i + 1].before
end
specs[n].after = strsub(fmt, pos)
-- Detect field name for each specifier based on surrounding text
local fields = {}
for i = 1, n do
local s = specs[i]
local field
if s.type == "d" then
field = "amount"
else
local before = s.before
local after = s.after
-- Rule 1: After "Your/your " -> ability (e.g., "Your %s hits")
if strfind(before, "Your ?$") or strfind(before, "your ?$") then
field = "ability"
-- Rule 2: After "'s " -> ability (e.g., "Source's %s hits")
elseif strfind(before, "'s ?$") or strfind(before, "' s ?$") then
field = "ability"
-- Rule 3: Before "'s" -> source (e.g., "%s's Ability", "%s 's Ability")
elseif strfind(after, "^'s") or strfind(after, "^' s") or strfind(after, "^ 's") then
field = "source"
-- Rule 4: Before " damage" -> school (e.g., "%d %s damage")
elseif strfind(after, "^ damage") then
field = "school"
-- Rule 5: Before " suffers" -> target (e.g., "%s suffers %d")
elseif strfind(after, "^ suffers") then
field = "target"
-- Rule 6: Before action verbs -> source (e.g., "%s hits", "%s critically hits")
elseif strfind(after, "^ hits") or strfind(after, "^ crits") or
strfind(after, "^ misses") or strfind(after, "^ attacks") or
strfind(after, "^ reflects") or strfind(after, "^ critically") then
field = "source"
-- Rule 7: Before reaction verbs -> target (e.g., "%s parries", "%s is immune")
elseif strfind(after, "^ parries") or strfind(after, "^ dodges") or
strfind(after, "^ blocks") or strfind(after, "^ absorbs") or
strfind(after, "^ is immune") then
field = "target"
-- Rule 8: Before " for " -> target (e.g., "hits %s for %d")
elseif strfind(after, "^ for ") then
field = "target"
-- Rule 9: After " to " -> target (e.g., "damage to %s")
elseif strfind(before, " to ?$") then
field = "target"
-- Rule 10: After " by " -> target (e.g., "dodged by %s")
elseif strfind(before, " by ?$") then
field = "target"
-- Rule 11: After " from " -> source (e.g., "damage from %s")
elseif strfind(before, " from ?$") then
field = "source"
-- Rule 12: "You <verb> %s" -> target (e.g., "You miss %s")
elseif strfind(before, "^You %a+ ?$") then
field = "target"
-- Rule 13: End of message -> target (fallback for last %s)
elseif strfind(after, "^%.?$") then
field = "target"
else
field = "target"
end
end
-- Apply overrides (e.g., env damage: detected "target" -> call it "source")
if overrides and overrides[field] then
field = overrides[field]
end
fields[field] = i
end
return fields
end
-- Flag indicating patterns have been built
CP.ready = false
-- Helper: add a pattern entry from a WoW global string name.
-- Field mappings are auto-detected from format string content.
-- overrides: optional table mapping detected_name -> desired_name
local function addP(tbl, globalName, hitType, overrides)
local str = getglobal(globalName)
if str then
local fields = CP:DetectFields(str, overrides)
if fields then
tinsert(tbl, {CP:Sanitize(str), hitType, fields})
end
end
end
-- Build all patterns from WoW globals.
-- MUST be called AFTER InitParser modifies the globals (adds space before 's).
function CP:BuildPatterns()
-- =================== SELF MELEE HITS ===================
-- "You hit Target for Amount [School damage]."
self.selfMeleeHit = {}
addP(self.selfMeleeHit, "COMBATHITCRITSCHOOLSELFOTHER", "crit")
addP(self.selfMeleeHit, "COMBATHITSCHOOLSELFOTHER", "hit")
addP(self.selfMeleeHit, "COMBATHITCRITSELFOTHER", "crit")
addP(self.selfMeleeHit, "COMBATHITSELFOTHER", "hit")
-- =================== OTHER MELEE HITS ===================
-- "Source hits Target for Amount [School damage]."
self.otherMeleeHit = {}
addP(self.otherMeleeHit, "COMBATHITCRITSCHOOLOTHEROTHER", "crit")
addP(self.otherMeleeHit, "COMBATHITSCHOOLOTHEROTHER", "hit")
addP(self.otherMeleeHit, "COMBATHITCRITOTHEROTHER", "crit")
addP(self.otherMeleeHit, "COMBATHITOTHEROTHER", "hit")
-- =================== SELF SPELL HITS ===================
-- "Your Ability hits Target for Amount [School damage]."
self.selfSpellHit = {}
addP(self.selfSpellHit, "SPELLLOGCRITSCHOOLSELFOTHER", "crit")
addP(self.selfSpellHit, "SPELLLOGSCHOOLSELFOTHER", "hit")
addP(self.selfSpellHit, "SPELLLOGCRITSELFOTHER", "crit")
addP(self.selfSpellHit, "SPELLLOGSELFOTHER", "hit")
addP(self.selfSpellHit, "SPELLLOGCRITSCHOOLSELFSELF", "crit")
addP(self.selfSpellHit, "SPELLLOGSCHOOLSELFSELF", "hit")
addP(self.selfSpellHit, "SPELLLOGCRITSELFSELF", "crit")
addP(self.selfSpellHit, "SPELLLOGSELFSELF", "hit")
-- =================== OTHER SPELL HITS ===================
-- "Source's Ability hits Target for Amount [School damage]."
self.otherSpellHit = {}
addP(self.otherSpellHit, "SPELLLOGCRITSCHOOLOTHEROTHER", "crit")
addP(self.otherSpellHit, "SPELLLOGSCHOOLOTHEROTHER", "hit")
addP(self.otherSpellHit, "SPELLLOGCRITOTHEROTHER", "crit")
addP(self.otherSpellHit, "SPELLLOGOTHEROTHER", "hit")
-- =================== PERIODIC DAMAGE ===================
-- "Target suffers Amount School damage from Source's Ability."
self.periodicDmg = {}
addP(self.periodicDmg, "PERIODICAURADAMAGEOTHEROTHER", "dot")
addP(self.periodicDmg, "PERIODICAURADAMAGESELFOTHER", "dot")
addP(self.periodicDmg, "PERIODICAURADAMAGEOTHERSELF", "dot")
addP(self.periodicDmg, "PERIODICAURADAMAGESELFSELF", "dot")
-- =================== DAMAGE SHIELDS ===================
self.dmgShield = {}
addP(self.dmgShield, "DAMAGESHIELDSELFOTHER", "shield")
addP(self.dmgShield, "DAMAGESHIELDOTHERSELF", "shield")
addP(self.dmgShield, "DAMAGESHIELDOTHEROTHER", "shield")
-- =================== ENVIRONMENTAL DAMAGE ===================
-- Entity "suffering" env damage is called "source" in the data model
local envOverride = {target = "source"}
self.envDmgSelf = {}
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_FALLING_SELF", "falling")
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_DROWNING_SELF", "drowning")
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_LAVA_SELF", "lava")
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_SLIME_SELF", "slime")
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_FIRE_SELF", "fire")
addP(self.envDmgSelf, "VSENVIRONMENTALDAMAGE_FATIGUE_SELF", "fatigue")
self.envDmgOther = {}
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_FALLING_OTHER", "falling", envOverride)
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_DROWNING_OTHER", "drowning", envOverride)
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_LAVA_OTHER", "lava", envOverride)
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_SLIME_OTHER", "slime", envOverride)
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_FIRE_OTHER", "fire", envOverride)
addP(self.envDmgOther, "VSENVIRONMENTALDAMAGE_FATIGUE_OTHER", "fatigue", envOverride)
-- =================== SELF SPELL MISSES ===================
self.selfSpellMiss = {}
addP(self.selfSpellMiss, "SPELLMISSSELFOTHER", "miss")
addP(self.selfSpellMiss, "SPELLRESISTSELFOTHER", "resist")
addP(self.selfSpellMiss, "SPELLPARRIEDSELFOTHER", "parry")
addP(self.selfSpellMiss, "SPELLDODGEDSELFOTHER", "dodge")
addP(self.selfSpellMiss, "SPELLLOGABSORBSELFOTHER", "absorb")
addP(self.selfSpellMiss, "SPELLBLOCKEDSELFOTHER", "block")
addP(self.selfSpellMiss, "SPELLIMMUNESELFOTHER", "immune")
-- =================== OTHER SPELL MISSES ===================
self.otherSpellMiss = {}
addP(self.otherSpellMiss, "SPELLMISSOTHEROTHER", "miss")
addP(self.otherSpellMiss, "SPELLRESISTOTHEROTHER", "resist")
addP(self.otherSpellMiss, "SPELLPARRIEDOTHEROTHER", "parry")
addP(self.otherSpellMiss, "SPELLDODGEDOTHEROTHER", "dodge")
addP(self.otherSpellMiss, "SPELLLOGABSORBOTHEROTHER", "absorb")
addP(self.otherSpellMiss, "SPELLBLOCKEDOTHEROTHER", "block")
addP(self.otherSpellMiss, "SPELLIMMUNEOTHEROTHER", "immune")
addP(self.otherSpellMiss, "SPELLEVADEDOTHEROTHER", "evade")
-- =================== SELF MELEE MISSES ===================
self.selfMeleeMiss = {}
addP(self.selfMeleeMiss, "MISSEDSELFOTHER", "miss")
addP(self.selfMeleeMiss, "VSPARRYSELFOTHER", "parry")
addP(self.selfMeleeMiss, "VSDODGESELFOTHER", "dodge")
addP(self.selfMeleeMiss, "VSBLOCKSELFOTHER", "block")
addP(self.selfMeleeMiss, "VSABSORBSELFOTHER", "absorb")
-- =================== OTHER MELEE MISSES ===================
self.otherMeleeMiss = {}
addP(self.otherMeleeMiss, "MISSEDOTHEROTHER", "miss")
addP(self.otherMeleeMiss, "VSPARRYOTHEROTHER", "parry")
addP(self.otherMeleeMiss, "VSDODGEOTHEROTHER", "dodge")
addP(self.otherMeleeMiss, "VSBLOCKOTHEROTHER", "block")
addP(self.otherMeleeMiss, "VSABSORBOTHEROTHER", "absorb")
self.ready = true
end
-- Debug: dump all detected patterns and their field mappings to chat.
-- Usage in-game: /script DPSMate.CombatPatterns:DebugDump()
function CP:DebugDump()
local function dump(name, tbl)
if not tbl or not tbl[1] then return end
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FF00=== " .. name .. " ===|r")
for i, entry in ipairs(tbl) do
local hitType = entry[2] or "nil"
local fields = entry[3]
local fieldStr = ""
if fields then
for k, v in pairs(fields) do
if fieldStr ~= "" then fieldStr = fieldStr .. ", " end
fieldStr = fieldStr .. k .. "=" .. v
end
end
DEFAULT_CHAT_FRAME:AddMessage(" " .. hitType .. ": {" .. fieldStr .. "}")
end
end
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00--- CombatPatterns Debug Dump ---|r")
dump("selfMeleeHit", self.selfMeleeHit)
dump("otherMeleeHit", self.otherMeleeHit)
dump("selfSpellHit", self.selfSpellHit)
dump("otherSpellHit", self.otherSpellHit)
dump("periodicDmg", self.periodicDmg)
dump("dmgShield", self.dmgShield)
dump("envDmgSelf", self.envDmgSelf)
dump("envDmgOther", self.envDmgOther)
dump("selfSpellMiss", self.selfSpellMiss)
dump("otherSpellMiss", self.otherSpellMiss)
dump("selfMeleeMiss", self.selfMeleeMiss)
dump("otherMeleeMiss", self.otherMeleeMiss)
DEFAULT_CHAT_FRAME:AddMessage("|cFF00FF00CP.ready = " .. tostring(self.ready) .. "|r")
end
-- Debug: test auto-detection on a specific WoW global and show the result.
-- Usage: /script DPSMate.CombatPatterns:DebugGlobal("PERIODICAURADAMAGEOTHERSELF")
function CP:DebugGlobal(globalName, overrides)
local str = getglobal(globalName)
if not str then
DEFAULT_CHAT_FRAME:AddMessage("|cFFFF0000" .. globalName .. " = nil|r")
return
end
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00" .. globalName .. "|r = \"" .. str .. "\"")
local fields = self:DetectFields(str, overrides)
if fields then
local fieldStr = ""
for k, v in pairs(fields) do
if fieldStr ~= "" then fieldStr = fieldStr .. ", " end
fieldStr = fieldStr .. k .. "=" .. v
end
DEFAULT_CHAT_FRAME:AddMessage(" Fields: {" .. fieldStr .. "}")
else
DEFAULT_CHAT_FRAME:AddMessage(" |cFFFF0000No fields detected|r")
end
DEFAULT_CHAT_FRAME:AddMessage(" Pattern: " .. (self:Sanitize(str) or "nil"))
end
File diff suppressed because it is too large Load Diff
+420
View File
@@ -0,0 +1,420 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\..\..\FrameXML\UI.xsd">
<StatusBar name="DPSMate_Bar" virtual="true">
<Size y="12" />
<Layers>
<Layer level="ARTWORK">
<FontString name="$parent_Name" inherits="TextStatusBarText" justifyH="LEFT">
<Anchors>
<Anchor point="TOPLEFT" />
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parent_Value" inherits="TextStatusBarText" justifyH="RIGHT">
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT">
<Offset x="-3" y="0" />
</Anchor>
</Anchors>
</FontString>
</Layer>
<Layer level="BACKGROUND">
<Texture name="$parent_BG">
<Anchors>
<Anchor point="TOPLEFT" />
<Anchor point="BOTTOMRIGHT" />
</Anchors>
<Color r="0" g="0" b="0" />
</Texture>
</Layer>
<Layer level="OVERLAY">
<Texture name="$parent_Icon" file="Interface\AddOns\DPSMate\images\class\hunter" hidden="true">
<Size x="13" y="13" />
<Anchors>
<Anchor point="LEFT" />
</Anchors>
</Texture>
</Layer>
</Layers>
</StatusBar>
<StatusBar name="DPSMate_StatusBar" inherits="DPSMate_Bar" virtual="true">
<Scripts>
<OnLoad>
this:SetMinMaxValues(1,100)
this:SetValue(100)
getglobal(this:GetName().."_BG"):SetAlpha(0.5)
</OnLoad>
<OnMouseUp>
if arg1 == "LeftButton" then
DPSMate.Options:UpdateDetails(this)
else
DPSMate.Options:InializePlayerDewDrop(this)
DPSMate.Options:OpenMenu(4, this)
end
</OnMouseUp>
<OnEnter>
DPSMate.Options:ShowTooltip()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</StatusBar>
<StatusBar name="DPSMate_StatusBarTotal" inherits="DPSMate_Bar" virtual="true">
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["leftclickopend"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnMouseUp>
DPSMate.Options:UpdateTotalDetails(this)
</OnMouseUp>
</Scripts>
</StatusBar>
<Frame name="DPSMate_Statusframe" parent="UIParent" movable="true" enablemouse="true" resizable="true" frameStrata="low" virtual="true">
<Size x="150" y="100" />
<ResizeBounds>
<minResize x="100" y="100"/>
<maxResize x="400" y="600"/>
</ResizeBounds>
<Anchors>
<Anchor point="CENTER" />
</Anchors>
<Scripts>
<OnLoad>
this:SetClampedToScreen(true)
</OnLoad>
<OnSizeChanged>
if getglobal(this:GetName().."_ScrollFrame") then
getglobal(this:GetName().."_ScrollFrame_Child"):SetWidth(this:GetWidth())
getglobal(this:GetName().."_ScrollFrame"):SetHeight(this:GetHeight()-16)
end
</OnSizeChanged>
</Scripts>
<Frames>
<Frame name="$parent_Border" frameStrata="BACKGROUND">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="-4" y="4" />
</Anchor>
<Anchor point="TOPRIGHT">
<Offset x="4" y="4" />
</Anchor>
<Anchor point="BOTTOMLEFT">
<Offset x="-4" y="-4" />
</Anchor>
<Anchor point="BOTTOMRIGHT">
<Offset x="4" y="-4" />
</Anchor>
</Anchors>
<Backdrop edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets left="5" right="5" top="3" bottom="1" />
<TileSize val="12" />
<EdgeSize val="4" />
<Color r="0.157" g="0.08" b="0.06" a="1" />
</Backdrop>
</Frame>
<Button name="$parent_Resize" frameStrata="HIGH">
<Size x="14" y="14" />
<Anchors>
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT" />
</Anchors>
<Scripts>
<OnMouseDown>
this:GetParent():StartSizing()
</OnMouseDown>
<OnMouseUp>
this:GetParent():StopMovingOrSizing()
DPSMateSettings["windows"][this:GetParent().Key]["savsize"] = {}
DPSMateSettings["windows"][this:GetParent().Key]["savsize"][1] = this:GetParent():GetWidth()
DPSMateSettings["windows"][this:GetParent().Key]["savsize"][2] = this:GetParent():GetHeight()
</OnMouseUp>
</Scripts>
<NormalTexture file="Interface\AddOns\DPSMate\images\UI-ChatIM-SizeGrabber-Up"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\UI-ChatIM-SizeGrabber-Down"/>
<HighlightTexture file="Interface\AddOns\DPSMate\images\UI-ChatIM-SizeGrabber-Highlight" alphaMode="ADD"/>
</Button>
<Frame name="$parent_Head">
<Size y="16" />
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="TOPRIGHT"/>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parent_Background">
<Color r="1" g="0.82" b="0"/>
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
</Texture>
</Layer>
<Layer level="ARTWORK">
<FontString name="$parent_Font" inherits="GameFontNormalSmall" justifyH="LEFT">
<Size x="200" y="16" />
<Anchors>
<Anchor point="LEFT" />
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["rcchangemode"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnMouseDown>
if arg1 == "LeftButton" and not DPSMateSettings.lock then
this:GetParent():StartMoving()
end
</OnMouseDown>
<OnMouseUp>
if arg1 == "RightButton" then
DPSMate.Options:OpenMenu(1, this:GetParent())
else
this:GetParent():StopMovingOrSizing()
local point, _, _, xOfs, yOfs = this:GetParent():GetPoint()
DPSMateSettings["windows"][this:GetParent().Key]["position"] = {}
DPSMateSettings["windows"][this:GetParent().Key]["position"][1] = point
DPSMateSettings["windows"][this:GetParent().Key]["position"][2] = xOfs
DPSMateSettings["windows"][this:GetParent().Key]["position"][3] = yOfs
end
</OnMouseUp>
</Scripts>
<Frames>
<Button name="$parent_Config">
<Size x="16" y="16" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["config"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnMouseUp>
DPSMate.Options:OpenMenu(3, this:GetParent():GetParent())
</OnMouseUp>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\icon-config" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\icon-config"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\icon-config"/>
</Button>
<Button name="$parent_Reset">
<Size x="14" y="14" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["reset"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate_PopUp:Show()
</OnClick>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\icon-reset" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\icon-reset"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\icon-reset"/>
</Button>
<Button name="$parent_Segments">
<Size x="14" y="14" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["segment"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnMouseUp>
DPSMate.Options:OpenMenu(2, this:GetParent():GetParent())
</OnMouseUp>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up"/>
</Button>
<Button name="$parent_Filter">
<Size x="14" y="14" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["filter"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnMouseUp>
DPSMate.Options:OpenMenu(5, this:GetParent():GetParent())
</OnMouseUp>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-PublicNote-Up"/>
</Button>
<Button name="$parent_Report">
<Size x="14" y="14" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["report"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate_Report.PaKey=this:GetParent():GetParent().Key
DPSMate_Report:Show()
</OnClick>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-MOTD-Up" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-MOTD-Up"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\UI-GuildButton-MOTD-Up"/>
</Button>
<Button name="$parent_Sync">
<Size x="14" y="14" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["sync"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate.Options:ToggleSync()
</OnClick>
</Scripts>
<HighlightTexture file="Interface\AddOns\DPSMate\images\sync" alphaMode="ADD"/>
<NormalTexture file="Interface\AddOns\DPSMate\images\sync"/>
<PushedTexture file="Interface\AddOns\DPSMate\images\sync"/>
</Button>
<Checkbutton name="$parent_Enable" inherits="UICheckButtonTemplate">
<Size x="18" y="18" />
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "TOPLEFT")
GameTooltip:AddLine(DPSMate.L["enabledisable"])
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate.Options:ToggleState()
</OnClick>
</Scripts>
</Checkbutton>
</Frames>
</Frame>
<ScrollFrame name="$parent_ScrollFrame">
<Size y="84" />
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_Head" relativePoint="BOTTOMLEFT">
<Offset x="0.5" y="0" />
</Anchor>
<Anchor point="TOPRIGHT" relativeTo="$parent_Head" relativePoint="BOTTOMRIGHT" />
</Anchors>
<Layers>
<Layer leve="BACKGROUND">
<Texture name="$parent_Background" file="Interface\Tooltips\UI-Tooltip-Background">
<Color r="1" g="1" b="1"/>
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnLoad>
this:SetVerticalScroll(0)
</OnLoad>
<OnMouseWheel>
DPSMate.Options:OnVerticalScroll(this, arg1)
</OnMouseWheel>
</Scripts>
<ScrollChild>
<Frame name="$parent_Child">
<Size x="400" />
<Frames>
<StatusBar name="$parent_Total" inherits="DPSMate_StatusBarTotal" />
<StatusBar name="$parent_StatusBar1" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar2" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar3" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar4" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar5" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar6" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar7" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar8" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar9" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar10" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar11" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar12" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar13" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar14" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar15" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar16" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar17" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar18" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar19" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar20" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar21" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar22" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar23" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar24" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar25" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar26" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar27" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar28" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar29" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar30" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar31" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar32" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar33" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar34" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar35" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar36" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar37" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar38" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar39" inherits="DPSMate_StatusBar" />
<StatusBar name="$parent_StatusBar40" inherits="DPSMate_StatusBar" />
</Frames>
</Frame>
</ScrollChild>
</ScrollFrame>
</Frames>
</Frame>
<GameTooltip name="DPSMate_Tooltip" frameStrata="TOOLTIP" hidden="false" parent="UIParent" inherits="GameTooltipTemplate">
<Scripts>
<Onload>
this:SetOwner(WorldFrame, "ANCHOR_NONE")
</Onload>
</Scripts>
</GameTooltip>
</Ui>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+819
View File
@@ -0,0 +1,819 @@
-- Events
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_PET_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_PET_MISSES")
--DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PET_BUFF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PET_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_SELF_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE") --
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE") --
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_PARTY_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_PARTY_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_BREAK_AURA")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_SELF")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_OTHER")
DPSMate.Parser:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_PARTY")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLY_DEATH")
DPSMate.Parser:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH")
DPSMate.Parser:RegisterEvent("PLAYER_AURAS_CHANGED")
DPSMate.Parser:RegisterEvent("PLAYER_LOGOUT")
DPSMate.Parser:RegisterEvent("PLAYER_ENTERING_WORLD")
BINDING_HEADER_DPSMATE = "DPSMate"
BINDING_NAME_DPSMATE_REPORT = DPSMate.L["togglereportframe"]
BINDING_NAME_DPSMATE_TOGGLE = DPSMate.L["toggleframes"]
BINDING_NAME_DPSMATE_RESET = DPSMate.L["resetdpsmate"]
-- Global Variables
DPSMate.Parser.procs = {
-- General
["Earthstrike"] = true,
["Juju Flurry"] = true,
["Holy Strength"] = true,
["Ephemeral Power"] = true,
["Chromatic Infusion"] = true,
["Brittle Armor"] = true,
["Unstable Power"] = true,
["Zandalarian Hero Medallion"] = true,
["Ascendance"] = true,
["Essence of Sapphiron"] = true,
["Hand of Justice"] = true,
["Sword Specialization"] = true,
["Bonereaver's Edge"] = true,
--New
["Felstriker"] = true,
["Sanctuary"] = true,
["Fury of Forgewright"] = true,
["Primal Blessing"] = true,
["Spinal Reaper"] = true, -- To test
["Netherwind Focus"] = true, -- To test
["Parry"] = true, -- To test
["Untamed Fury"] = true,
["The Eye of Diminution"] = true,
["Kiss of the Spider"] = true,
["Glyph of Deflection"] = true,
["The Eye of the Dead"] = true,
["Slayer's Crest"] = true,
["Badge of the Swarmguard"] = true,
["Arcane Shroud"] = true,
["Persistent Shield"] = true,
["Jom Gabbar"] = true,
["The Burrower's Shell"] = true,
["Thrash"] = true,
["Free Action"] = true,
["Living Free Action"] = true,
["Restoration"] = true,
["Speed"] = true,
["Invulnerability"] = true,
["Aura of the Blue Dragon"] = true, -- Mana Darkmoon card
["Battle Squawk"] = true,
["Devilsaur Fury"] = true,
["Furious Howl"] = true,
["Healing Potion"] = true,
["Major Rejuvenation Potion"] = true,
["Mana Potion"] = true,
["Restore Mana"] = true,
["Dreamless Sleep"] = true,
-- Rogue
["Slice and Dice"] = true,
["Blade Flurry"] = true,
["Sprint"] = true,
["Adrenaline Rush"] = true,
["Vanish"] = true,
["Relentless Strikes Effect"] = true,
["Ruthlessness"] = true, -- To Test!!!!
["Rogue Armor Energize Effect"] = true,
["Rogue Armor Energize"] = true,
["Invigorate"] = true,
["Head Rush"] = true,
["Venomous Totem"] = true,
["Evasion"] = true,
["Restore Energy"] = true,
["Remorseless Attacks"] = true,
-- Mage
["Arcane Power"] = true,
["Combustion"] = true,
["Mind Quickening"] = true,
["Enigma Resist Bonus"] = true,
["Enigma Blizzard Bonus"] = true,
["Adaptive Warding"] = true,
["Not There"] = true,
["Cold Snap"] = true,
["Presence of Mind"] = true,
["Ice Block"] = true,
["Evocation"] = true,
-- Priest
["Power Infusion"] = true,
["Oracle Healing Bonus"] = true,
["Epiphany"] = true,
["Aegis of Preservation"] = true,
["Inspiration"] = true,
["Blessed Recovery"] = true,
["Focused Casting"] = true,
["Spirit Tap"] = true,
-- Druid
["Symbols of Unending Life Finisher Bonus"] = true,
["Metamorphosis Rune"] = true,
["Clearcasting"] = true,
["Nature's Grace"] = true,
-- Paladin
["Battlegear of Eternal Justice"] = true,
["Blinding Light"] = true,
["Divine Favor"] = true,
["Divine Shield"] = true,
["Redoubt"] = true,
["Holy Shield"] = true,
["Vengeance"] = true,
["Blessing of Freedom"] = true,
["Blessing of Sacrifice"] = true,
["Blessing of Protection"] = true,
-- Shaman
["Stormcaller's Wrath"] = true,
["Nature Aligned"] = true,
["Elemental Mastery"] = true,
["Windfury Weapon"] = true,
["Windfury Totem"] = true,
["Nature's Swiftness"] = true,
["Ancestral Healing"] = true,
["Reincarnation"] = true,
-- Warlock
["Vampirism"] = true,
["Nightfall"] = true,
["Soul Link"] = true,
["Life Tap"] = true,
-- Warrior
["Cheat Death"] = true,
["Gift of Life"] = true,
["Bloodrage"] = true,
["Flurry"] = true,
["Enrage"] = true,
["Sweeping Strikes"] = true,
["Death Wish"] = true,
["Recklessness"] = true,
["Mighty Rage"] = true,
["Great Rage"] = true,
["Rage"] = true,
["Berserker Rage"] = true,
["Shield Wall"] = true,
["Retaliation"] = true,
["Diamond Flask"] = true,
["Shield Block"] = true,
["Last Stand"] = true,
-- Hunter
["Arcane Infused"] = true,
["Quick Shots"] = true,
["Rapid Fire"] = true,
-- Boss Spells
["Lucifron's Curse"] = true,
["Gehennas' Curse"] = true,
["Panic"] = true,
["Living Bomb"] = true,
["Brood Affliction: Bronze"] = true,
["Bellowing Roar"] = true,
["Fear"] = true,
["Entangle"] = true,
["Digestive Acid"] = true,
["Locust Swarm"] = true,
["Web Wrap"] = true,
["Mutating Injection"] = true,
["Terrifying Roar"] = true,
}
DPSMate.Parser.BuffExceptions = {
["Fury of Forgewright"] = true,
["Bloodfang"] = true,
}
DPSMate.Parser.OtherExceptions = {
["Mighty Rage"] = true,
["Bloodrage"] = true,
["Holy Strength"] = true,
["Dreamless Sleep"] = true,
["Vampirism"] = true,
}
DPSMate.Parser.DmgProcs = {
-- General
["Life Steal"] = true,
["Thunderfury"] = true,
-- New
["Bloodfang"] = true,
["Fatal Wound"] = true,
["Decapitate"] = true,
["Gutgore Ripper"] = true,
["Firebolt"] = true,
-- Can't add Hand of Ragnaros
["Expose Weakness"] = true, -- To Test
["Silence"] = true, -- To Test
["Chilled"] = true, -- To Test
["Glimpse of Madness"] = true, -- To Test
["Engulfing Shadows"] = true, -- To Test
["Elemental Vulnerability"] = true, -- To Test
["Holy Power"] = true, -- To Test
["Revealed Flaw"] = true, -- To Test
["Totemic Power"] = true, -- To Test
["Stygian Grasp"] = true, -- To Test
["Electric Discharge"] = true, -- To Test
["Flame Lash"] = true, -- To Test
["Spell Vulnerability"] = true, -- To Test
["Lightning Strike"] = true, -- To Test
-- Deathbringer Skipped
}
DPSMate.Parser.IgnoredDmgSpells = {
}
DPSMate.Parser.TargetParty = {}
DPSMate.Parser.RCD = {
["Shield Wall"] = true,
["Recklessness"] = true,
["Retaliation"] = true,
["Last Stand"] = true,
["Innervate"] = true,
["Divine Shield"] = true,
["Blessing of Protection"] = true,
["Gift of Life"] = true,
["Redemption"] = true,
["Rebirth"] = true,
["Resurrection"] = true,
["Reincarnation"] = true,
["Ancestral Spirit"] = true,
["Soulstone Resurrection"] = true,
}
DPSMate.Parser.FailDT = {
-- Molten Core
["Rain of Fire"] = true,
["Cone of Fire"] = true,
["Lava Bomb"] = true,
["Eruption"] = true,
["Earthquake"] = true,
["Hand of Ragnaros"] = true,
["Wrath of Ragnaros"] = true,
["Conflagration"] = true,
-- Blackwing Lair
["War Stomp"] = true,
["Incinerate"] = true,
["Corrosive Acid"] = true,
["Frost Burn"] = true,
["Ignite Flesh"] = true,
["Time Lapse"] = true,
-- Zul Gurub
["Whirlwind"] = true,
["Charge"] = true,
["Poison Cloud"] = true,
-- AQ 20
["Arcane Eruption"] = true,
["Harsh Winds"] = true,
["Sand Trap"] = true,
-- AQ 40
["Toxin Cloud"] = true,
["Arcane Burst"] = true,
["Eye Beam"] = true,
["Dark Glare"] = true,
-- Naxx
["Negative Charge"] = true,
["Positive Charge"] = true,
["Void Zone"] = true,
["Plague Cloud"] = true,
["Blizzard"] = true,
["Chill"] = true,
["Frost Breath"] = true,
["Mana Detonation"] = true,
["Shadow Fissure"] = true,
}
DPSMate.Parser.FailDB = {
-- Molten Core
-- Blackwing Lair
["Suppression Aura"] = true,
["Bellowing Roar"] = true,
}
DPSMate.Parser.CC = {
["Sap"] = true,
["Gouge"] = true,
["Sleep"] = true,
["Polymorph"] = true,
["Greater Polymorph"] = true,
["Polymorph: Chicken"] = true,
["Polymorph: Cow"] = true,
["Polymorph: Pig"] = true,
["Polymorph: Sheep"] = true,
["Polymorph: Turtle"] = true,
["Blind"] = true,
["Freezing Trap Effect"] = true,
["Intimidating Shout"] = true,
["Magic Dust"] = true,
["Scatter Shot"] = true,
["Wyvern Sting"] = true,
["Seduction"] = true,
["Repentance"] = true,
["Shackle Undead"] = true,
["Reckless Charge"] = true,
}
DPSMate.Parser.Dispels = {
["Remove Curse"] = true,
["Cleanse"] = true,
["Remove Lesser Curse"] = true,
["Purify"] = true,
["Dispel Magic"] = true,
["Abolish Poison"] = true,
["Abolish Disease"] = true,
["Devour Magic"] = true,
["Cure Disease"] = true,
["Poison Cleansing Totem"] = true,
["Cure Poison"] = true,
["Disease Cleansing Totem"] = true,
["Purge"] = true,
-- Potion
["Powerful Anti-Venom"] = true,
["Restoration"] = true,
["Purification"] = true,
["Purification Potion"] = true,
["Restorative Potion"] = true,
}
DPSMate.Parser.DeCurse = {
["Remove Curse"] = true,
["Remove Lesser Curse"] = true,
["Restoration"] = true,
["Purification"] = true,
}
DPSMate.Parser.DeMagic = {
["Dispel Magic"] = true,
["Devour Magic"] = true,
["Purge"] = true,
["Restoration"] = true,
}
DPSMate.Parser.DeDisease = {
["Purify"] = true,
["Abolish Disease"] = true,
["Cure Disease"] = true,
["Disease Cleansing Totem"] = true,
["Restoration"] = true,
["Purification"] = true,
}
DPSMate.Parser.DePoison = {
["Abolish Poison"] = true,
["Purify"] = true,
["Poison Cleansing Totem"] = true,
["Cure Poison"] = true,
["Powerful Anti-Venom"] = true,
["Restoration"] = true,
["Purification"] = true,
}
DPSMate.Parser.DebuffTypes = {}
DPSMate.Parser.HotDispels = {
["Abolish Poison"] = true,
["Abolish Disease"] = true,
["Restoration"] = true,
}
DPSMate.Parser.Kicks = {
-- Interrupts
-- Rogue
["Kick"] = true,
-- Warrior
["Pummel"] = true,
["Shield Bash"] = true,
-- Mage
["Counterspell"] = true,
-- Shaman
["Earth Shock"] = true,
-- Priest
["Silence"] = true,
-- Stuns
-- Rogue
["Gouge"] = true,
["Kidney Shot"] = true,
["Cheap Shot"] = true,
-- Hunter
["Scatter Shot"] = true,
["Improved Concussive Shot"] = true,
["Wyvern Sting"] = true,
["Intimidation"] = true,
-- Warrior
["Charge Stun"] = true,
["Intercept Stun"] = true,
["Concussion Blow"] = true,
-- Druid
["Feral Charge"] = true,
["Feral Charge Effect"] = true,
["Bash"] = true,
["Pounce"] = true,
-- Mage
["Impact"] = true,
-- Paladin
["Repentance"] = true,
["Hammer of Justice"] = true,
-- Warlock
["Pyroclasm"] = true,
["Death Coil"] = true,
-- Priest
["Blackout"] = true,
-- General
["Tidal Charm"] = true,
["Reckless Charge"] = true,
}
DPSMate.Parser.player = UnitName("player")
DPSMate.Parser.playerclass = nil
-- Local Variables
local playerclassLoc,playerclass = UnitClass("player")
local fac = UnitFactionGroup("player")
local UL = UnitLevel
local DPSTool = {}
local DPSToolTextLeft1 = {}
local GetPlayerBuff = GetPlayerBuff
-- Begin Functions
function DPSMate.Parser:OnLoad()
self.player, self.realm = UnitName("player")
DPSMate.DB:BuildUser(self.player, strlower(playerclass))
if DPSMateUser[self.player] then
DPSMateUser[self.player][2] = strlower(playerclass)
DPSMateUser[self.player][8] = UL("player")
end
-- Prevent this addon from causing issues
if SW_FixLogStrings then
DPSMate:SendMessage("Please disable SW_StatsFixLogStrings and SW_Stats. Those addons cause issues.")
end
DPSTool = DPSMate_Tooltip
DPSToolTextLeft1 = DPSMate_TooltipTextLeft1
if self.InitParser then
self:InitParser()
end
end
local UnitName = UnitName
function DPSMate.Parser:GetUnitByName(target)
local unit = self.TargetParty[target]
if not unit then
if target==UnitName("player") then
unit="player"
elseif target==UnitName("target") then
unit="target"
end
end
return unit
end
local UnitHealthMax = UnitHealthMax
local UnitHealth = UnitHealth
function DPSMate.Parser:GetOverhealByName(amount, target)
local result, unit = 0, self:GetUnitByName(target)
if not amount then
return 0;
end
if unit then result = amount-(UnitHealthMax(unit)-UnitHealth(unit)) end
if result<0 then return 0 else return result end
end
local UnitClass = UnitClass
local UnitName = UnitName
local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers
local GetRaidRosterInfo = GetRaidRosterInfo
local subGRP, PSGRP, c
function DPSMate.Parser:AssociateShaman(name, old, update)
if not subGRP or not PSGRP[name] or update then
local tnum = GetNumPartyMembers()
subGRP, PSGRP = {}, {}
if tnum <= 0 then
tnum=GetNumRaidMembers()
for i=1, tnum do
_, _, c = GetRaidRosterInfo(i)
if UnitClass("raid"..i)==DPSMate.L["shaman"] then
subGRP[c] = UnitName("raid"..i)
end
PSGRP[UnitName("raid"..i)] = c
end
else
for i=1, tnum do
if UnitClass("party"..i)==DPSMate.L["shaman"] then
subGRP[1] = UnitName("party"..i)
end
PSGRP[UnitName("party"..i)] = 1
end
PSGRP[name] = 1
end
end
if PSGRP[name] and subGRP[PSGRP[name]] then
return subGRP[PSGRP[name]]
end
return old
end
-- Qualify a pet/totem source name with its owner for disambiguation.
-- When _petOwner is set (PET_ events), use the player as owner.
-- Otherwise, look up the petToOwnerMap for single-owner pets.
function DPSMate.Parser:QualifyPetSource(source)
if self._petOwner then
return source .. " (" .. self._petOwner .. ")"
end
if self.petToOwnerMap and self.petToOwnerMap[source] then
local count, singleOwner = 0, nil
for o, _ in pairs(self.petToOwnerMap[source]) do
count = count + 1
singleOwner = o
end
if count == 1 then
return source .. " (" .. singleOwner .. ")"
end
end
return source
end
-- The totem aura just reports a removed event in the chat.
-- Maybe we can guess here?
local UnitDebuff = UnitDebuff
DPSMate.Parser.PLAYER_AURAS_CHANGED = function(unit)
local aura, debuffDispelType
if DPSTool.SetPlayerBuff then
for i=1, 4 do
DPSTool:SetPlayerBuff(GetPlayerBuff(i, "HARMFUL"))
aura = DPSToolTextLeft1:GetText()
DPSTool:Hide()
if not aura then break end
_, _, debuffDispelType = UnitDebuff("player", i);
if debuffDispelType and DPSMateAbility[aura] then
DPSMateAbility[aura][2] = debuffDispelType
end
end
end
end
DPSMate.Parser.CHAT_MSG_COMBAT_HOSTILE_DEATH = function(arg1)
this:CombatHostileDeaths(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_FRIENDLY_DEATH = function(arg1)
this:CombatFriendlyDeath(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_BREAK_AURA = function(arg1)
this:SpellBreakAura(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_AURA_GONE_PARTY = function(arg1)
this:SpellAuraGoneParty(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_AURA_GONE_OTHER = function(arg1)
this:SpellAuraGoneOther(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_AURA_GONE_SELF = function(arg1)
this:SpellAuraGoneSelf(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS = function(arg1)
this:SpellPeriodicFriendlyPlayerBuffs(arg1)
this:SpellPeriodicFriendlyPlayerBuffsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PARTY_BUFF = function(arg1)
this:SpellHostilePlayerBuff(arg1)
this:SpellHostilePlayerBuffDispels(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS = function(arg1)
this:SpellPeriodicFriendlyPlayerBuffs(arg1)
this:SpellPeriodicFriendlyPlayerBuffsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF = function(arg1)
this:SpellHostilePlayerBuff(arg1)
this:SpellHostilePlayerBuffDispels(arg1)
this:HostilePlayerSpellDamageInterrupts(arg1)
this:SpellPeriodicFriendlyPlayerBuffsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS = function(arg1)
this:SpellPeriodicFriendlyPlayerBuffs(arg1)
this:SpellPeriodicFriendlyPlayerBuffsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF = function(arg1)
this:SpellHostilePlayerBuff(arg1)
this:SpellHostilePlayerBuffDispels(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS = function(arg1)
this:SpellPeriodicSelfBuff(arg1)
this:SpellPeriodicSelfBuffAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_SELF_BUFF = function(arg1)
this:SpellSelfBuff(arg1)
this:SpellSelfBuffDispels(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE = function(arg1)
this:SpellPeriodicDamageTaken(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE = function(arg1)
this:CreatureVsCreatureSpellDamage(arg1)
this:CreatureVsCreatureSpellDamageAbsorb(arg1)
this:CreatureVsCreatureSpellDamageInterrupts(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES = function(arg1)
this:CreatureVsCreatureMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS = function(arg1)
this:CreatureVsCreatureHits(arg1)
this:CreatureVsCreatureHitsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE = function(arg1)
this:CreatureVsCreatureSpellDamage(arg1)
this:CreatureVsCreatureSpellDamageAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE = function(arg1)
this:SpellPeriodicDamageTaken(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES = function(arg1)
this:CreatureVsCreatureMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS = function(arg1)
this:CreatureVsCreatureHits(arg1)
this:CreatureVsCreatureHitsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE = function(arg1)
this:PeriodicSelfDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE = function(arg1)
this:CreatureVsSelfSpellDamage(arg1)
this:CreatureVsSelfSpellDamageAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES = function(arg1)
this:CreatureVsSelfMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS = function(arg1)
this:CreatureVsSelfHits(arg1)
this:CreatureVsSelfHitsAbsorb(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS = function(arg1)
this:SpellDamageShieldsOnOthers(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF = function(arg1)
this:SpellDamageShieldsOnSelf(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES = function(arg1)
this:FriendlyPlayerMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES = function(arg1)
this:FriendlyPlayerMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS = function(arg1)
this:FriendlyPlayerHits(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS = function(arg1)
this:FriendlyPlayerHits(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE = function(arg1)
this:FriendlyPlayerDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PARTY_DAMAGE = function(arg1)
this:FriendlyPlayerDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_PARTY_MISSES = function(arg1)
this:FriendlyPlayerMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_PARTY_HITS = function(arg1)
this:FriendlyPlayerHits(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE = function(arg1)
this:PeriodicDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE = function(arg1)
this:FriendlyPlayerDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE = function(arg1)
this:PeriodicDamage(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_SELF_DAMAGE = function(arg1)
this:SelfSpellDMG(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_SELF_MISSES = function(arg1)
this:SelfMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_SELF_HITS = function(arg1)
this:SelfHits(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_PET_HITS = function(arg1)
this:PetHits(arg1)
end
DPSMate.Parser.CHAT_MSG_COMBAT_PET_MISSES = function(arg1)
this:PetMisses(arg1)
end
DPSMate.Parser.CHAT_MSG_SPELL_PET_DAMAGE = function(arg1)
this:PetSpellDamage(arg1)
end
DPSMate.Parser:SetScript("OnEvent", function()
if this[event] then
local msg = arg1
if msg and strfind(event, "CHAT_MSG_", 1, true) and not strfind(msg, " 's ", 1, true) and strfind(msg, "'s ", 1, true) then
msg = string.gsub(msg, "'s ", " 's ", 1)
end
this[event](msg)
end
end)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,301 @@
-- Global Variables
DPSMate.Modules.DPS = {}
DPSMate.Modules.DPS.Hist = "DMGDone"
DPSMate.Options.Options[1]["args"]["dps"] = {
order = 10,
type = 'toggle',
name = DPSMate.L["dps"],
desc = DPSMate.L["show"].." "..DPSMate.L["dps"]..".",
get = function() return DPSMateSettings["windows"][DPSMate.Options.Dewdrop:GetOpenedParent().Key]["options"][1]["dps"] end, -- Addons might conflicting here with dewdrop
set = function() DPSMate.Options:ToggleDrewDrop(1, "dps", DPSMate.Options.Dewdrop:GetOpenedParent()) end,
}
DPSMate.Modules.DPS.Events = {
"CHAT_MSG_COMBAT_SELF_HITS",
"CHAT_MSG_COMBAT_SELF_MISSES",
"CHAT_MSG_SPELL_SELF_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_HITS",
"CHAT_MSG_SPELL_PARTY_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_MISSES",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES",
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",
-- Pet Damage
"CHAT_MSG_COMBAT_PET_HITS",
"CHAT_MSG_COMBAT_PET_MISSES",
--"CHAT_MSG_SPELL_PET_BUFF",
"CHAT_MSG_SPELL_PET_DAMAGE",
}
-- Register the moodule
DPSMate:Register("dps", DPSMate.Modules.DPS, DPSMate.L["dps"])
local tinsert = table.insert
local strformat = string.format
function DPSMate.Modules.DPS:GetSortedTable(arr,k)
local b, a, total = {}, {}, 0
if arr then
local petsByOwner = DPSMateSettings["mergepets"] and DPSMate:GetPetsByOwner(arr) or {}
local processedOwners = {}
for cat, val in pairs(arr) do
local name = DPSMate:GetUserById(cat)
if not name or not DPSMateUser[name] then
-- skip unknown users
elseif (not DPSMateUser[name][4] or (DPSMateUser[name][4] and not DPSMateSettings["mergepets"])) then
if DPSMate:ApplyFilter(k, name) then
local CV = val["i"]
if DPSMateSettings["mergepets"] and petsByOwner[cat] then
processedOwners[cat] = true
for _, petCat in pairs(petsByOwner[cat]) do
if arr[petCat] then
CV = CV + arr[petCat]["i"]
end
end
end
local i = 1
while true do
if (not b[i]) then
tinsert(b, i, CV)
tinsert(a, i, name)
break
else
if b[i] < CV then
tinsert(b, i, CV)
tinsert(a, i, name)
break
end
end
i=i+1
end
total = total + CV
end
end
end
-- Handle owners with no personal damage but with pets that have damage
if DPSMateSettings["mergepets"] then
for oid, petList in pairs(petsByOwner) do
if not processedOwners[oid] and not arr[oid] then
local name = DPSMate:GetUserById(oid)
if name and DPSMateUser[name] and not DPSMateUser[name][4] and DPSMate:ApplyFilter(k, name) then
local CV = 0
for _, petCat in pairs(petList) do
if arr[petCat] then
CV = CV + arr[petCat]["i"]
end
end
if CV > 0 then
local i = 1
while true do
if (not b[i]) then
tinsert(b, i, CV)
tinsert(a, i, name)
break
else
if b[i] < CV then
tinsert(b, i, CV)
tinsert(a, i, name)
break
end
end
i=i+1
end
total = total + CV
end
end
end
end
end
end
return b, total, a
end
function DPSMate.Modules.DPS:EvalTable(user, k, cbt)
if not user then return end
local a, u, p, d, total, pet = {}, {}, {}, {}, 0, false
local arr, cbet = DPSMate:GetMode(k)
cbt = cbt or cbet
if not cbt or cbt <= 0 then cbt = 1 end
u = {user[1]}
if DPSMateSettings["mergepets"] then
local petsByOwner = DPSMate:GetPetsByOwner(arr)
if petsByOwner[user[1]] then
for _, petCat in pairs(petsByOwner[user[1]]) do
tinsert(u, petCat)
end
end
end
if not arr[user[1]] and getn(u) <= 1 then return end
for _, v in pairs(u) do
if arr[v] then
for cat, val in pairs(arr[v]) do
if (type(val) == "table" and cat~="i") then
if val[13] and val[13]~=0 and cat~="" then
local vname = DPSMate:GetUserById(v)
if vname and DPSMateUser[vname] and DPSMateUser[vname][4] then pet=vname; else pet=false; end
local i = 1
while true do
if (not d[i]) then
tinsert(a, i, cat)
tinsert(d, i, {val[13]/cbt, pet})
break
else
if (d[i][1] < val[13]/cbt) then
tinsert(a, i, cat)
tinsert(d, i, {val[13]/cbt, pet})
break
end
end
i = i + 1
end
end
end
end
total=total+(arr[v]["i"] or 0)
end
end
return a, total/(cbt or 1), d
end
function DPSMate.Modules.DPS:GetSettingValues(arr, cbt, k, ecbt)
local pt = ""
local name, value, perc, sortedTable, total, a, p, strt = {}, {}, {}, {}, 0, 0, "", {[1]="",[2]=""}
if DPSMateSettings["windows"][k]["numberformat"] == 2 or DPSMateSettings["windows"][k]["numberformat"] == 4 then p = "K"; pt = "K" end
sortedTable, total, a = DPSMate.Modules.DPS:GetSortedTable(arr,k)
local validCbt = cbt and cbt > 0.001
for cat, val in pairs(sortedTable) do
local dmg, tot, sort, dmgr, totr, sortr = DPSMate:FormatNumbers(val, total, sortedTable[1], k)
if dmgr==0 then break end; if totr <= 10000 then pt = "" end; if dmgr<=10000 then p = "" end
local str = {[1]="",[2]="",[3]="",[4]=""}
local pname = a[cat]
if DPSMateSettings["columnsdps"][1] then str[1] = "("..DPSMate:Commas(dmg, k)..p..")"; strt[1] = "("..DPSMate:Commas(tot, k)..pt..")" end
if DPSMateSettings["columnsdps"][2] and validCbt then str[2] = " "..strformat("%.1f", (dmg/cbt))..p; strt[2] = " "..strformat("%.1f", (tot/cbt))..pt end
if DPSMateSettings["columnsdps"][3] then str[3] = " ("..strformat("%.1f", 100*dmgr/totr).."%)" end
if DPSMateSettings["columnsdps"][4] then local ev = ecbt[pname] or cbt; if ev and ev > 0.001 then str[4] = " ("..strformat("%.1f", (dmg/ev))..p..")" end end
tinsert(name, a[cat])
tinsert(value, str[1]..str[2]..str[4]..str[3])
tinsert(perc, 100*(dmgr/sortr))
end
return name, value, perc, strt
end
function DPSMate.Modules.DPS:ShowTooltip(user,k)
if DPSMateSettings["informativetooltips"] then
if not DPSMateUser[user] then return end
local a,b,c = DPSMate.Modules.DPS:EvalTable(DPSMateUser[user], k)
local db, cbt = DPSMate:GetModeByArr(DPSMateEDT, k, "EDTaken")
local i, p = 1, 0
local pet = 0
local edtaken, edtakenPet = {}, {}
-- Find all pet IDs for this owner
local ownerId = DPSMateUser[user][1]
local petIds = {}
local petNames = {}
for pname, pdata in pairs(DPSMateUser) do
if pdata[4] and pdata[6] == ownerId then
tinsert(petIds, pdata[1])
tinsert(petNames, pname)
end
end
-- Getting the value of the pet
while a and a[i] do
if c[i][2] then
pet = pet + c[i][1]
end
i = i + 1
end
-- Getting edt values
for cat, val in pairs(db) do
if val[ownerId] and val[ownerId]["i"] then
if val[ownerId]["i"]>0 then
i = 1
while true do
if (not edtaken[i]) then
tinsert(edtaken, i, {cat, val[ownerId]["i"]})
break
else
if (edtaken[i][2] < val[ownerId]["i"]) then
tinsert(edtaken, i, {cat, val[ownerId]["i"]})
break
end
end
i = i + 1
end
end
end
-- Aggregate EDT from all pets for this enemy
local petTotal = 0
for _, pid in pairs(petIds) do
if val[pid] and val[pid]["i"] > 0 then
petTotal = petTotal + val[pid]["i"]
end
end
if petTotal > 0 then
i = 1
while true do
if (not edtakenPet[i]) then
tinsert(edtakenPet, i, {cat, petTotal})
break
else
if (edtakenPet[i][2] < petTotal) then
tinsert(edtakenPet, i, {cat, petTotal})
break
end
end
i = i + 1
end
end
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttdamage"]..DPSMate.L["ttabilities"])
for i=1, DPSMateSettings["subviewrows"] do
if not a[i] then break end
if not c[i][2] then
local div = (b-pet) ~= 0 and (b-pet) or 1
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetAbilityById(a[i]),strformat("%.2f", c[i][1]).." ("..strformat("%.2f", 100*c[i][1]/div).."%)",1,1,1,1,1,1)
end
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttattacked"])
for i=1, DPSMateSettings["subviewrows"] do
if not edtaken[i] then break end
local ediv = (b-pet) ~= 0 and (b-pet) or 1
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetUserById(edtaken[i][1]), strformat("%.2f", edtaken[i][2]/cbt).." ("..strformat("%.2f", (100*edtaken[i][2]/cbt)/ediv).."%)", 1,1,1,1,1,1)
end
if pet~=0 and getn(petIds) > 0 then
local petDisplay = table.concat(petNames, ", ")
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(DPSMate.L["ttpet2"],petDisplay.."<"..user.."> ("..strformat("%.2f", 100*pet/b).."%)",1,0.82,0,1,1,1)
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttpet"]..DPSMate.L["ttdamage"]..DPSMate.L["ttabilities"])
i, p = 1,1
while DPSMateSettings["subviewrows"]>=p do
if not a[i] then break end
if c[i][2] then
GameTooltip:AddDoubleLine(p..". "..DPSMate:GetAbilityById(a[i]),strformat("%.2f", c[i][1]).." ("..strformat("%.2f", 100*c[i][1]/pet).."%)",1,1,1,1,1,1)
p = p + 1
end
i = i + 1
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttpet"]..DPSMate.L["ttattacked"])
for i=1, DPSMateSettings["subviewrows"] do
if not edtakenPet[i] then break end
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetUserById(edtakenPet[i][1]), strformat("%.2f", edtakenPet[i][2]/cbt).." ("..strformat("%.2f", (100*edtakenPet[i][2]/cbt)/pet).."%)", 1,1,1,1,1,1)
end
end
end
end
function DPSMate.Modules.DPS:OpenDetails(obj, key, bool)
if bool then
DPSMate.Modules.DetailsDamage:UpdateCompare(obj, key, bool)
else
DPSMate.Modules.DetailsDamage:UpdateDetails(obj, key)
end
end
function DPSMate.Modules.DPS:OpenTotalDetails(obj, key)
DPSMate.Modules.DetailsDamageTotal:UpdateDetails(obj, key)
end
@@ -0,0 +1,298 @@
-- Global Variables
DPSMate.Modules.Damage = {}
DPSMate.Modules.Damage.Hist = "DMGDone"
DPSMate.Options.Options[1]["args"]["damage"] = {
order = 20,
type = 'toggle',
name = DPSMate.L["damage"],
desc = DPSMate.L["show"].." "..DPSMate.L["damage"]..".",
get = function() return DPSMateSettings["windows"][DPSMate.Options.Dewdrop:GetOpenedParent().Key]["options"][1]["damage"] end,
set = function() DPSMate.Options:ToggleDrewDrop(1, "damage", DPSMate.Options.Dewdrop:GetOpenedParent()) end,
}
DPSMate.Modules.Damage.Events = {
"CHAT_MSG_COMBAT_SELF_HITS",
"CHAT_MSG_COMBAT_SELF_MISSES",
"CHAT_MSG_SPELL_SELF_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_HITS",
"CHAT_MSG_SPELL_PARTY_DAMAGE",
"CHAT_MSG_COMBAT_PARTY_MISSES",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS",
"CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES",
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",
-- Pet Damage
"CHAT_MSG_COMBAT_PET_HITS",
"CHAT_MSG_COMBAT_PET_MISSES",
--"CHAT_MSG_SPELL_PET_BUFF",
"CHAT_MSG_SPELL_PET_DAMAGE",
}
-- Register the moodule
DPSMate:Register("damage", DPSMate.Modules.Damage, DPSMate.L["damage"])
local tinsert = table.insert
local strformat = string.format
local pairs = pairs
function DPSMate.Modules.Damage:GetSortedTable(arr, k)
local b, a, total, CV, i, name = {}, {}, 0
local petsByOwner = DPSMateSettings["mergepets"] and DPSMate:GetPetsByOwner(arr) or {}
local processedOwners = {}
for cat, val in pairs(arr) do
name = DPSMate:GetUserById(cat)
if not name or not DPSMateUser[name] then
-- skip unknown users
elseif (not DPSMateUser[name][4] or (DPSMateUser[name][4] and not DPSMateSettings["mergepets"])) then
if DPSMate:ApplyFilter(k, name) then
CV = val["i"] or 0
if DPSMateSettings["mergepets"] and petsByOwner[cat] then
processedOwners[cat] = true
for _, petCat in pairs(petsByOwner[cat]) do
if arr[petCat] then
CV = CV + (arr[petCat]["i"] or 0)
end
end
end
i = 1
while true do
if (not b[i]) then
tinsert(b, i, CV)
tinsert(a, i, name)
break
else
if b[i] < CV then
tinsert(b, i, CV)
tinsert(a, i, name)
break
end
end
i=i+1
end
total = total + CV
end
end
end
-- Handle owners with no personal damage but with pets that have damage
if DPSMateSettings["mergepets"] then
for oid, petList in pairs(petsByOwner) do
if not processedOwners[oid] and not arr[oid] then
name = DPSMate:GetUserById(oid)
if name and DPSMateUser[name] and not DPSMateUser[name][4] and DPSMate:ApplyFilter(k, name) then
CV = 0
for _, petCat in pairs(petList) do
if arr[petCat] then
CV = CV + (arr[petCat]["i"] or 0)
end
end
if CV > 0 then
i = 1
while true do
if (not b[i]) then
tinsert(b, i, CV)
tinsert(a, i, name)
break
else
if b[i] < CV then
tinsert(b, i, CV)
tinsert(a, i, name)
break
end
end
i=i+1
end
total = total + CV
end
end
end
end
end
return b, total, a
end
function DPSMate.Modules.Damage:EvalTable(user, k)
if not user then return end
local a, u, p, d, total, pet = {}, {}, {}, {}, 0, false
local arr = DPSMate:GetMode(k)
u = {user[1]}
if DPSMateSettings["mergepets"] then
local petsByOwner = DPSMate:GetPetsByOwner(arr)
if petsByOwner[user[1]] then
for _, petCat in pairs(petsByOwner[user[1]]) do
tinsert(u, petCat)
end
end
end
if not arr[user[1]] and getn(u) <= 1 then return end
for _, v in pairs(u) do
if arr[v] then
for cat, val in pairs(arr[v]) do
if (type(val) == "table" and cat~="i") then
if val[13] and val[13]~=0 and cat~="" then
local vname = DPSMate:GetUserById(v)
if vname and DPSMateUser[vname] and DPSMateUser[vname][4] then pet=vname; else pet=false; end
local i = 1
while true do
if (not d[i]) then
tinsert(a, i, cat)
tinsert(d, i, {val[13], pet})
break
else
if (d[i][1] < val[13]) then
tinsert(a, i, cat)
tinsert(d, i, {val[13], pet})
break
end
end
i = i + 1
end
end
end
end
total=total+(arr[v]["i"] or 0)
end
end
return a, total, d
end
function DPSMate.Modules.Damage:GetSettingValues(arr, cbt, k,ecbt)
local pt = ""
local name, value, perc, sortedTable, total, a, p, strt = {}, {}, {}, {}, 0, 0, "", {[1]="",[2]=""}
if DPSMateSettings["windows"][k]["numberformat"] == 2 or DPSMateSettings["windows"][k]["numberformat"] == 4 then p = "K"; pt = "K" end
sortedTable, total, a = DPSMate.Modules.Damage:GetSortedTable(arr, k)
local validCbt = cbt and cbt > 0.001
for cat, val in pairs(sortedTable) do
local dmg, tot, sort, dmgr, totr, sortr = DPSMate:FormatNumbers(val, total, sortedTable[1], k)
if dmgr==0 then break end; if totr <= 10000 then pt = "" end; if dmgr<=10000 then p = "" end
local str = {[1]="",[2]="",[3]="",[4]=""}
local pname = a[cat]
if DPSMateSettings["columnsdmg"][1] then str[1] = " "..DPSMate:Commas(dmg, k)..p; strt[2] = DPSMate:Commas(tot, k)..pt end
if DPSMateSettings["columnsdmg"][2] and validCbt then str[2] = "("..strformat("%.1f", (dmg/cbt))..p..")"; strt[1] = "("..strformat("%.1f", (tot/cbt))..pt..") " end
if DPSMateSettings["columnsdmg"][3] then str[3] = " ("..strformat("%.1f", 100*dmgr/totr).."%)" end
if DPSMateSettings["columnsdmg"][4] then local ev = (type(ecbt)=="table" and ecbt[pname]) or cbt; if ev and ev > 0.001 then str[4] = " ("..strformat("%.1f", dmg/ev)..p..")" end end
tinsert(name, a[cat])
tinsert(value, str[2]..str[1]..str[4]..str[3])
tinsert(perc, 100*(dmgr/sortr))
end
return name, value, perc, strt
end
function DPSMate.Modules.Damage:ShowTooltip(user,k)
if DPSMateSettings["informativetooltips"] then
if not DPSMateUser[user] then return end
local a,b,c = DPSMate.Modules.Damage:EvalTable(DPSMateUser[user], k)
local db = DPSMate:GetModeByArr(DPSMateEDT, k, "EDTaken")
local i, p = 1, 0
local pet = 0
local edtaken, edtakenPet = {}, {}
-- Find all pet IDs for this owner
local ownerId = DPSMateUser[user][1]
local petIds = {}
local petNames = {}
for pname, pdata in pairs(DPSMateUser) do
if pdata[4] and pdata[6] == ownerId then
tinsert(petIds, pdata[1])
tinsert(petNames, pname)
end
end
-- Getting the value of the pet
while a and a[i] do
if c[i][2] then
pet = pet + c[i][1]
end
i = i + 1
end
-- Getting edt values
for cat, val in pairs(db) do
if val[ownerId] then
if val[ownerId]["i"] and val[ownerId]["i"]>0 then
i = 1
while true do
if (not edtaken[i]) then
tinsert(edtaken, i, {cat, val[ownerId]["i"]})
break
else
if (edtaken[i][2] < val[ownerId]["i"]) then
tinsert(edtaken, i, {cat, val[ownerId]["i"]})
break
end
end
i = i + 1
end
end
end
-- Aggregate EDT from all pets for this enemy
local petTotal = 0
for _, pid in pairs(petIds) do
if val[pid] and (val[pid]["i"] or 0) > 0 then
petTotal = petTotal + (val[pid]["i"] or 0)
end
end
if petTotal > 0 then
i = 1
while true do
if (not edtakenPet[i]) then
tinsert(edtakenPet, i, {cat, petTotal})
break
else
if (edtakenPet[i][2] < petTotal) then
tinsert(edtakenPet, i, {cat, petTotal})
break
end
end
i = i + 1
end
end
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttdamage"]..DPSMate.L["ttabilities"])
for i=1, DPSMateSettings["subviewrows"] do
if not a[i] then break end
if not c[i][2] then
local div = (b-pet) ~= 0 and (b-pet) or 1
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetAbilityById(a[i]),c[i][1].." ("..strformat("%.2f", 100*c[i][1]/div).."%)",1,1,1,1,1,1)
end
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttattacked"])
for i=1, DPSMateSettings["subviewrows"] do
if not edtaken[i] then break end
local ediv = (b-pet) ~= 0 and (b-pet) or 1
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetUserById(edtaken[i][1]), edtaken[i][2].." ("..strformat("%.2f", 100*edtaken[i][2]/ediv).."%)", 1,1,1,1,1,1)
end
if pet~=0 and getn(petIds) > 0 then
local petDisplay = table.concat(petNames, ", ")
GameTooltip:AddLine(" ")
GameTooltip:AddDoubleLine(DPSMate.L["ttpet2"],petDisplay.."<"..user.."> ("..strformat("%.2f", 100*pet/b).."%)",1,0.82,0,1,1,1)
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttpet"]..DPSMate.L["ttdamage"]..DPSMate.L["ttabilities"])
i, p = 1,1
while DPSMateSettings["subviewrows"]>=p do
if not a[i] then break end
if c[i][2] then
GameTooltip:AddDoubleLine(p..". "..DPSMate:GetAbilityById(a[i]),c[i][1].." ("..strformat("%.2f", 100*c[i][1]/pet).."%)",1,1,1,1,1,1)
p = p + 1
end
i = i + 1
end
GameTooltip:AddLine(DPSMate.L["tttop"]..DPSMateSettings["subviewrows"]..DPSMate.L["ttpet"]..DPSMate.L["ttattacked"])
for i=1, DPSMateSettings["subviewrows"] do
if not edtakenPet[i] then break end
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetUserById(edtakenPet[i][1]), edtakenPet[i][2].." ("..strformat("%.2f", 100*edtakenPet[i][2]/pet).."%)", 1,1,1,1,1,1)
end
end
end
end
function DPSMate.Modules.Damage:OpenDetails(obj, key, bool)
if bool then
DPSMate.Modules.DetailsDamage:UpdateCompare(obj, key, bool)
else
DPSMate.Modules.DetailsDamage:UpdateDetails(obj, key)
end
end
function DPSMate.Modules.Damage:OpenTotalDetails(obj, key)
DPSMate.Modules.DetailsDamageTotal:UpdateDetails(obj, key)
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,494 @@
DPSMate.Modules.DetailsDamageTotal = {}
local g, g2 = nil,nil
local curKey = 1
local db, cbt = {}, 0
local buttons = {}
local ColorTable={}
local _G = getglobal
local tinsert = table.insert
local tremove = table.remove
local strformat = string.format
local toggle = false
local totSumTable = {}
local totMax = 0
local totTime = 0
function DPSMate.Modules.DetailsDamageTotal:UpdateDetails(obj, key)
curKey = key
db, cbt = DPSMate:GetMode(key)
buttons = {}
ColorTable={
{0.95,0.90,0.5},
{0.0,0.9,0.0},
{0.0,0.0,1.0},
{1.0,1.0,0.0},
{1.0,0.0,1.0},
{0.0,1.0,1.0},
{1.0,1.0,1.0},
{0.5,0.0,0.0},
{0.0,0.5,0.0},
{0.0,0.0,0.5},
{0.5,0.5,0.0},
{0.5,0.0,0.5},
{0.0,0.5,0.5},
{0.5,0.5,0.5},
{0.75,0.25,0.25},
{0.25,0.75,0.25},
{0.25,0.25,0.75},
{0.75,0.75,0.25},
{0.75,0.25,0.75},
{0.25,0.75,0.75},
{1.0,0.5,0.0},
{0.0,0.5,1.0},
{1.0,0.0,0.5},
{0.5,1.0,0.0},
{0.5,0.0,1.0},
{0.0,1.0,0.5},
{0.0,0.25,0.5},
{0.25,0,0.5},
{0.5,0.25,0.0},
{0.5,0.0,0.25},
{0.5,0.75,0.0},
{0.5,0.0,0.75},
{0.0,0.75,0.5},
{0.75,0.0,0.5},
}
if not g then
g=DPSMate.Options.graph:CreateGraphLine("DMGDTLineGraph",DPSMate_Details_DamageTotal_DiagramLine,"CENTER","CENTER",0,0,740,220)
g2=DPSMate.Options.graph:CreateStackedGraph("DMGDTStackedGraph",DPSMate_Details_DamageTotal_DiagramLine,"CENTER","CENTER",0,0,850,220)
g2:SetGridColor({0.5,0.5,0.5,0.5})
g2:SetAxisDrawing(true,true)
g2:SetAxisColor({1.0,1.0,1.0,1.0})
g2:SetAutoScale(true)
g2:SetYLabels(true, false)
g2:SetXLabels(true)
g2:Hide()
DPSMate.Modules.DetailsDamageTotal:CreateGraphTable()
end
DPSMate_Details_DamageTotal_PlayerList_CB:SetChecked(false)
DPSMate_Details_DamageTotal_PlayerList_CB.act = false
DPSMate_Details_DamageTotal_Title:SetText(DPSMate.L["dmgdonesum"])
self:LoadTable()
self:LoadLegendButtons()
if toggle then
self:UpdateStackedGraph()
else
self:UpdateLineGraph()
end
DPSMate_Details_DamageTotal:Show()
DPSMate_Details_DamageTotal:SetScale((DPSMateSettings["targetscale"] or 0.58)/UIParent:GetScale())
end
function DPSMate.Modules.DetailsDamageTotal:UpdateLineGraph()
g:ResetData()
g:SetGridColor({0.5,0.5,0.5,0.5})
g:SetAxisDrawing(true,true)
g:SetAxisColor({1.0,1.0,1.0,1.0})
g:SetAutoScale(true)
g:SetYLabels(true, false)
g:SetXLabels(true)
g2:Hide()
DPSMate_Details_DamageTotal_DiagramLine:SetWidth(770)
DPSMate_Details_DamageTotal_DiagramLegend:Show()
g:Show()
toggle=false
self:AddTotalDataSeries()
local Max = totMax
for cat, val in pairs(buttons) do
g:AddDataSeries(val[3], {val[1], {}}, {})
local temp = DPSMate:GetMaxValue(val[3], 2)
if temp>Max then
Max = temp
end
end
g:SetGridSpacing(totTime/10,Max/7)
end
function DPSMate.Modules.DetailsDamageTotal:UpdateStackedGraph()
g:Hide()
DPSMate_Details_DamageTotal_DiagramLine:SetWidth(870)
DPSMate_Details_DamageTotal_DiagramLegend:Hide()
local Data1 = {}
local label = {}
local maxX, maxY = 0,0
local p = {}
for cat, val in db do
local temp = {}
local user =DPSMate:GetUserById(cat)
if DPSMate:ApplyFilter(curKey, user) then
for ca, va in val do
if ca~="i" then
for c,v in va["i"] do
local i = 1
while true do
if not temp[i] then
tinsert(temp, i, {c,v})
break
elseif c<=temp[i][1] then
tinsert(temp, i, {c,v})
break
end
i=i+1
end
if p[c] then
p[c] = p[c] + v
else
p[c] = v
end
if maxX == 0 or maxX<c then
maxX = c
end
end
end
end
tinsert(label, 1, user)
tinsert(Data1, 1, temp)
end
end
for cat, val in p do
if maxY<val then
maxY = val
end
end
g2:ResetData()
g2:SetGridSpacing(maxX/7,(maxY/2)/14)
g2:AddDataSeries(Data1,{1.0,0.0,0.0,0.8}, {}, label)
g2:Show()
toggle=true
end
function DPSMate.Modules.DetailsDamageTotal:ToggleMode()
if toggle then
self:UpdateLineGraph()
toggle=false
else
self:UpdateStackedGraph()
toggle=true
end
end
function DPSMate.Modules.DetailsDamageTotal:GetSummarizedTable(arr)
return DPSMate.Sync:GetSummarizedTable(arr)
end
function DPSMate.Modules.DetailsDamageTotal:CreateGraphTable()
local lines = {}
for i=1, 8 do
-- Horizontal
lines[i] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 10, 270-i*30, 860, 270-i*30, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[i]:Show()
end
-- Vertical
lines[9] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 40, 260, 40, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[9]:Show()
lines[10] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 170, 260, 170, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[10]:Show()
lines[11] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 540, 260, 540, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[11]:Show()
lines[12] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 600, 260, 600, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[12]:Show()
lines[13] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 660, 260, 660, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[13]:Show()
lines[13] = DPSMate.Options.graph:DrawLine(DPSMate_Details_DamageTotal_PlayerList, 740, 260, 740, 10, 20, {0.5,0.5,0.5,0.5}, "BACKGROUND")
lines[13]:Show()
end
function DPSMate.Modules.DetailsDamageTotal:AddTotalDataSeries()
local sumTable, newArr = {[0]=0}, {}
local temp = {}
for cat, val in db do
local user = DPSMate:GetUserById(cat)
if DPSMate:ApplyFilter(curKey, user) then
temp[user] = true
for ca, va in val do
if ca~="i" and va["i"] then
for c,v in va["i"] do
if sumTable[c] then
sumTable[c] = sumTable[c] + v
else
sumTable[c] = v
end
end
end
end
end
end
local tl = DPSMate:TableLength(temp)
tl = ceil(tl-0.3*tl)
for cat, val in sumTable do
local i=1
while true do
if (not newArr[i]) then
tinsert(newArr, i, {cat, val/tl})
break
end
if cat<newArr[i][1] then
tinsert(newArr, i, {cat, val/tl})
break
end
i=i+1
end
end
totSumTable = self:GetSummarizedTable(newArr)
totMax = DPSMate:GetMaxValue(totSumTable, 2)
totTime = DPSMate:GetMaxValue(totSumTable, 1)
g:SetXAxis(0,totTime)
g:SetYAxis(0,totMax)
g:SetGridSpacing(totTime/10,totMax/7)
g:AddDataSeries(totSumTable,{{1.0,0.0,0.0,0.8}, {1.0,1.0,0.0,0.8}}, {})
end
function DPSMate.Modules.DetailsDamageTotal:GetTableValues()
local arr, total = {}, 0
for cat, val in db do
local name = DPSMate:GetUserById(cat)
if DPSMate:ApplyFilter(curKey, name) then
local crit, totCrit, miss, totMiss, time, last = 0, 0.000001, 0, 0.000001, 0, 0
for ca, va in val do
if ca~="i" then
totCrit=totCrit+va[1]+va[5]+va[9]+va[10]+va[11]+va[12]+va[14]
crit=crit+va[5]
totMiss=totMiss+va[1]+va[5]+va[9]+va[10]+va[11]+va[12]+va[14]
miss=miss+va[9]+va[10]+va[11]+va[12]
else
time = tonumber(strformat("%.2f", DPSMateCombatTime["effective"][curKey][name] or 0))
end
end
tinsert(arr, {name, (val["i"] or 0), crit, miss, time, totCrit, totMiss, cat})
total = total + (val["i"] or 0)
end
end
local newArr = {}
for cat, val in arr do
local i = 1
while true do
if (not newArr[i]) then
tinsert(newArr, i, val)
break
else
if newArr[i][2] < val[2] then
tinsert(newArr, i, val)
break
end
end
i=i+1
end
end
return newArr, total
end
function DPSMate.Modules.DetailsDamageTotal:CheckButtonCheckAll(obj)
if obj.act then
obj.act = false
for i=1, 30 do
local ob = _G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i)
if ob.user then
self:RemoveLinesButton(ob.user, ob)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i.."_CB"):SetChecked(obj.act)
end
end
else
obj.act = true
for i=1, 30 do
local ob = _G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i)
if ob.user then
self:RemoveLinesButton(ob.user, ob)
self:AddLinesButton(ob.user, ob)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i.."_CB"):SetChecked(obj.act)
end
end
end
end
function DPSMate.Modules.DetailsDamageTotal:SortLineTable(uid)
local user = DPSMate:GetUserById(uid)
local uentry = DPSMateUser[user]
if not uentry then return {} end
local newArr = {}
-- user
for cat, val in db[uentry[1]] do
if cat~="i" and val["i"] then
for c,v in val["i"] do
local i = 1
while true do
if not newArr[i] then
tinsert(newArr, i, {c,v})
break
elseif c<=newArr[i][1] then
tinsert(newArr, i, {c,v})
break
end
i = i+1
end
end
end
end
-- Pet
if DPSMateSettings["mergepets"] then
for pName, pEntry in pairs(DPSMateUser) do
if pEntry[4] and pEntry[6] == uentry[1] and pName ~= user and db[pEntry[1]] then
for cat, val in db[pEntry[1]] do
if cat~="i" and val["i"] then
for c,v in val["i"] do
local i = 1
while true do
if not newArr[i] then
tinsert(newArr, i, {c,v})
break
elseif c<=newArr[i][1] then
tinsert(newArr, i, {c,v})
break
end
i = i+1
end
end
end
end
end
end
end
return newArr
end
function DPSMate.Modules.DetailsDamageTotal:AddLinesButton(uid, obj)
local sumTable = self:SortLineTable(uid)
sumTable = self:GetSummarizedTable(sumTable)
local Max = DPSMate:GetMaxValue(sumTable, 2)
if Max > totMax then
g:SetGridSpacing(totTime/10,Max/7)
end
g:AddDataSeries(sumTable, {ColorTable[1], {}}, {})
tinsert(buttons, {ColorTable[1], uid, sumTable})
tremove(ColorTable, 1)
g2:Hide()
DPSMate_Details_DamageTotal_DiagramLine:SetWidth(770)
DPSMate_Details_DamageTotal_DiagramLegend:Show()
g:Show()
toggle=false
obj.act = true
self:LoadLegendButtons()
end
function DPSMate.Modules.DetailsDamageTotal:RemoveLinesButton(uid, obj)
obj.act = false
g:ResetData()
for cat, val in pairs(buttons) do
if val[2]==uid then
tinsert(ColorTable, 1, val[1])
tremove(buttons, cat)
break
end
end
local Max = totMax
g:AddDataSeries(totSumTable,{{1.0,0.0,0.0,0.8}, {1.0,1.0,0.0,0.8}}, {})
for cat, val in pairs(buttons) do
g:AddDataSeries(val[3], {val[1], {}}, {})
local temp = DPSMate:GetMaxValue(val[3], 2)
if temp>Max then
Max = temp
end
end
g:SetGridSpacing(totTime/10,Max/7)
g2:Hide()
DPSMate_Details_DamageTotal_DiagramLine:SetWidth(770)
DPSMate_Details_DamageTotal_DiagramLegend:Show()
g:Show()
toggle = false
self:LoadLegendButtons()
end
function DPSMate.Modules.DetailsDamageTotal:LoadLegendButtons()
for i=1, 30 do
_G("DPSMate_Details_DamageTotal_DiagramLegend_Child_C"..i):Hide()
end
for cat, val in buttons do
local name = DPSMate:GetUserById(val[2])
local font = _G("DPSMate_Details_DamageTotal_DiagramLegend_Child_C"..cat.."_Font")
font:SetText(name)
local uentry = DPSMateUser[name]
font:SetTextColor(DPSMate:GetClassColor(uentry and uentry[2]))
_G("DPSMate_Details_DamageTotal_DiagramLegend_Child_C"..cat.."_SwatchBg"):SetTexture(val[1][1],val[1][2],val[1][3],1)
_G("DPSMate_Details_DamageTotal_DiagramLegend_Child_C"..cat):Show()
end
end
function DPSMate.Modules.DetailsDamageTotal:RoundToH(val)
if val>100 then
return 100
end
return val
end
function DPSMate.Modules.DetailsDamageTotal:CompareVal(x,y)
if x>y then
return y
end
return x
end
function DPSMate.Modules.DetailsDamageTotal:LoadTable()
local arr, total = self:GetTableValues()
local i = 0
for i=1, 30 do
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i):Hide()
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i.."_CB"):SetChecked(false)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..i.."_CB").act = false
end
for cat, val in arr do
local uentry = DPSMateUser[val[1]]
if uentry and uentry[4] then
i=i+1
else
if (cat-i)>30 then break end
local r,g,b = DPSMate:GetClassColor(uentry and uentry[2])
_G("DPSMate_Details_DamageTotal_PlayerList_Child"):SetHeight((cat-i)*30)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_Name"):SetText(val[1])
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_Name"):SetTextColor(r,g,b)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_Amount"):SetText(val[2])
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_StatusBar"):SetValue(100*val[2]/arr[1][2])
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_StatusBar"):SetStatusBarColor(r,g,b, 1)
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_AmountPerc"):SetText(strformat("%.1f", 100*val[2]/total).."%")
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_Crit"):SetText(strformat("%.1f", 100*val[3]/val[6]).."%")
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_Miss"):SetText(strformat("%.1f", 100*val[4]/val[7]).."%")
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_DPS"):SetText(strformat("%.1f", val[2]/cbt))
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i).."_ActiveTime"):SetText(self:CompareVal(ceil(val[5]), ceil(cbt)).."s | "..strformat("%.1f", self:RoundToH(100*val[5]/cbt)).."%")
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i)).user = val[8]
_G("DPSMate_Details_DamageTotal_PlayerList_Child_R"..(cat-i)):Show()
end
end
end
function DPSMate.Modules.DetailsDamageTotal:ShowTooltip(user, obj)
local name = DPSMate:GetUserById(user)
if not DPSMateUser[name] then return end
local a,b,c = DPSMate.Modules.Damage:EvalTable(DPSMateUser[name], curKey)
local pet = ""
GameTooltip:SetOwner(obj, "TOPLEFT")
GameTooltip:AddLine(name.."'s "..strlower(DPSMate.L["damagedone"]), 1,1,1)
if not a or not b or not c then return end
for i=1, DPSMateSettings["subviewrows"] do
if not a[i] then break end
if c[i][2] then pet="("..c[i][2]..")" else pet="" end
GameTooltip:AddDoubleLine(i..". "..DPSMate:GetAbilityById(a[i])..pet,c[i][1].." ("..strformat("%.2f", 100*c[i][1]/b).."%)",1,1,1,1,1,1)
end
GameTooltip:Show()
end
@@ -0,0 +1,761 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\..\..\FrameXML\UI.xsd">
<Frame name="DPSMate_Details_DamageTotal_Template_LegendColumn" virtual="true" hidden="true">
<Size x="18" y="18" />
<Layers>
<Layer level="ARTWORK">
<FontString name="$parent_Font" inherits="GameFontNormalSmall" text="Average" justifyH="LEFT">
<Size x="60" y="18" />
<Anchors>
<Anchor point="LEFT" relativeTo="$parent" relativePoint="RIGHT">
<Offset x="5" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
</Layer>
<Layer level="BACKGROUND">
<Texture name="$parent_SwatchBg">
<Size x="16" y="16"/>
<Anchors>
<Anchor point="CENTER" />
</Anchors>
<Color r="1.0" g="0" b="0" a="1"/>
</Texture>
</Layer>
</Layers>
</Frame>
<Frame name="DPSMate_Details_DamageTotal_Template_Row" virtual="true" hidden="true">
<Size x="870" y="30" />
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parent_Hover" hidden="true">
<Size x="850" y="25"/>
<Anchors>
<Anchor point="CENTER">
<Offset x="0" y="-5" />
</Anchor>
</Anchors>
<Color r="0.95" g="0.9" b="0.5" a="0.5"/>
</Texture>
<FontString name="$parent_Name" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="130" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="45" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_Amount" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="175" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
<FontString name="$parent_AmountPerc" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="485" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
<FontString name="$parent_Crit" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="545" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
<FontString name="$parent_Miss" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="605" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
<FontString name="$parent_DPS" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="665" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
<FontString name="$parent_ActiveTime" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER">
<Size x="120" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="745" y="0" />
</Anchor>
</Anchors>
<Color r="1" g="1" b="1" />
</FontString>
</Layer>
</Layers>
<Scripts>
<OnEnter>
getglobal(this:GetName().."_Hover"):Show()
DPSMate.Modules.DetailsDamageTotal:ShowTooltip(this.user, this)
</OnEnter>
<OnLeave>
getglobal(this:GetName().."_Hover"):Hide()
GameTooltip:Hide()
</OnLeave>
</Scripts>
<Frames>
<CheckButton name="$parent_CB" inherits="UICheckButtonTemplate">
<Size x="26" y="26" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="10" y="-9" />
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
this:GetParent().act = false
</OnLoad>
<OnClick>
local uid = this:GetParent().user
local act = this:GetParent().act
if uid then
if act then
DPSMate.Modules.DetailsDamageTotal:RemoveLinesButton(uid, this:GetParent())
else
DPSMate.Modules.DetailsDamageTotal:AddLinesButton(uid, this:GetParent())
end
end
</OnClick>
</Scripts>
</CheckButton>
<StatusBar name="$parent_StatusBar">
<Size x="225" y="16" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="255" y="-13" />
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
this:SetMinMaxValues(1,100)
this:SetStatusBarTexture("Interface\\AddOns\\DPSMate\\images\\statusbar\\Healbot")
this:SetValue(100)
</OnLoad>
</Scripts>
</StatusBar>
</Frames>
</Frame>
<Frame name="DPSMate_Details_DamageTotal" parent="UIParent" movable="true" hidden="true">
<Size x="900" y="600" />
<Anchors>
<Anchor point="CENTER" />
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets left="6" right="6" top="6" bottom="6" />
<TileSize val="16" />
<EdgeSize val="16" />
<Color r="0.157" g="0.08" b="0.06" a="1" />
</Backdrop>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parent_Title" inherits="GameFontNormalHuge" justifyH="LEFT" justifyV="CENTER" text="Damage done for Shino">
<Size x="900" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="20" y="-10" />
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad>
this:SetClampedToScreen()
getglobal(this:GetName().."_Title"):SetFont(UNIT_NAME_FONT, 24)
</OnLoad>
<OnMouseDown>
this:StartMoving()
</OnMouseDown>
<OnMouseUp>
this:StopMovingOrSizing()
</OnMouseUp>
</Scripts>
<Frames>
<Button name="$parent_CloseButton">
<Size x="30" y="30" />
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parent" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(DPSMate.L["close"], nil, nil, nil, nil, 1)
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate_Details_DamageTotal:Hide()
PlaySound("igMainMenuOptionCheckBoxOff")
</OnClick>
</Scripts>
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
</Button>
<Button name="$parent_SwitchGraph">
<Size x="22" y="22" />
<Anchors>
<Anchor point="RIGHT" relativeTo="$parent_CloseButton" relativePoint="LEFT">
<Offset>
<AbsDimension x="-3" y="-3"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText(DPSMate.L["switchgraphsdesc"], nil, nil, nil, nil, 1)
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
DPSMate.Modules.DetailsDamageTotal:ToggleMode()
PlaySound("igMainMenuOptionCheckBoxOff")
</OnClick>
</Scripts>
<NormalTexture file="Interface\Buttons\UI-GroupLoot-Dice-Up"/>
<PushedTexture file="Interface\Buttons\UI-GroupLoot-Dice-Down"/>
<HighlightTexture file="Interface\Buttons\UI-GroupLoot-Dice-Highlight" alphaMode="ADD"/>
</Button>
<Frame name="$parent_DiagramLine">
<Size x="770" y="250" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="15" y="-65" />
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets left="6" right="6" top="6" bottom="6" />
<TileSize val="16" />
<EdgeSize val="16" />
<Color r="0.157" g="0.08" b="0.06" a="0.5" />
</Backdrop>
</Frame>
<ScrollFrame name="$parent_DiagramLegend">
<Size x="100" y="250" />
<Anchors>
<Anchor point="LEFT" relativeTo="$parent_DiagramLine" relativePoint="RIGHT" />
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets left="6" right="6" top="6" bottom="6" />
<TileSize val="16" />
<EdgeSize val="16" />
<Color r="0.157" g="0.08" b="0.06" a="0.5" />
</Backdrop>
<Scripts>
<OnLoad>
this:SetVerticalScroll(0)
</OnLoad>
<OnMouseWheel>
DPSMate.Options:OnVerticalScroll(this, arg1, 20, true)
</OnMouseWheel>
</Scripts>
<HitRectInsets left="0" right="0" top="5" bottom="5"/>
<ScrollChild>
<Frame name="$parent_Child">
<Size x="100" y="620" />
<Frames>
<Frame name="$parent_Total" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn" hidden="false">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT">
<Offset x="10" y="-8" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C1" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_Total" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C2" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C1" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C3" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C2" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C4" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C3" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C5" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C4" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C6" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C5" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C7" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C6" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C8" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C7" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C9" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C8" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C10" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C9" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C11" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C10" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C12" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C11" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C13" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C12" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C14" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C13" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C15" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C14" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C16" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C15" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C17" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C16" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C18" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C17" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C19" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C18" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C20" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C19" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C21" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C20" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C22" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C21" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C23" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C22" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C24" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C23" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C25" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C24" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C26" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C25" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C27" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C26" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C28" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C27" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C29" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C28" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_C30" inherits="DPSMate_Details_DamageTotal_Template_LegendColumn">
<Anchors>
<Anchor point="TOP" relativeTo="$parent_C29" relativePoint="BOTTOM">
<Offset x="0" y="-2" />
</Anchor>
</Anchors>
</Frame>
</Frames>
</Frame>
</ScrollChild>
</ScrollFrame>
<ScrollFrame name="$parent_PlayerList">
<Size x="870" y="270" />
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_DiagramLine" relativePoint="BOTTOMLEFT" />
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<BackgroundInsets left="6" right="6" top="6" bottom="6" />
<TileSize val="16" />
<EdgeSize val="16" />
<Color r="0.157" g="0.08" b="0.06" a="0.5" />
</Backdrop>
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parent_Name" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="Name">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="45" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_Amount" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="Amount">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="329" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_Crit" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="Crit">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="545" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_Miss" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="Miss">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="605" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_DPS" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="DPS">
<Size x="100" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="665" y="0" />
</Anchor>
</Anchors>
</FontString>
<FontString name="$parent_ActiveTime" inherits="GameFontNormal" justifyH="LEFT" justifyV="CENTER" text="Active Time">
<Size x="130" y="40" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="745" y="0" />
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad>
this:SetVerticalScroll(0)
</OnLoad>
<OnMouseWheel>
DPSMate.Options:OnVerticalScroll(this, arg1, 30, true)
</OnMouseWheel>
</Scripts>
<HitRectInsets left="0" right="0" top="35" bottom="5"/>
<ScrollChild>
<Frame name="$parent_Child">
<Size x="870" y="270" />
<Frames>
<Frame name="$parent_R1" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOP">
<Offset x="0" y="-25" />
</Anchor>
</Anchors>
</Frame>
<Frame name="$parent_R2" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R1" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R3" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R2" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R4" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R3" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R5" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R4" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R6" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R5" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R7" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R6" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R8" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R7" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R9" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R8" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R10" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R9" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R11" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R10" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R12" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R11" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R13" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R12" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R14" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R13" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R15" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R14" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R16" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R15" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R17" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R16" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R18" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R17" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R19" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R18" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R20" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R19" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R21" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R20" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R22" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R21" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R23" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R22" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R24" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R23" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R25" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R24" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R26" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R25" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R27" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R26" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R28" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R27" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R29" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R28" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
<Frame name="$parent_R30" inherits="DPSMate_Details_DamageTotal_Template_Row">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parent_R29" relativePoint="BOTTOMLEFT" />
</Anchors>
</Frame>
</Frames>
</Frame>
</ScrollChild>
<Frames>
<CheckButton name="$parent_CB" inherits="UICheckButtonTemplate">
<Size x="26" y="26" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="10" y="-4.5" />
</Anchor>
</Anchors>
<Scripts>
<OnClick>
DPSMate.Modules.DetailsDamageTotal:CheckButtonCheckAll(this)
</OnClick>
</Scripts>
</CheckButton>
</Frames>
</ScrollFrame>
</Frames>
</Frame>
</Ui>
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+97
View File
@@ -0,0 +1,97 @@
# DPSMate
A combat analysis addon for World of Warcraft 1.12 (Classic). Parses combat log messages in real-time to track ~40 metrics and presents them in customizable UI windows.
Originally by Shino &lt;Synced&gt; - Kronos. This fork targets TWoW/Kronos private servers.
## Installation
1. Download and extract into `Interface/AddOns/` so the folder is named `DPSMate` (not `DPSMate-master`).
2. Increase addon memory to at least 150 MB.
3. If upgrading from a previous version, delete the old SavedVariables while logged out:
- `WTF/Account/<ACCOUNT>/SavedVariables/DPSMate.lua` (account-wide settings)
- `WTF/Account/<ACCOUNT>/<SERVER>/<CHARACTER>/SavedVariables/DPSMate.lua` (per-character data)
4. Add these lines to `WTF/config.wtf` for full combat log range:
```
SET CombatLogRangeParty "150"
SET CombatLogRangePartyPet "150"
SET CombatLogRangeFriendlyPlayers "150"
SET CombatLogRangeFriendlyPlayersPets "150"
SET CombatLogRangeHostilePlayers "150"
SET CombatLogRangeHostilePlayersPets "150"
SET CombatLogRangeCreature "150"
```
5. Log in and `/reload` to load the addon.
## Slash Commands
| Command | Description |
|---------|-------------|
| `/dps` | Show help and available commands |
| `/dps config` | Open configuration window |
| `/dps lock` | Lock all frames |
| `/dps unlock` | Unlock all frames |
| `/dps show {name}` | Show a specific window |
| `/dps hide {name}` | Hide a specific window |
| `/dps showAll` | Show all windows |
| `/dps hideAll` | Hide all windows |
| `/dps reset` | Reset all saved data (players, abilities, history, metrics) |
| `/dps testmode` | Toggle test mode for UI testing |
## Features
### Tracking Modes (~40)
- Damage done / DPS / damage taken / DTPS
- Enemy damage done / taken
- Healing (total, effective, overhealing) / HPS / EHPS / OHPS
- Healing taken (total, effective, overhealing)
- Healing and absorbs combined
- Absorbs done / taken
- Threat / TPS (requires KLHThreatMeter)
- Deaths with full death recap
- Interrupts (including stuns and silences)
- Dispels / decurses / cure disease / cure poison / lift magic (done and received)
- CC breakers
- Friendly fire (done and taken)
- Auras (gained, lost, uptime)
- Buffs/debuffs and procs
- Casts
- Fails
### UI
- Multiple independent windows showing different modes simultaneously
- Resizable and movable frames
- Per-window customization of fonts, colors, textures, bar height, spacing, columns
- Configurable display refresh rate (0.016s to 2.0s)
- Up to 40 status bars per window
- Compare mode for player-vs-player analysis
- Detail views with graphs for every mode
### Data Management
- Configurable segment history (1-20 fight segments)
- Boss-only fight filtering
- Automatic stale player pruning between fights
- Raid data synchronization via addon channel
- Report function for chat output
## Supported Locales
enUS, deDE, frFR, ruRU, koKR, zhCN
## Optional Dependencies
- **KLHThreatMeter** -- enables threat/TPS tracking
## Troubleshooting
**SavedVariables getting too large?**
- Use `/dps reset` to wipe all accumulated data.
- Reduce the number of stored segments in General Options.
- History segments automatically strip per-tick graph data to save space.
**Missing group members?**
- Ensure combat log range settings are applied in `config.wtf` (see Installation step 4).
- Verify all raid members have the addon loaded for sync to work.
@@ -0,0 +1,474 @@
--[[
Name: Babble-Boss-2.3
Revision: $Rev: 20300 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Babble-Boss-2.2
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Boss-2.2
Description: A library to provide localizations for bosses.
Dependencies: AceLibrary, AceLocale-2.2
Rewritten a little and added some "bosses" by Shino
]]
local bosses = {
-- Costum bosses
["Firesworn"] = true,
["Avalanchion"] = true,
["The Windreaver"] = true,
["Baron Charr"] = true,
["Princess Tempestria"] = true,
["Grethok the Controller"] = true,
["Patchwerk"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Feugen"] = true,
["Stalagg"] = true,
["Thaddius"] = true,
["Anub'Rekhan"] = true,
["Grand Widow Faerlina"] = true,
["Maexxna"] = true,
["Instructor Razuvious"] = true,
--["Deathknight Understudy"] = true,
["Gothik the Harvester"] = true,
["Highlord Mograine"] = true,
["Thane Korth'azz"] = true,
["Lady Blaumeux"] = true,
["Sir Zeliek"] = true,
["The Four Horsemen"] = true,
["Noth the Plaguebringer"] = true,
["Heigan the Unclean"] = true,
["Loatheb"] = true,
["Sapphiron"] = true,
["Kel'Thuzad"] = true,
["Lord Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz the Corrupt"] = true,
["Razorgore the Untamed"] = true,
["Broodlord Lashlayer"] = true,
["Chromaggus"] = true,
["Ebonroc"] = true,
["Firemaw"] = true,
["Flamegor"] = true,
["Majordomo Executus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg the Incinerator"] = true,
["Garr"] = true,
["Sulfuron Harbinger"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Lord Kazzak"] = true,
["Ysondre"] = true,
["Emeriss"] = true,
["Taerar"] = true,
["Lethon"] = true,
["High Priestess Jeklik"] = true,
["High Priest Venoxis"] = true,
["High Priest Thekal"] = true,
["High Priestess Arlokk"] = true,
["High Priestess Mar'li"] = true,
["Jin'do the Hexxer"] = true,
["Bloodlord Mandokir"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Hakkar"] = true,
["Ayamiss the Hunter"] = true,
["Buru the Gorger"] = true,
["General Rajaxx"] = true,
["Lieutenant General Andorov"] = true,
["Moam"] = true,
["Ossirian the Unscarred"] = true,
["Lord Kri"] = true,
["Princess Yauj"] = true,
["Vem"] = true,
["The Bug Family"] = true,
["Eye of C'Thun"] = true,
["C'Thun"] = true,
["Fankriss the Unyielding"] = true,
["Princess Huhuran"] = true,
["Ouro"] = true,
["Battleguard Sartura"] = true,
["The Prophet Skeram"] = true,
["Emperor Vek'lor"] = true,
["Emperor Vek'nilash"] = true,
["The Twin Emperors"] = true,
["Viscidus"] = true,
["Alzzin the Wildshaper"] = true,
["Ambassador Flamelash"] = true,
["Anger'rel"] = true,
["Archivist Galford"] = true,
["Atal'alarion"] = true,
["Avatar of Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baroness Anastari"] = true,
["Baron Rivendare"] = true,
["Cannon Master Willey"] = true,
["Captain Kromcrush"] = true,
["Celebras the Cursed"] = true,
["Crystal Fang"] = true,
["Darkmaster Gandling"] = true,
["Doctor Theolen Krastinov"] = true,
["Doom'rel"] = true,
["Dope'rel"] = true,
["Dreamscythe"] = true,
["Emperor Dagran Thaurissan"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["General Angerforge"] = true,
["General Drakkisath"] = true,
["Gloom'rel"] = true,
["Golem Lord Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Guard Fengus"] = true,
["Guard Mol'dar"] = true,
["Guard Slip'kik"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Hate'rel"] = true,
["Hazzas"] = true,
["Hearthsinger Forresten"] = true,
["High Interrogator Gerstahn"] = true,
["Highlord Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrospawn"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instructor Malicia"] = true,
["Jammal'an the Prophet"] = true,
["Jandice Barov"] = true,
["King Gordok"] = true,
["Kirtonos the Herald"] = true,
["Lady Illucia Barov"] = true,
["Landslide"] = true,
["Lethtendris"] = true,
["Lord Alexei Barov"] = true,
["Lord Incendius"] = true,
["Lord Vyletongue"] = true,
["Lorekeeper Polkelt"] = true,
["Loro"] = true,
["Magister Kalendris"] = true,
["Magistrate Barthilas"] = true,
["Magmus"] = true,
["Maleki the Pallid"] = true,
["Marduk Blackpool"] = true,
["Meshlok the Harvester"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Mother Smolderweb"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom the Wretched"] = true,
["Overlord Wyrmthalak"] = true,
["Phalanx"] = true,
["Plugger Spazzring"] = true,
["Postmaster Malown"] = true,
["Princess Moira Bronzebeard"] = true,
["Princess Theradras"] = true,
["Prince Tortheldrin"] = true,
["Pusillin"] = true,
["Pyroguard Emberseer"] = true,
["Ramstein the Gorger"] = true,
["Ras Frostwhisper"] = true,
["Rattlegore"] = true,
["Razorlash"] = true,
["Warchief Rend Blackhand"] = true,
["Ribbly Screwspigot"] = true,
["Rotgrip"] = true,
["Seeth'rel"] = true,
["Shade of Eranikus"] = true,
["Shadow Hunter Vosh'gajin"] = true,
["Solakar Flamewreath"] = true,
["Stomper Kreeg"] = true,
["Tendris Warpwood"] = true,
["The Beast"] = true,
["The Ravenian"] = true,
["Timmy the Cruel"] = true,
["Tinkerer Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Vile'rel"] = true,
["War Master Voone"] = true,
["Weaver"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
-- From Mendeleev
["Cho'Rush the Observer"] = true,
["Lord Hel'nurath"] = true,
["Pimgib"] = true,
["Knot Thimblejack's Cache"] = true,
["Cannonmaster Willey"] = true,
["Emperor Dagran Thaurissian"] = true,
["Archmage Arugal"] = true,
["Archmage Arugal's Voidwalker"] = true,
["Baron Silverlaine"] = true,
["Commander Springvale"] = true,
["Prelate Ironmane"] = true,
["Deathsworn Captain"] = true,
["Fenrus the Devourer"] = true,
["Odo the Blindwatcher"] = true,
["Razorclaw the Butcher"] = true,
["Wolf Master Nandos"] = true,
["Rend Blackhand"] = true,
["Kurinnaxx"] = true,
-- From Zae for Kara 40
["Keeper Gnarlmoon"] = true,
["Ley-Watcher Incantagos"] = true,
["Anomalus"] = true,
["Echo of Medivh"] = true,
["King"] = true,
["Queen"] = true,
["Bishop"] = true,
["Rook"] = true,
["Ima'ghaol, Herald of Desolation"] = true,
["Sanv Tas'dal"] = true,
["Rupturan the Broken"] = true,
["Kruul"] = true,
["Mephistroth"] = true,
["Master Blacksmith Rolfen"] = true, -- Lower Kara
["Brood Queen Araxxna"] = true,
["Grizikil"] = true,
["Clawlord Howlfang"] = true,
["Lord Blackwald II"] = true,
["Moroes"] = true,
["Incindis"] = true, -- MC Update
["Basalthar"] = true,
["Smoldaris"] = true,
["Sorcerer-Thane Thaurissan"] = true,
["Solnius"] = true,
["Erennius"] = true,
-- Emerald Sanctum
["Sanctum Dragonkin"] = true,
["Sanctum Dreamer"] = true,
["Sanctum Supressor"] = true,
["Sanctum Wyrmkin"] = true,
["Sanctum Wyrm"] = true,
-- Black Morass
["Rotmaw"] = true,
["Antnormi"] = true,
["Mossheart"] = true,
["Time-Lord Epochronos"] = true,
["Drifting Avatar of Sand"] = true,
["Epidamu"] = true,
["Chronar"] = true,
-- TWoW world bosses
["Nerubian Overseer"] = true,
["Dark Reaver of Karazhan"] = true,
["Ostarius"] = true,
["Cla'ckora"] = true,
["Father Lycan"] = true,
["Snowball"] = true,
-- Low level dungeons
["Maur Grimtotem"] = true,
["Oggleflint"] = true,
["Taragaman the Hungerer"] = true,
["Jergosh the Invoker"] = true,
["Bazzalan"] = true,
["Disciple of Naralex"] = true,
["Lord Cobrahn"] = true,
["Lady Anacondra"] = true,
["Kresh"] = true,
["Lord Pythas"] = true,
["Skum"] = true,
["Lord Serpentis"] = true,
["Verdan the Everliving"] = true,
["Zandara Windhoof"] = true,
["Vangros"] = true,
["Mutanus the Devourer"] = true,
["Naralex"] = true,
["Deviate Faerie Dragon"] = true,
["Ghamoo-ra"] = true,
["Lady Sarevess"] = true,
["Gelihast"] = true,
["Lorgus Jett"] = true,
["Baron Aquanis"] = true,
["Velthelaxx the Defiler"] = true,
["Twilight Lord Kelris"] = true,
["Old Serra'kis"] = true,
["Aku'mai"] = true,
["Roogug"] = true,
["Aggem Thorncurse"] = true,
["Death Speaker Jargba"] = true,
["Overlord Ramtusk"] = true,
["Agathelos the Raging"] = true,
["Blind Hunter"] = true,
["Charlga Razorflank"] = true,
["Earthcaller Halmgar"] = true,
["Rotthorn"] = true,
["Tuten'kash"] = true,
["Lady Falther'ess"] = true,
["Mordresh Fire Eye"] = true,
["Glutton"] = true,
["Ragglesnout"] = true,
["Death Prophet Rakameg"] = true,
["Amnennar the Coldbringer"] = true,
["Plaguemaw the Rotting"] = true,
["Matthias Holtz"] = true,
["Packmaster Ragetooth"] = true,
["Judge Sutherland"] = true,
["Dustivan Blackcowl"] = true,
["Marshal Magnus Greystone"] = true,
["Horsemaster Levvin"] = true,
["Genn Greymane"] = true,
["Regent-Lord Mortimer Harlow"] = true,
["Antu'sul"] = true,
["Dustwraith"] = true,
["Zerillis"] = true,
["Witch Doctor Zum'rah"] = true,
["Shadowpriest Sezz'ziz"] = true,
["Gahz'rilla"] = true,
["Zel'jeb the Ancient"] = true,
["Champion Razjal the Quick"] = true,
["Chief Ukorz Sandscalp"] = true,
["Ruuzlu"] = true,
["Isalien"] = true,
["Revanchion"] = true,
["High Foreman Bargul Blackhammer"] = true,
["Engineer Figgles"] = true,
["Corrosis"] = true,
["Hatereaver Annihilator"] = true,
["Har'gesh Doomcaller"] = true,
["Lord Roccor"] = true,
["Anub'shiah"] = true,
["Eviscerator"] = true,
["Gorosh the Dervish"] = true,
["Grizzle"] = true,
["Hedrum the Creeper"] = true,
["Ok'thor the Breaker"] = true,
["Houndmaster Grebmar"] = true,
["Pyromancer Loregrain"] = true,
["Warder Stilgiss"] = true,
["Verek"] = true,
["Watchman Doomgrip"] = true,
["Panzor the Invincible"] = true,
["Mor Grayhoof"] = true,
["Bannok Grimaxe"] = true,
["Urok Doomhowl"] = true,
["Quartermaster Zigris"] = true,
["Gizrul the Slavener"] = true,
["Ghok Bashguud"] = true,
["Jed Runewatcher"] = true,
["Lord Valthalak"] = true,
["Grubbis"] = true,
["Chomper"] = true,
["Viscous Fallout"] = true,
["Electrocutioner 6000"] = true,
["Crowd Pummeler 9-60"] = true,
["Dark Iron Ambassador"] = true,
["Mekgineer Thermaplugg"] = true,
["Houndmaster Loksey"] = true,
["Brother Wynstan"] = true,
["Arcanist Doan"] = true,
["Armory Quartermaster Daghelm"] = true,
["Herod"] = true,
["High Inquisitor Fairbanks"] = true,
["Scarlet Commander Mograine"] = true,
["High Inquisitor Whitemane"] = true,
["Interrogator Vishas"] = true,
["Bloodmage Thalnos"] = true,
["Ironspine"] = true,
["Azshir the Sleepless"] = true,
["Fallen Champion"] = true,
["Oronok Torn-Heart"] = true,
["Dagar the Glutton"] = true,
["Duke Balor the IV"] = true,
["Librarian Theodorus"] = true,
["Chieftain Stormsong"] = true,
["Deathlord Tidebane"] = true,
["Subjugator Halthas Shadecrest"] = true,
["Mycellakos"] = true,
["Eldermaw the Primordial"] = true,
["Lady Drazare"] = true,
["Remains of the Innocent"] = true,
["Mergothid"] = true,
["Ighal'for"] = true,
["Death Knight Darkreaver"] = true,
["Kormok"] = true,
["Skul"] = true,
["Balzaphon"] = true,
["Malor the Zealous"] = true,
["Sothos"] = true,
["Jarien"] = true,
["Stonespine"] = true,
["Jared Voss"] = true,
["Rhahk'Zor"] = true,
["Miner Johnson"] = true,
["Masterpiece Harvester"] = true,
["Sneed"] = true,
["Gilnid"] = true,
["Captain Greenskin"] = true,
["Edwin VanCleef"] = true,
["Mr. Smite"] = true,
["Cookie"] = true,
["Targorr the Dread"] = true,
["Kam Deepfury"] = true,
["Hamhock"] = true,
["Bazil Thredd"] = true,
["Dextren Ward"] = true,
["Bruegal Ironknuckle"] = true,
["Gowlfang"] = true,
["Cavernweb Broodmother"] = true,
["Web Master Torkon"] = true,
["Garlok Flamekeeper"] = true,
["Halgan Redbrand"] = true,
["Slagfist Destroyer"] = true,
["Overlord Blackheart"] = true,
["Elder Hollowblood"] = true,
["Searistrasz"] = true,
["Zuluhed the Whacked"] = true,
["Duke Dreadmoore"] = true,
["Grovetender Engryss"] = true,
["Keeper Ranathos"] = true,
["High Priestess A'lathea"] = true,
["Fenektis the Deceiver"] = true,
["Master Raxxieth"] = true,
["Baelog"] = true,
["Eric \"The Swift\""] = true,
["Olaf"] = true,
["Revelosh"] = true,
["Ironaya"] = true,
["Obsidian Sentinel"] = true,
["Ancient Stone Keeper"] = true,
["Galgann Firehammer"] = true,
["Grimlok"] = true,
["Archaedas"] = true,
["Sever"] = true,
["Scorn"] = true,
["Rethilgore"] = true,
["Atiesh"] = true,
["Marrowspike"] = true,
["Hivaxxis"] = true,
["Corpsemuncher"] = true,
["Guard Captain Gort"] = true,
["Archlich Enkhraz"] = true,
["Commander Andreon"] = true,
["Alarus"] = true,
["Aszosh Grimflame"] = true,
["Tham'Grarr"] = true,
["Black Bride"] = true,
["Damian"] = true,
["Volkan Cruelblade"] = true,
["Arc'tiras"] = true,
}
BabbleBoss = {}
function BabbleBoss:Contains(name)
return bosses[name]
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+536
View File
@@ -0,0 +1,536 @@
DPSMate.L["name"] = "DPSMate"
DPSMate.L["popup"] = "Do you want to reset DPSMate?"
DPSMate.L["memory"] = "DPSMate has collected a lot of data. This will cause screen lag during the data saving process upon logout. Do you want to reset DPSMate first?"
DPSMate.L["accept"] = "Accept"
DPSMate.L["decline"] = "Decline"
DPSMate.L["total"] = "Total"
DPSMate.L["current"] = "Current"
DPSMate.L["cancel"] = "Cancel"
DPSMate.L["report"] = "Report"
DPSMate.L["reportfor"] = "Report for "
-- Abilities
DPSMate.L["vanish"] = "Vanish"
DPSMate.L["feigndeath"] = "Feign Death"
DPSMate.L["divineintervention"] = "Divine Intervention"
DPSMate.L["stealth"] = "Stealth"
-- Evaluation frame
DPSMate.L["procs"] = "Procs"
DPSMate.L["procstooltip"] = "Select a proc to display it in the LineGraph."
DPSMate.L["absorbsby"] = "Absorbs by "
DPSMate.L["absorbstakenby"] = "Absorbstaken by "
DPSMate.L["aurasof"] = "Auras of "
DPSMate.L["BUDEBU"] = {"Buffs", "Debuffs"}
DPSMate.L["castsof"] = "Casts of "
DPSMate.L["bname"] = "Name"
DPSMate.L["count"] = "Count"
DPSMate.L["uptime"] = "Uptime"
DPSMate.L["chance"] = "Chance"
DPSMate.L["ccbreakerof"] = "CCBreaker of "
DPSMate.L["time"] = "Time"
DPSMate.L["cbt"] = "CBT"
DPSMate.L["ability"] = "Ability"
DPSMate.L["target"] = "Target"
DPSMate.L["diseasecuredby"] = "Disease cured by "
DPSMate.L["diseasecuredof"] = "Disease cured of "
DPSMate.L["poisoncuredby"] = "Poison cured by "
DPSMate.L["poisoncuredof"] = "Poison cured of "
DPSMate.L["dmgdoneby"] = "Damage done by "
DPSMate.L["dmgtakenby"] = "Damage taken by "
DPSMate.L["dmgtakensum"] = "Damage taken summary"
DPSMate.L["dmgdonesum"] = "Damage done summary"
DPSMate.L["deathsof"] = "Deaths of "
DPSMate.L["cause"] = "Cause"
DPSMate.L["type"] = "Type"
DPSMate.L["healin"] = "Heal In"
DPSMate.L["damagein"] = "Damage In"
DPSMate.L["decursesby"] = "Decurses by "
DPSMate.L["decursesreceivedby"] = "Decurses received of "
DPSMate.L["dispelsby"] = "Dispels by "
DPSMate.L["dispelsreceivedby"] = "Dispels received of "
DPSMate.L["block"] = "Block"
DPSMate.L["crush"] = "Crush"
DPSMate.L["hit"] = "Hit"
DPSMate.L["average"] = "Average"
DPSMate.L["min"] = "Min"
DPSMate.L["max"] = "Max"
DPSMate.L["crit"] = "Crit"
DPSMate.L["miss"] = "Miss"
DPSMate.L["parry"] = "Parry"
DPSMate.L["dodge"] = "Dodge"
DPSMate.L["resist"] = "Resist"
DPSMate.L["glance"] = "Glance"
DPSMate.L["effhealdoneby"] = "Effective healing done by "
DPSMate.L["effhealtakenby"] = "Effective healing taken by "
DPSMate.L["failsof"] = "Fails of "
DPSMate.L["victim"] = "Victim"
DPSMate.L["ffby"] = "Friendly fire by "
DPSMate.L["healdoneby"] = "Healing done by "
DPSMate.L["habby"] = "Healing and Absorbs by "
DPSMate.L["healtakenby"] = "Healing taken by "
DPSMate.L["interruptsby"] = "Interrupts by "
DPSMate.L["magicliftby"] = "Magic lifted by "
DPSMate.L["magicliftof"] = "Magic lifted of "
DPSMate.L["overhealby"] = "Overhealing done by "
DPSMate.L["procsof"] = "Procs of "
-- Menu
DPSMate.L["mdps"] = "Show dps."
DPSMate.L["mdmg"] = "Show damage done."
DPSMate.L["mdmgtaken"] = "Show damage taken."
DPSMate.L["medd"] = "Show the damage done by enemies."
DPSMate.L["medt"] = "Show the damage that enemies took."
DPSMate.L["mhealing"] = "Show efficient healing."
DPSMate.L["mhab"] = "Show efficient healing with absorbs."
DPSMate.L["mhealingtaken"] = "Show healing taken."
DPSMate.L["moverhealing"] = "Show overhealing done."
DPSMate.L["minterrupts"] = "Show interrupts done."
DPSMate.L["mdeaths"] = "Show deaths."
DPSMate.L["mdispels"] = "Show dispels done."
DPSMate.L["totalmode"] = "Set to total mode."
DPSMate.L["currentmode"] = "Set to current mode."
DPSMate.L["reportsegment"] = "Report this segment."
DPSMate.L["resetdesc"] = "Reset DPSMate."
DPSMate.L["newsegment"] = "New segment"
DPSMate.L["newsegmentdesc"] = "Start a new segment."
DPSMate.L["removesegment"] = "Remove segment"
DPSMate.L["removesegmentdesc"] = "Remove an segment."
DPSMate.L["purgeoldsegments"] = "Delete segments > 24h"
DPSMate.L["purgeoldsegmentsdesc"] = "Delete all saved segments older than 24 hours."
DPSMate.L["purgeoldsegmentsdone"] = "Segments older than 24 hours have been deleted."
DPSMate.L["purgenotimestamp"] = "24h purge unavailable: time() is not exposed on this server."
DPSMate.L["lockdesc"] = "Lock the DPSMate frame."
DPSMate.L["hidewindowdesc"] = "Hide the DPSMate frame."
DPSMate.L["showwindowdesc"] = "Show the DPSMate frame."
DPSMate.L["configframe"] = "Open the configuration frame."
DPSMate.L["testmodedesc"] = "Toggle the test mode."
DPSMate.L["filterdesc"] = "Filter options."
DPSMate.L["switchdesc"] = "Switch mode"
DPSMate.L["mcurrent"] = "Current fight"
DPSMate.L["mrealtime"] = "Create realtime graph"
DPSMate.L["mrealtimedesc"] = 'Create a realtime graph. Be aware it takes a lot of ressources.'
DPSMate.L["damagedone"] = "Damage done"
DPSMate.L["realtimedmgdone"] = 'Select damage done for this frame.'
DPSMate.L["realtimedmgtaken"] = 'Select damage taken for this frame.'
DPSMate.L["realtimehealing"] = 'Select raw healing for this frame.'
DPSMate.L["realtimeehealing"] = 'Select effective healing for this frame.'
DPSMate.L["showAll"] = "Show all"
DPSMate.L["showAllDesc"] = 'Click to show all frames'
DPSMate.L["hideAll"] = "Hide all"
DPSMate.L["hideAllDesc"] = 'Click to hide all frames'
DPSMate.L["showwindow"] = "Show window"
DPSMate.L["hidewindow"] = "Hide window"
DPSMate.L["unlock"] = "Unlock windows"
DPSMate.L["config"] = "Configure"
DPSMate.L["reportdesc"] = "Report details"
DPSMate.L["whisper"] = "Whisper"
DPSMate.L["whisperdesc"] = "Whisper someone"
DPSMate.L["classes"] = "Classes"
DPSMate.L["classesdesc"] = "Select classes"
DPSMate.L["warrior"] = "Warrior"
DPSMate.L["rogue"] = "Rogue"
DPSMate.L["warlock"] = "Warlock"
DPSMate.L["mage"] = "Mage"
DPSMate.L["paladin"] = "Paladin"
DPSMate.L["shaman"] = "Shaman"
DPSMate.L["priest"] = "Priest"
DPSMate.L["druid"] = "Druid"
DPSMate.L["hunter"] = "Hunter"
DPSMate.L["warriordesc"] = "Show warrior"
DPSMate.L["roguedesc"] = "Show rogues"
DPSMate.L["warlockdesc"] = "Show warlocks"
DPSMate.L["magedesc"] = "Show mages"
DPSMate.L["paladindesc"] = "Show paladins"
DPSMate.L["shamandesc"] = "Show shaman"
DPSMate.L["priestdesc"] = "Show priest"
DPSMate.L["druiddesc"] = "Show druids"
DPSMate.L["hunterdesc"] = "Show hunter"
DPSMate.L["certainnames"] = "Certain names"
DPSMate.L["certainnamesdesc"] = 'Split them by "," Ex: Shino,'
DPSMate.L["grouponly"] = "Group only"
DPSMate.L["grouponlydesc"] = "Only show your group"
-- Config menu
DPSMate.L["slider"] = "Lines"
DPSMate.L["slidertooltip"] = "Move this to set the amount of lines that will be reported."
DPSMate.L["editboxtitle"] = "Whisper Target"
DPSMate.L["editboxtooltip"] = "Enter the name you'd like to report to."
DPSMate.L["channel"] = "Channel"
DPSMate.L["channeltooltip"] = "Select the channel you'd like to submit your report."
DPSMate.L["close"] = "Close"
DPSMate.L["minimapleft"] = "LeftClick-Drag to move the icon."
DPSMate.L["minimapright"] = "RightClick to open the menu."
DPSMate.L["window"] = "Window"
DPSMate.L["bars"] = "Bars"
DPSMate.L["titlebar"] = "Title bar"
DPSMate.L["content"] = "Content"
DPSMate.L["modeswitching"] = "Mode switching"
DPSMate.L["dataresets"] = "Data resets"
DPSMate.L["generaloptions"] = "General options"
DPSMate.L["columns"] = "Columns"
DPSMate.L["tooltips"] = "Tooltips"
DPSMate.L["broadcasting"] = "Broadcasting options"
DPSMate.L["about"] = "About"
DPSMate.L["createwindow"] = "Create window"
DPSMate.L["createwindowtooltip"] = "Enter the name of the window."
DPSMate.L["submit"] = "Submit"
DPSMate.L["submitTooltip"] = "Click here to create the window."
DPSMate.L["availwindows"] = "Available windows"
DPSMate.L["availwindowsTooltip"] = "Select a window."
DPSMate.L["lock"] = "Lock windows"
DPSMate.L["testmode"] = "Test mode"
DPSMate.L["barfont"] = "Bar font"
DPSMate.L["barfontTooltip"] = "Select a bar font."
DPSMate.L["barfontsize"] = "Bar font size"
DPSMate.L["barfontsizeTooltip"] = "Move this to change the bar font size."
DPSMate.L["barfontflags"] = "Bar font flags"
DPSMate.L["barfontflagsTooltip"] = "Select a font flag."
DPSMate.L["bartexture"] = "Bar texture"
DPSMate.L["bartextureTooltip"] = "Select a bar texture."
DPSMate.L["barspacing"] = "Bar spacing"
DPSMate.L["barspacingTooltip"] = "Move this to change the spacing between the bars."
DPSMate.L["barheight"] = "Bar height"
DPSMate.L["barheightTooltip"] = "Move this to change the bar height."
DPSMate.L["classicons"] = "Class icons"
DPSMate.L["ranks"] = "Ranks"
DPSMate.L["mode"] = "Mode"
DPSMate.L["modes"] = "Modes"
DPSMate.L["reset"] = "Reset"
DPSMate.L["sync"] = "Synchronizing"
DPSMate.L["bgcolor"] = "Background color"
DPSMate.L["fontcolor"] = "Font color"
DPSMate.L["fontcolorTooltip"] = "Click to choose a font color."
DPSMate.L["bgcolorTooltip"] = "Click to choose a background color."
DPSMate.L["scale"] = "Scale"
DPSMate.L["scaleTooltip"] = "Move this to change the scale of the frame."
DPSMate.L["opacity"] = "Opacity"
DPSMate.L["opacityTooltip"] = "Move this to change the opacity of the frame."
DPSMate.L["bgtex"] = "Background texture"
DPSMate.L["bgtexTooltip"] = "Change the texture of the frame."
DPSMate.L["enterworldinstance"] = "World/Instance"
DPSMate.L["enterworldinstanceTooltip"] = "Reset on entering world or instance"
DPSMate.L["joinparty"] = "Joining a party"
DPSMate.L["joinpartyTooltip"] = "Reset on joining a party"
DPSMate.L["leavingparty"] = "Leaving a party"
DPSMate.L["leavingpartyTooltip"] = "Reset on leaving a party"
DPSMate.L["partymemberchanged"] = "Party amount changed"
DPSMate.L["partymemberchangedTooltip"] = "Reset on party member amount changed"
DPSMate.L["minimap"] = "Show minimap button"
DPSMate.L["showtotal"] = "Show totals"
DPSMate.L["solo"] = "Hide when solo"
DPSMate.L["combat"] = "Hide in combat"
DPSMate.L["bossfights"] = "Only keep boss fights"
DPSMate.L["pvp"] = "Hide in PVP"
DPSMate.L["disable"] = "Disable while hidden"
DPSMate.L["mergepets"] = "Merge pets"
DPSMate.L["numberformat"] = "Number format"
DPSMate.L["numberformatTooltip"] = "Controls how numbers are displayed."
DPSMate.L["segments"] = "Data segments to keep"
DPSMate.L["segmentsTooltip"] = "Move this to increase the amount of fight segments that are saved. This increases data collection a lot and may cause lag!"
DPSMate.L["enable"] = "Enable"
DPSMate.L["damage"] = "Damage"
DPSMate.L["percent"] = "Percent"
DPSMate.L["dps"] = "DPS"
DPSMate.L["edps"] = "EDPS"
DPSMate.L["dtps"] = "DTPS"
DPSMate.L["edtps"] = "EDTPS"
DPSMate.L["healing"] = "Healing"
DPSMate.L["hps"] = "HPS"
DPSMate.L["ehps"] = "EHPS"
DPSMate.L["etps"] = "ETPS"
DPSMate.L["damagetaken"] = "Damage taken"
DPSMate.L["enemydamagedone"] = "Enemy damage done"
DPSMate.L["enemydamagetaken"] = "Enemy damage taken"
DPSMate.L["healing"] = "Healing"
DPSMate.L["absorbs"] = "Absorbs"
DPSMate.L["absorbstaken"] = "Absorbs taken"
DPSMate.L["amount"] = "Amount"
DPSMate.L["dispelsreceived"] = "Dispels received"
DPSMate.L["decurses"] = "Decurses"
DPSMate.L["decursesreceived"] = "Decurses received"
DPSMate.L["curedisease"] = "Diseases cured"
DPSMate.L["curepoison"] = "Poisons cured"
DPSMate.L["liftmagic"] = "Magic lifted"
DPSMate.L["aurasgained"] = "Auras gained"
DPSMate.L["auraslost"] = "Auras lost"
DPSMate.L["aurauptime"] = "Aura uptime"
DPSMate.L["friendlyfire"] = "Friendly fire"
DPSMate.L["procs"] = "Procs"
DPSMate.L["liftmagicreceived"] = "Magic lift received"
DPSMate.L["curepoisonreceived"] = "Poison cure received"
DPSMate.L["curediseasereceived"] = "Disease cure received"
DPSMate.L["effectivehealing"] = "Effective healing"
DPSMate.L["effectivehps"] = "Effective HPS"
DPSMate.L["effectivehealingtaken"] = "Effective healing taken"
DPSMate.L["healingandabsorbs"] = "Healing and Absorbs"
DPSMate.L["healingtaken"] = "Healing taken"
DPSMate.L["overhealing"] = "Overhealing"
DPSMate.L["interrupts"] = "Interrupts"
DPSMate.L["deaths"] = "Deaths"
DPSMate.L["dispels"] = "Dispels"
DPSMate.L["threat"] = "Threat"
DPSMate.L["tps"] = "TPS"
DPSMate.L["fails"] = "Fails"
DPSMate.L["cat"] = "Category"
DPSMate.L["ccbreaker"] = "CCBreaker"
DPSMate.L["subviewrows"] = "Subview rows"
DPSMate.L["subviewrowsTooltip"] = "Move this to change the amount of rows displayed in the tooltip."
DPSMate.L["TooltipPositionDropDown"] = "Tooltip position"
DPSMate.L["TooltipPositionDropDownTooltip"] = "Select the position of the tooltip relative to the frame."
DPSMate.L["whatisdpsmate"] = "What is DPSMate?"
DPSMate.L["whatisdpsmateText"] = "DPSMate is a combat analyzing tool. It provides a lot of functions to review the fight as accurately as possible. By this information gameplay improvements are easy to evaluate."
DPSMate.L["whocreateddpsmate"] = "Who created DPSMate?"
DPSMate.L["whocreateddpsmateText"] = "DPSMate was created by Shino (Albea) <Synced> who developed the AddOn on Kronos (Twinstar.cz). He is formally known as Geigerkind in the Twinstar community."
DPSMate.L["thanksto"] = "Thanks to following supporters:"
DPSMate.L["thankstoText"] = "Weasel - For beta testing and providing feedback. \nBambustreppe - For translating DPSMate to german. \nDreamstate - For beta testing DPSMate TBC and providing nice suggestions for features. \nMaus - Huge thanks for the full ruRU translation. \nITTranslator - For translating DPSMate to french. \nDarkmiao - For translating DPSMate to mandarin."
DPSMate.L["remove"] = "Remove"
DPSMate.L["removeTooltip"] = "Click here in order to remove the selected window."
DPSMate.L["copy"] = "Copy"
DPSMate.L["copyTooltip"] = "Click here to copy the configuration to the selected window."
DPSMate.L["configto"] = "Copy configuration to:"
DPSMate.L["configtoTooltip"] = "Select the window you want to configure."
DPSMate.L["configfrom"] = "Copy configuration from:"
DPSMate.L["configfromTooltip"] = "Select the windows you want to copy the configuration from."
DPSMate.L["reset"] = "Reset"
DPSMate.L["syncrequest"] = "Sync reset request"
DPSMate.L["syncrequesttooltip"] = "What happens if an sync reset request pops up."
DPSMate.L["dataresetslogout"] = "Logout reset request"
DPSMate.L["dataresetslogouttooltip"] = "Reset on logout"
DPSMate.L["enabledisable"] = "Enable/Disable"
DPSMate.L["bgbarcolor"] = "Background bar color"
DPSMate.L["bgbarcolorTooltip"] = "Click to choose a background bar color."
DPSMate.L["displayoptions"] = "Display options"
DPSMate.L["filter"] = "Filter options"
DPSMate.L["raidleader"] = "Raid leader options"
DPSMate.L["bgOpacityTooltip"] = "Adjust the opacity of the background."
DPSMate.L["bgOpacity"] = "Background opacity"
DPSMate.L["casts"] = "Casts"
DPSMate.L["locktooltip"] = "Check this to lock the frames."
DPSMate.L["testmodetooltip"] = "Check this to activate the testmode."
DPSMate.L["classiconstooltip"] = "Check this to show additions classicons on the statusbars."
DPSMate.L["rankstooltip"] = "Check this to show the rank position in the meter."
DPSMate.L["enabletitlebartooltip"] = "Check this to enable the title bar."
DPSMate.L["buttonshowtooltip"] = "Check this to show this icon on the titlebar."
DPSMate.L["minimaptooltip"] = "Check this to show the minimap icon."
DPSMate.L["showtotaltooltip"] = "Check this to get an extra bar for total stats."
DPSMate.L["solotooltip"] = "Check this to hide the frame when you are not in a group or raid."
DPSMate.L["combattooltip"] = "Check this to hide the frame when you enter combat."
DPSMate.L["bossfightstooltip"] = "Check this to only save boss fights."
DPSMate.L["pvptooltip"] = "Check this to hide the frame when you enter a battleground."
DPSMate.L["disabletooltip"] = "Check this to disable data collection when the frames are hidden."
DPSMate.L["mergepetstooltip"] = "Check this to merge pets with their respective owner."
DPSMate.L["showtooltips"] = "Show tooltips"
DPSMate.L["showtooltipsTooltip"] = "Check this to show tooltips when you hover over something."
DPSMate.L["informativetooltips"] = "Informative tooltips"
DPSMate.L["informativetooltipsTooltip"] = "Check this to render tooltips with more details."
DPSMate.L["shownmodes"] = "Shown modes"
DPSMate.L["hiddenmodes"] = "Hidden modes"
DPSMate.L["moveleftTooltip"] = "Click to show thise mode."
DPSMate.L["moverightTooltip"] = "Click to hide this mode."
DPSMate.L["helloworld"] = "Hello World!"
DPSMate.L["helloworldTooltip"] = "Return a list of player being in the Synced-Channel."
DPSMate.L["enablebroadcasting"] = "Check this to enable the broadcasting options below."
DPSMate.L["useraidwarning"] = "Use raidwarning"
DPSMate.L["useraidwarningTooltip"] = "Check this to use the raid warning channel instead of the raid channel."
DPSMate.L["relevantcds"] = "Relevant cooldowns"
DPSMate.L["relevantcdsTooltip"] = "Check this to broadcast relevant cooldowns like Shield Wall for example."
DPSMate.L["ress"] = "Ressurections"
DPSMate.L["ressTooltip"] = "Check this to broadcast if someone received a ress."
DPSMate.L["killingblows"] = "Killingblows"
DPSMate.L["killingblowsTooltip"] = "Check this to broadcast killing blow information if a player died."
DPSMate.L["failsTooltip"] = "Check this to broadcast if a player failed. (Friendly Fire/Damage taken/Debuff taken)"
DPSMate.L["framesavailable"] = "Following frames are available. If there is none type /config."
DPSMate.L["slashabout"] = "|c3ffddd80About:|r A combat analyzation tool."
DPSMate.L["slashusage"] = "|c3ffddd80Usage:|r /dps {lock|unlock|show|hide|config}"
DPSMate.L["slashlock"] = "|c3ffddd80- lock:|r Lock your windows."
DPSMate.L["slashunlock"] = "|c3ffddd80- unlock:|r Unlock your windows."
DPSMate.L["slashshowAll"] = "|c3ffddd80- showAll:|r Show all windows."
DPSMate.L["slashhideAll"] = "|c3ffddd80- hideAll:|r Hide all windows."
DPSMate.L["slashshow"] = "|c3ffddd80- show {name}:|r Show the window with the name {name}."
DPSMate.L["slashhide"] = "|c3ffddd80- hide {name}:|r Hide the window with the name {name}."
DPSMate.L["slashconfig"] = "|c3ffddd80- config:|r Opens the config menu."
DPSMate.L["slashreset"] = "|c3ffddd80- reset:|r Wipes all saved data (players, abilities, history, metrics)."
DPSMate.L["resetconfirm"] = "Are you sure you want to reset ALL DPSMate data? This cannot be undone. Type /dps resetconfirm to proceed."
DPSMate.L["resetdone"] = "All DPSMate data has been reset."
DPSMate.L["bccdo"] = function(who, what) return who.." gained "..what end
DPSMate.L["bccdt"] = function(who, what) return who.."'s "..what.." faded" end
DPSMate.L["bcress"] = function(who, what) return what.." has been resurrected by "..who end
DPSMate.L["bckb"] = function(who, what, with, value) return who.." has been killed by "..what.."'s "..with.." ("..value.." damage)" end
DPSMate.L["bcfailo"] = function(what, who, value, with) return "Fail: "..what.." friendly fired "..who.." "..value.." damage with "..with end
DPSMate.L["bcfailt"] = function(who, with) return "Fail: "..who.." is afflicted by "..with end
DPSMate.L["bcfailth"] = function(who, value, with, what) return "Fail: "..who.." suffered "..value.." damage from "..with.." by "..what end
DPSMate.L["syncreseterror"] = "DPSMate cant be reset while being in Sync-Mode in raids."
DPSMate.L["resetnotofficererror"] = "You are not the leader of the group or an assist!"
DPSMate.L["findusererror"] = "Could not find this user!"
DPSMate.L["yes"] = "Yes"
DPSMate.L["no"] = "No"
DPSMate.L["ask"] = "Ask"
DPSMate.L["normal"] = "Normal"
DPSMate.L["condensed"] = "Condensed"
DPSMate.L["default"] = "Default"
DPSMate.L["topright"] = "Top Right"
DPSMate.L["topleft"] = "Top Left"
DPSMate.L["left"] = "Left"
DPSMate.L["top"] = "Top"
DPSMate.L["gchannel"] = {[1]="Raid",[2]="Party",[3]="Say",[4]="Officer",[5]="Guild"}
DPSMate.L["nodetailserror"] = "There are no details to be reported."
DPSMate.L["reportof"] = "Report of"
DPSMate.L["opendetails"] = "Open details"
DPSMate.L["reportdetails"] = "Report the details of this user."
DPSMate.L["fdetailsfor"] = "Fight details for "
DPSMate.L["removesegmentof"] = "Remove segment of "
DPSMate.L["lockedallw"] = "Locked all windows."
DPSMate.L["unlockedallw"] = "Unlocked all windows."
DPSMate.L["leftclickopend"] = "LeftClick to open the details."
DPSMate.L["rightclickopenm"] = "RightClick to open the menu."
DPSMate.L["hide"] = "Hide"
DPSMate.L["show"] = "Show"
DPSMate.L["rcchangemode"] = "RightClick to change the mode."
DPSMate.L["segment"] = "Segment"
DPSMate.L["sync"] = "Synchronising"
DPSMate.L["alliance"] = "Alliance"
DPSMate.L["horde"] = "Horde"
DPSMate.L["unknown"] = "Unknown"
DPSMate.L["votestartederror"] = "Vote has already been started!"
DPSMate.L["votefailederror"] = "Reset vote failed!"
DPSMate.L["votesuccess"] = "Reset vote was successful! DPSMate has been reset!"
DPSMate.L["disease"] = "Disease"
DPSMate.L["magic"] = "Magic"
DPSMate.L["curse"] = "Curse"
DPSMate.L["poison"] = "Poison"
DPSMate.L["physical"] = "Physical"
DPSMate.L["debufftaken"] = "Debuff taken"
DPSMate.L["buffs"] = "Buffs"
DPSMate.L["debuffs"] = "Debuffs"
DPSMate.L["mc"] = "Molten Core"
DPSMate.L["bwl"] = "Blackwing Lair"
DPSMate.L["ony"] = "Onyxia's Lair"
DPSMate.L["zg"] = "Zul'Gurub"
DPSMate.L["aq401"] = "Ruins of Ahn'Qiraj"
DPSMate.L["aq20"] = "Temple of Ahn'Qiraj"
DPSMate.L["aq402"] = "Ahn'Qiraj"
DPSMate.L["naxx"] = "Naxxramas"
DPSMate.L["azs"] = "Azshara"
DPSMate.L["bl"] = "Blasted Lands"
DPSMate.L["dw"] = "Duskwood"
DPSMate.L["hintl"] = "Hinterlands"
DPSMate.L["ash"] = "Ashenvale"
DPSMate.L["fe"] = "Feralas"
DPSMate.L["switchgraphsdesc"] = "Switch graphs"
DPSMate.L["switchindividualsdesc"] = "Individual/Total"
DPSMate.L["OHPS"] = "OHPS"
DPSMate.L["OHealingTaken"] = "Overhealing taken"
DPSMate.L["eohps"] = "EOHPS"
DPSMate.L["ohealtakenby"] = "Overhealing taken by "
DPSMate.L["friendlyfiretaken"] = "Friendly fire taken"
DPSMate.L["fftby"] = "Friendly fire taken by "
DPSMate.L["poisoncleansingtotem"] = "Poison Cleansing Totem"
DPSMate.L["threatdoneby"] = "Threat done by "
DPSMate.L["periodic"] = "(Periodic)"
DPSMate.L["reportchannel"] = {[1]="Whisper",[2]="Raid",[3]="Party",[4]="Say",[5]="Officer",[6]="Guild"}
DPSMate.L["raid"] = "Raid"
DPSMate.L["activity"] = "Activity: "
DPSMate.L["of"] = "of"
DPSMate.L["comparewith"] = "Compare with"
DPSMate.L["comparewithdesc"] = "Choose a player to compare this player to."
DPSMate.L["targetscale"] = "Target e-frame scale"
DPSMate.L["targetscaleTooltip"] = "Change the scale of the evaluation frames, to fit it better to your tastes."
DPSMate.L["updateinterval"] = "Display refresh rate"
DPSMate.L["updateintervalTooltip"] = "How often (in seconds) the display bars and timer refresh. Lower values are smoother but use more CPU."
DPSMate.L["autowipe"] = "Auto-wipe (logins)"
DPSMate.L["autowipeTooltip"] = "Automatically wipe all saved data every N logins. Set to 0 to disable. Example: 7 wipes once per week for daily players."
DPSMate.L["eddsum"] = "Enemy damage done summary"
DPSMate.L["edtsum"] = "Enemy damage taken summary"
DPSMate.L["ehpssum"] = "Effective healing summary"
DPSMate.L["tehealing"] = "effective healing"
DPSMate.L["hpssum"] = "Healing summary"
DPSMate.L["thealing"] = "healing"
DPSMate.L["ohpssum"] = "Overhealing summary"
DPSMate.L["tohealing"] = " overhealing"
DPSMate.L["tehealingtaken"] = "effective healing taken"
DPSMate.L["ehpstsum"] = "Effective healing taken summary"
DPSMate.L["thealingtaken"] = "healing taken"
DPSMate.L["hpstsum"] = "Healing taken summary"
DPSMate.L["tohealingtaken"] = "overhealing taken"
DPSMate.L["ohpstsum"] = "Overhealing taken summary"
DPSMate.L["habsum"] = "Healing and Absorbs summary"
DPSMate.L["threatdone"] = "threat done"
DPSMate.L["threatsum"] = "Threat done summary"
DPSMate.L["ffsum"] = "Friendly fire summary"
DPSMate.L["fftsum"] = "Friendly fire taken summary"
DPSMate.L["over"] = "Over"
DPSMate.L["lastability"] = "Last three hits"
DPSMate.L["deathssum"] = "Deaths summary"
DPSMate.L["victim"] = "Victim"
DPSMate.L["deathhistory"] = "death history"
DPSMate.L["intersum"] = "Interrupts summary"
DPSMate.L["dispelssum"] = "Dispels summary"
DPSMate.L["dispels"] = "Dispels"
DPSMate.L["decursessum"] = "Decurses summary"
DPSMate.L["liftmagicsum"] = "Lift magic summary"
DPSMate.L["curediseasesum"] = "Cure disease summary"
DPSMate.L["curepoisonsum"] = "Cure poison summary"
DPSMate.L["ccbreakersum"] = "CCBreaker summary"
DPSMate.L["failssum"] = "Fails summary"
DPSMate.L["AutoAttack"] = "AutoAttack"
DPSMate.L["AutoShot"] = "Auto Shot"
DPSMate.L["castssum"] = "Casts summary"
DPSMate.L["procssum"] = "Procs summary"
DPSMate.L["aurassum"] = "Auras summary"
DPSMate.L["absorbssum"] = "Absorbs summary"
DPSMate.L["absorbeddmg"] = "absorbs"
DPSMate.L["absorbstakensum"] = "Absorbs taken summary"
DPSMate.L["activity"] = "Activity"
DPSMate.L["cbtdisplay"] = "Disable CBT-Display"
DPSMate.L["disablebarbg"] = "Disable background"
DPSMate.L["disablebarbgtooltip"] = "Disable the background of each incomplete bar."
DPSMate.L["totalbaropacity"] = "Totalbar opacity"
DPSMate.L["totalbaropacitytooltip"] = "Slide to change the opacity of the total bar."
DPSMate.L["abortvote"] = "Abort reset. As assist or leader you are able to abort the vote, if you are quick enough."
DPSMate.L["resetaborted"] = "The reset vote has been aborted. There is a 20 seconds cooldown on reset now."
DPSMate.L["vreset"] = "Reset"
DPSMate.L["vdreset"] = "Don't Reset"
DPSMate.L["togglereportframe"] = "Toggle report frame"
DPSMate.L["toggleframes"] = "Toggle frames"
DPSMate.L["resetdpsmate"] = "Reset DPSMate"
DPSMate.L["columnstooltip"] = "Check this to show this extra information in this mode."
DPSMate.L["commas"] = "Commas"
DPSMate.L["versionisold"] = "Your version of DPSMate is old. Please update! DPSMate will only synchronize with actual versions."
DPSMate.L["rezz"] = "Resurrections"
DPSMate.L["rezzof"] = "Resurrections of "
DPSMate.L["rezzsum"] = "Ressurection summary"
DPSMate.L["activity"] = "Activity"
DPSMate.L["cbtdisplay"] = "Disable CBT-Display"
DPSMate.L["semicondensed"] = "Semi-Condensed"
DPSMate.L["loginhide"] = "Hide on login"
DPSMate.L["borderOpacityTooltip"] = "Adjust the border opacity."
DPSMate.L["borderOpacity"] = "Border opacity"
DPSMate.L["bordertextureTooltip"] = "Select the border texture."
DPSMate.L["bordertexture"] = "Border texture"
DPSMate.L["borderstrataTooltip"] = "Select the border strata. This pushes the border further into the back- or foreground."
DPSMate.L["borderstrata"] = "Border strata"
DPSMate.L["bordercolor"] = "Border color"
DPSMate.L["bordercolorTooltip"] = "Adjust the border color."
DPSMate.L["reportdelaytooltip"] = "Add a delay to prevent chat mutes on some servers."
DPSMate.L["delay"] = "Delay"
-- Newly added:
DPSMate.L["tttop"] = "Top "
DPSMate.L["ttdamage"] = " Damage"
DPSMate.L["tthealing"] = " Healing"
DPSMate.L["ttpet"] = " Pet"
DPSMate.L["ttpet2"] = "Pet: "
DPSMate.L["ttabilities"] = " Abilities"
DPSMate.L["ttattacked"] = " Attacked"
DPSMate.L["tthealed"] = " Healed"
DPSMate.L["ttinterrupt"] = " Interrupt"
DPSMate.L["ttinterrupted"] = " Interrupted"
DPSMate.L["ttdispelled"] = " Dispelled"
DPSMate.L["ttabsorbed"] = " Absorbed"
DPSMate.L["ttabsorb"] = " Absorb"
DPSMate.L["ttthreat"] = " Threat"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,841 @@
--[[
Name: AceLibrary
Revision: $Rev: 14130 $
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
Inspired By: Iriel (iriel@vigilance-committee.org)
Tekkub (tekkub@gmail.com)
Revision: $Rev: 14130 $
Website: http://www.wowace.com/
Documentation: http://www.wowace.com/index.php/AceLibrary
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary
Description: Versioning library to handle other library instances, upgrading,
and proper access.
It also provides a base for libraries to work off of, providing
proper error tools. It is handy because all the errors occur in the
file that called it, not in the library file itself.
Dependencies: None
]]
local ACELIBRARY_MAJOR = "AceLibrary"
local ACELIBRARY_MINOR = "$Revision: 99130 $"
local table_setn
do
local version = GetBuildInfo()
if string.find(version, "^2%.") then
-- 2.0.0
table_setn = function() end
else
table_setn = table.setn
end
end
local string_gfind = string.gmatch or string.gfind
local _G = getfenv(0)
local previous = _G[ACELIBRARY_MAJOR]
local tmp
if previous then
previous.error = function(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
if type(self) ~= "table" then
_G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2)
end
if not tmp then
tmp = {}
else
for k in pairs(tmp) do tmp[k] = nil end
table_setn(tmp, 0)
end
table.insert(tmp, a1)
table.insert(tmp, a2)
table.insert(tmp, a3)
table.insert(tmp, a4)
table.insert(tmp, a5)
table.insert(tmp, a6)
table.insert(tmp, a7)
table.insert(tmp, a8)
table.insert(tmp, a9)
table.insert(tmp, a10)
table.insert(tmp, a11)
table.insert(tmp, a12)
table.insert(tmp, a13)
table.insert(tmp, a14)
table.insert(tmp, a15)
table.insert(tmp, a16)
table.insert(tmp, a17)
table.insert(tmp, a18)
table.insert(tmp, a19)
table.insert(tmp, a20)
local stack = debugstack()
if not message then
local _,_,second = string.find(stack, "\n(.-)\n")
message = "error raised! " .. second
else
for i = 1,table.getn(tmp) do
tmp[i] = tostring(tmp[i])
end
for i = 1,10 do
table.insert(tmp, "nil")
end
message = string.format(message, unpack(tmp))
end
if getmetatable(self) and getmetatable(self).__tostring then
message = string.format("%s: %s", tostring(self), message)
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
message = string.format("%s: %s", self:GetLibraryVersion(), message)
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
message = string.format("%s: %s", self.class:GetLibraryVersion(), message)
end
if not string.find(message, "Babble%-Spell") then
return
end
local first = string.gsub(stack, "\n.*", "")
local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1")
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
local i = 0
for s in string_gfind(stack, "\n([^\n]*)") do
i = i + 1
if not string.find(s, file .. "%.lua:%d+:") then
file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1")
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
break
end
end
local j = 0
for s in string_gfind(stack, "\n([^\n]*)") do
j = j + 1
if j > i and not string.find(s, file .. "%.lua:%d+:") then
_G.error(message, j + 1)
return
end
end
_G.error(message, 2)
return
end
end
if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end
-- @table AceLibrary
-- @brief System to handle all versioning of libraries.
local AceLibrary = {}
local AceLibrary_mt = {}
setmetatable(AceLibrary, AceLibrary_mt)
local tmp
local function error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
if type(self) ~= "table" then
_G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2)
end
if not tmp then
tmp = {}
else
for k in pairs(tmp) do tmp[k] = nil end
table_setn(tmp, 0)
end
table.insert(tmp, a1)
table.insert(tmp, a2)
table.insert(tmp, a3)
table.insert(tmp, a4)
table.insert(tmp, a5)
table.insert(tmp, a6)
table.insert(tmp, a7)
table.insert(tmp, a8)
table.insert(tmp, a9)
table.insert(tmp, a10)
table.insert(tmp, a11)
table.insert(tmp, a12)
table.insert(tmp, a13)
table.insert(tmp, a14)
table.insert(tmp, a15)
table.insert(tmp, a16)
table.insert(tmp, a17)
table.insert(tmp, a18)
table.insert(tmp, a19)
table.insert(tmp, a20)
local stack = debugstack()
if not message then
local _,_,second = string.find(stack, "\n(.-)\n")
message = "error raised! " .. second
else
for i = 1,table.getn(tmp) do
tmp[i] = tostring(tmp[i])
end
for i = 1,10 do
table.insert(tmp, "nil")
end
message = string.format(message, unpack(tmp))
end
if getmetatable(self) and getmetatable(self).__tostring then
message = string.format("%s: %s", tostring(self), message)
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
message = string.format("%s: %s", self:GetLibraryVersion(), message)
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
message = string.format("%s: %s", self.class:GetLibraryVersion(), message)
end
if not string.find(message, "Babble%-Spell") then
return
end
local first = string.gsub(stack, "\n.*", "")
local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1")
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
local i = 0
for s in string_gfind(stack, "\n([^\n]*)") do
i = i + 1
if not string.find(s, file .. "%.lua:%d+:") then
file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1")
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
break
end
end
local j = 0
for s in string_gfind(stack, "\n([^\n]*)") do
j = j + 1
if j > i and not string.find(s, file .. "%.lua:%d+:") then
_G.error(message, j + 1)
return
end
end
_G.error(message, 2)
return
end
local function assert(self, condition, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
if not condition then
if not message then
local stack = debugstack()
local _,_,second = string.find(stack, "\n(.-)\n")
message = "assertion failed! " .. second
end
error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
return
end
return condition
end
local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5)
if type(num) ~= "number" then
error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num))
elseif type(kind) ~= "string" then
error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind))
end
local errored = false
arg = type(arg)
if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then
local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])")
if not func then
_,_,func = string.find(debugstack(), "([`<].-['>])")
end
if kind5 then
error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg)
elseif kind4 then
error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg)
elseif kind3 then
error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg)
elseif kind2 then
error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg)
else
error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg)
end
end
end
local function pcall(self, func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = _G.pcall(func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
if not a1 then
error(self, string.gsub(a2, ".-%.lua:%d-: ", ""))
else
return a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
end
end
local recurse = {}
local function addToPositions(t, major)
if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then
rawset(t, recurse, true)
AceLibrary.positions[t] = major
for k,v in pairs(t) do
if type(v) == "table" and not rawget(v, recurse) then
addToPositions(v, major)
end
if type(k) == "table" and not rawget(k, recurse) then
addToPositions(k, major)
end
end
local mt = getmetatable(t)
if mt and not rawget(mt, recurse) then
addToPositions(mt, major)
end
rawset(t, recurse, nil)
end
end
local function svnRevisionToNumber(text)
if type(text) == "string" then
if string.find(text, "^%$Revision: (%d+) %$$") then
return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1")))
elseif string.find(text, "^%$Rev: (%d+) %$$") then
return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1")))
elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then
return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1")))
end
elseif type(text) == "number" then
return text
end
return nil
end
local crawlReplace
do
local recurse = {}
local function func(t, to, from)
if recurse[t] then
return
end
recurse[t] = true
local mt = getmetatable(t)
setmetatable(t, nil)
rawset(t, to, rawget(t, from))
rawset(t, from, nil)
for k,v in pairs(t) do
if v == from then
t[k] = to
elseif type(v) == "table" then
if not recurse[v] then
func(v, to, from)
end
end
if type(k) == "table" then
if not recurse[k] then
func(k, to, from)
end
end
end
setmetatable(t, mt)
if mt then
if mt == from then
setmetatable(t, to)
elseif not recurse[mt] then
func(mt, to, from)
end
end
end
function crawlReplace(t, to, from)
func(t, to, from)
for k in pairs(recurse) do
recurse[k] = nil
end
end
end
-- @function destroyTable
-- @brief remove all the contents of a table
-- @param t table to destroy
local function destroyTable(t)
setmetatable(t, nil)
for k,v in pairs(t) do t[k] = nil end
table_setn(t, 0)
end
local function isFrame(frame)
return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function"
end
local new, del
do
local tables = setmetatable({}, {__mode = "k"})
function new()
local t = next(tables)
if t then
tables[t] = nil
return t
else
return {}
end
end
function del(t, depth)
if depth and depth > 0 then
for k,v in pairs(t) do
if type(v) == "table" and not isFrame(v) then
del(v, depth - 1)
end
end
end
destroyTable(t)
tables[t] = true
end
end
-- @function copyTable
-- @brief Create a shallow copy of a table and return it.
-- @param from The table to copy from
-- @return A shallow copy of the table
local function copyTable(from)
local to = new()
for k,v in pairs(from) do to[k] = v end
table_setn(to, table.getn(from))
setmetatable(to, getmetatable(from))
return to
end
-- @function deepTransfer
-- @brief Fully transfer all data, keeping proper previous table
-- backreferences stable.
-- @param to The table with which data is to be injected into
-- @param from The table whose data will be injected into the first
-- @param saveFields If available, a shallow copy of the basic data is saved
-- in here.
-- @param list The account of table references
-- @param list2 The current status on which tables have been traversed.
local deepTransfer
do
-- @function examine
-- @brief Take account of all the table references to be shared
-- between the to and from tables.
-- @param to The table with which data is to be injected into
-- @param from The table whose data will be injected into the first
-- @param list An account of the table references
local function examine(to, from, list, major)
list[from] = to
for k,v in pairs(from) do
if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then
if from[k] == to[k] then
list[from[k]] = to[k]
elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then
list[from[k]] = from[k]
elseif not list[from[k]] then
examine(to[k], from[k], list, major)
end
end
end
return list
end
function deepTransfer(to, from, saveFields, major, list, list2)
setmetatable(to, nil)
local createdList
if not list then
createdList = true
list = new()
list2 = new()
examine(to, from, list, major)
end
list2[to] = to
for k,v in pairs(to) do
if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then
if saveFields then
saveFields[k] = v
end
to[k] = nil
elseif v ~= _G then
if saveFields then
saveFields[k] = copyTable(v)
end
end
end
for k in pairs(from) do
if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then
if not list2[to[k]] then
deepTransfer(to[k], from[k], nil, major, list, list2)
end
to[k] = list[to[k]] or list2[to[k]]
else
rawset(to, k, from[k])
end
end
table_setn(to, table.getn(from))
setmetatable(to, getmetatable(from))
local mt = getmetatable(to)
if mt then
if list[mt] then
setmetatable(to, list[mt])
elseif mt.__index and list[mt.__index] then
mt.__index = list[mt.__index]
end
end
destroyTable(from)
if createdList then
del(list)
del(list2)
end
end
end
-- @method TryToLoadStandalone
-- @brief Attempt to find and load a standalone version of the requested library
-- @param major A string representing the major version
-- @return If library is found, return values from the call to LoadAddOn are returned
-- If the library has been requested previously, nil is returned.
local function TryToLoadStandalone(major)
if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end
if AceLibrary.scannedlibs[major] then return end
AceLibrary.scannedlibs[major] = true
local name, _, _, enabled, loadable = GetAddOnInfo(major)
if loadable then
return LoadAddOn(name)
end
for i=1,GetNumAddOns() do
if GetAddOnMetadata(i, "X-AceLibrary-"..major) then
local name, _, _, enabled, loadable = GetAddOnInfo(i)
if loadable then
return LoadAddOn(name)
end
end
end
end
-- @method IsNewVersion
-- @brief Obtain whether the supplied version would be an upgrade to the
-- current version. This allows for bypass code in library
-- declaration.
-- @param major A string representing the major version
-- @param minor An integer or an svn revision string representing the minor version
-- @return whether the supplied version would be newer than what is
-- currently available.
function AceLibrary:IsNewVersion(major, minor)
argCheck(self, major, 2, "string")
TryToLoadStandalone(major)
if type(minor) == "string" then
local m = svnRevisionToNumber(minor)
if m then
minor = m
else
_G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
end
end
argCheck(self, minor, 3, "number")
local data = self.libs[major]
if not data then
return true
end
return data.minor < minor
end
-- @method HasInstance
-- @brief Returns whether an instance exists. This allows for optional support of a library.
-- @param major A string representing the major version.
-- @param minor (optional) An integer or an svn revision string representing the minor version.
-- @return Whether an instance exists.
function AceLibrary:HasInstance(major, minor)
argCheck(self, major, 2, "string")
TryToLoadStandalone(major)
if minor then
if type(minor) == "string" then
local m = svnRevisionToNumber(minor)
if m then
minor = m
else
_G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
end
end
argCheck(self, minor, 3, "number")
if not self.libs[major] then
return
end
return self.libs[major].minor == minor
end
return self.libs[major] and true
end
-- @method GetInstance
-- @brief Returns the library with the given major/minor version.
-- @param major A string representing the major version.
-- @param minor (optional) An integer or an svn revision string representing the minor version.
-- @return The library with the given major/minor version.
function AceLibrary:GetInstance(major, minor)
argCheck(self, major, 2, "string")
TryToLoadStandalone(major)
local data = self.libs[major]
if not data then
_G.error(string.format("Cannot find a library instance of %s.", major), 2)
return
end
if minor then
if type(minor) == "string" then
local m = svnRevisionToNumber(minor)
if m then
minor = m
else
_G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
end
end
argCheck(self, minor, 2, "number")
if data.minor ~= minor then
_G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2)
return
end
end
return data.instance
end
-- Syntax sugar. AceLibrary("FooBar-1.0")
AceLibrary_mt.__call = AceLibrary.GetInstance
local donothing
local AceEvent
-- @method Register
-- @brief Registers a new version of a given library.
-- @param newInstance the library to register
-- @param major the major version of the library
-- @param minor the minor version of the library
-- @param activateFunc (optional) A function to be called when the library is
-- fully activated. Takes the arguments
-- (newInstance [, oldInstance, oldDeactivateFunc]). If
-- oldInstance is given, you should probably call
-- oldDeactivateFunc(oldInstance).
-- @param deactivateFunc (optional) A function to be called by a newer library's
-- activateFunc.
-- @param externalFunc (optional) A function to be called whenever a new
-- library is registered.
function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc)
argCheck(self, newInstance, 2, "table")
argCheck(self, major, 3, "string")
if type(minor) == "string" then
local m = svnRevisionToNumber(minor)
if m then
minor = m
else
_G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
end
end
argCheck(self, minor, 4, "number")
if math.floor(minor) ~= minor or minor < 0 then
error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor)
end
argCheck(self, activateFunc, 5, "function", "nil")
argCheck(self, deactivateFunc, 6, "function", "nil")
argCheck(self, externalFunc, 7, "function", "nil")
if not deactivateFunc then
if not donothing then
donothing = function() end
end
deactivateFunc = donothing
end
local data = self.libs[major]
if not data then
-- This is new
local instance = copyTable(newInstance)
crawlReplace(instance, instance, newInstance)
destroyTable(newInstance)
if AceLibrary == newInstance then
self = instance
AceLibrary = instance
end
self.libs[major] = {
instance = instance,
minor = minor,
deactivateFunc = deactivateFunc,
externalFunc = externalFunc,
}
rawset(instance, 'GetLibraryVersion', function(self)
return major, minor
end)
if not rawget(instance, 'error') then
rawset(instance, 'error', error)
end
if not rawget(instance, 'assert') then
rawset(instance, 'assert', assert)
end
if not rawget(instance, 'argCheck') then
rawset(instance, 'argCheck', argCheck)
end
if not rawget(instance, 'pcall') then
rawset(instance, 'pcall', pcall)
end
addToPositions(instance, major)
if activateFunc then
activateFunc(instance, nil, nil) -- no old version, so explicit nil
end
if externalFunc then
for k,data in pairs(self.libs) do
if k ~= major then
externalFunc(instance, k, data.instance)
end
end
end
for k,data in pairs(self.libs) do
if k ~= major and data.externalFunc then
data.externalFunc(data.instance, major, instance)
end
end
if major == "AceEvent-2.0" then
AceEvent = instance
end
if AceEvent then
AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance)
end
return instance
end
local instance = data.instance
if minor <= data.minor then
-- This one is already obsolete, raise an error.
_G.error(string.format("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end", major, data.minor, minor, major, minor), 2)
return
end
-- This is an update
local oldInstance = new()
addToPositions(newInstance, major)
local isAceLibrary = (AceLibrary == newInstance)
local old_error, old_assert, old_argCheck, old_pcall
if isAceLibrary then
self = instance
AceLibrary = instance
old_error = instance.error
old_assert = instance.assert
old_argCheck = instance.argCheck
old_pcall = instance.pcall
self.error = error
self.assert = assert
self.argCheck = argCheck
self.pcall = pcall
end
deepTransfer(instance, newInstance, oldInstance, major)
crawlReplace(instance, instance, newInstance)
local oldDeactivateFunc = data.deactivateFunc
data.minor = minor
data.deactivateFunc = deactivateFunc
data.externalFunc = externalFunc
rawset(instance, 'GetLibraryVersion', function(self)
return major, minor
end)
if not rawget(instance, 'error') then
rawset(instance, 'error', error)
end
if not rawget(instance, 'assert') then
rawset(instance, 'assert', assert)
end
if not rawget(instance, 'argCheck') then
rawset(instance, 'argCheck', argCheck)
end
if not rawget(instance, 'pcall') then
rawset(instance, 'pcall', pcall)
end
if isAceLibrary then
for _,v in pairs(self.libs) do
local i = type(v) == "table" and v.instance
if type(i) == "table" then
if not rawget(i, 'error') or i.error == old_error then
rawset(i, 'error', error)
end
if not rawget(i, 'assert') or i.assert == old_assert then
rawset(i, 'assert', assert)
end
if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then
rawset(i, 'argCheck', argCheck)
end
if not rawget(i, 'pcall') or i.pcall == old_pcall then
rawset(i, 'pcall', pcall)
end
end
end
end
if activateFunc then
activateFunc(instance, oldInstance, oldDeactivateFunc)
else
oldDeactivateFunc(oldInstance)
end
del(oldInstance)
if externalFunc then
for k,data in pairs(self.libs) do
if k ~= major then
externalFunc(instance, k, data.instance)
end
end
end
return instance
end
local iter
function AceLibrary:IterateLibraries()
if not iter then
local function iter(t, k)
k = next(t, k)
if not k then
return nil
else
return k, t[k].instance
end
end
end
return iter, self.libs, nil
end
-- @function Activate
-- @brief The activateFunc for AceLibrary itself. Called when
-- AceLibrary properly registers.
-- @param self Reference to AceLibrary
-- @param oldLib (optional) Reference to an old version of AceLibrary
-- @param oldDeactivate (optional) Function to deactivate the old lib
local function activate(self, oldLib, oldDeactivate)
if not self.libs then
if oldLib then
self.libs = oldLib.libs
self.scannedlibs = oldLib.scannedlibs
end
if not self.libs then
self.libs = {}
end
if not self.scannedlibs then
self.scannedlibs = {}
end
end
if not self.positions then
if oldLib then
self.positions = oldLib.positions
end
if not self.positions then
self.positions = setmetatable({}, { __mode = "k" })
end
end
-- Expose the library in the global environment
_G[ACELIBRARY_MAJOR] = self
if oldDeactivate then
oldDeactivate(oldLib)
end
end
if not previous then
previous = AceLibrary
end
if not previous.libs then
previous.libs = {}
end
AceLibrary.libs = previous.libs
if not previous.positions then
previous.positions = setmetatable({}, { __mode = "k" })
end
AceLibrary.positions = previous.positions
AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate)
@@ -0,0 +1,465 @@
--
-- ChatThrottleLib by Mikk
--
-- Manages AddOn chat output to keep player from getting kicked off.
--
-- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
--
-- Priorities get an equal share of available bandwidth when fully loaded.
-- Communication channels are separated on extension+chattype+destination and
-- get round-robinned. (Destination only matters for whispers and channels,
-- obviously)
--
-- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure
-- bandwidth bypassing the library and use less bandwidth itself.
--
--
-- Fully embeddable library. Just copy this file into your addon directory,
-- add it to the .toc, and it's done.
--
-- Can run as a standalone addon also, but, really, just embed it! :-)
--
local CTL_VERSION = 13
local MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
local MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
local BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
local MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
if(ChatThrottleLib and ChatThrottleLib.version>=CTL_VERSION) then
-- There's already a newer (or same) version loaded. Buh-bye.
return;
end
if(not ChatThrottleLib) then
ChatThrottleLib = {}
end
local ChatThrottleLib = ChatThrottleLib
local strlen = strlen
local setmetatable = setmetatable
local getn = getn
local tremove = tremove
local tinsert = tinsert
local tostring = tostring
local GetTime = GetTime
local format = format
ChatThrottleLib.version=CTL_VERSION;
-----------------------------------------------------------------------
-- Double-linked ring implementation
local Ring = {}
local RingMeta = { __index=Ring }
function Ring:New()
local ret = {}
setmetatable(ret, RingMeta)
return ret;
end
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if(self.pos) then
obj.prev = self.pos.prev;
obj.prev.next = obj;
obj.next = self.pos;
obj.next.prev = obj;
else
obj.next = obj;
obj.prev = obj;
self.pos = obj;
end
end
function Ring:Remove(obj)
obj.next.prev = obj.prev;
obj.prev.next = obj.next;
if(self.pos == obj) then
self.pos = obj.next;
if(self.pos == obj) then
self.pos = nil;
end
end
end
-----------------------------------------------------------------------
-- Recycling bin for pipes (kept in a linked list because that's
-- how they're worked with in the rotating rings; just reusing members)
ChatThrottleLib.PipeBin = { count=0 }
function ChatThrottleLib.PipeBin:Put(pipe)
for i=getn(pipe),1,-1 do
tremove(pipe, i);
end
pipe.prev = nil;
pipe.next = self.list;
self.list = pipe;
self.count = self.count+1;
end
function ChatThrottleLib.PipeBin:Get()
if(self.list) then
local ret = self.list;
self.list = ret.next;
ret.next=nil;
self.count = self.count - 1;
return ret;
end
return {};
end
function ChatThrottleLib.PipeBin:Tidy()
if(self.count < 25) then
return;
end
local n
if(self.count > 100) then
n=self.count-90;
else
n=10;
end
for i=2,n do
self.list = self.list.next;
end
local delme = self.list;
self.list = self.list.next;
delme.next = nil;
end
-----------------------------------------------------------------------
-- Recycling bin for messages
ChatThrottleLib.MsgBin = {}
function ChatThrottleLib.MsgBin:Put(msg)
msg.text = nil;
tinsert(self, msg);
end
function ChatThrottleLib.MsgBin:Get()
local ret = tremove(self, getn(self));
if(ret) then return ret; end
return {};
end
function ChatThrottleLib.MsgBin:Tidy()
if(getn(self)<50) then
return;
end
if(getn(self)>150) then -- "can't happen" but ...
for n=getn(self),120,-1 do
tremove(self,n);
end
else
for n=getn(self),getn(self)-20,-1 do
tremove(self,n);
end
end
end
-----------------------------------------------------------------------
-- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc
function ChatThrottleLib:Init()
-- Set up queues
if(not self.Prio) then
self.Prio = {}
self.Prio["ALERT"] = { ByName={}, Ring = Ring:New(), avail=0 };
self.Prio["NORMAL"] = { ByName={}, Ring = Ring:New(), avail=0 };
self.Prio["BULK"] = { ByName={}, Ring = Ring:New(), avail=0 };
end
-- v4: total send counters per priority
for _,Prio in pairs(self.Prio) do
Prio.nTotalSent = Prio.nTotalSent or 0;
end
self.avail = self.avail or 0; -- v5
self.nTotalSent = self.nTotalSent or 0; -- v5
-- Set up a frame to get OnUpdate events
if(not self.Frame) then
self.Frame = CreateFrame("Frame");
self.Frame:Hide();
end
self.Frame.Show = self.Frame.Show; -- cache for speed
self.Frame.Hide = self.Frame.Hide; -- cache for speed
self.Frame:SetScript("OnUpdate", self.OnUpdate);
self.Frame:SetScript("OnEvent", self.OnEvent); -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
self.OnUpdateDelay=0;
self.LastAvailUpdate=GetTime();
self.HardThrottlingBeginTime=GetTime(); -- v11: Throttle hard for a few seconds after startup
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if(not self.ORIG_SendChatMessage) then
--SendChatMessage
self.ORIG_SendChatMessage = SendChatMessage;
SendChatMessage = function(a1,a2,a3,a4) return ChatThrottleLib.Hook_SendChatMessage(a1,a2,a3,a4); end
--SendAdd[Oo]nMessage
if(SendAddonMessage or SendAddOnMessage) then -- v10: don't pretend like it doesn't exist if it doesn't!
self.ORIG_SendAddonMessage = SendAddonMessage or SendAddOnMessage;
SendAddonMessage = function(a1,a2,a3) return ChatThrottleLib.Hook_SendAddonMessage(a1,a2,a3); end
if(SendAddOnMessage) then -- in case Slouken changes his mind...
SendAddOnMessage = SendAddonMessage;
end
end
end
self.nBypass = 0;
end
-----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
local self = ChatThrottleLib;
local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(destination or "")) + 40;
self.avail = self.avail - size;
self.nBypass = self.nBypass + size;
return self.ORIG_SendChatMessage(text, chattype, language, destination);
end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype)
local self = ChatThrottleLib;
local size = strlen(tostring(text or "")) + strlen(tostring(chattype or "")) + strlen(tostring(prefix or "")) + 40;
self.avail = self.avail - size;
self.nBypass = self.nBypass + size;
return self.ORIG_SendAddonMessage(prefix, text, chattype);
end
-----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available
function ChatThrottleLib:UpdateAvail()
local now = GetTime();
local newavail = MAX_CPS * (now-self.LastAvailUpdate);
if(now - self.HardThrottlingBeginTime < 5) then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
self.avail = min(self.avail + (newavail*0.1), MAX_CPS*0.5);
elseif(GetFramerate()<MIN_FPS) then -- GetFrameRate call takes ~0.002 secs
newavail = newavail * 0.5;
self.avail = min(MAX_CPS, self.avail + newavail);
self.bChoking = true; -- just for stats
else
self.avail = min(BURST, self.avail + newavail);
self.bChoking = false;
end
self.avail = max(self.avail, 0-(MAX_CPS*2)); -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
self.LastAvailUpdate = now;
return self.avail;
end
-----------------------------------------------------------------------
-- Despooling logic
function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring;
while(ring.pos and Prio.avail>ring.pos[1].nSize) do
local msg = tremove(Prio.Ring.pos, 1);
if(not Prio.Ring.pos[1]) then
local pipe = Prio.Ring.pos;
Prio.Ring:Remove(pipe);
Prio.ByName[pipe.name] = nil;
self.PipeBin:Put(pipe);
else
Prio.Ring.pos = Prio.Ring.pos.next;
end
Prio.avail = Prio.avail - msg.nSize;
msg.f(msg[1], msg[2], msg[3], msg[4]);
Prio.nTotalSent = Prio.nTotalSent + msg.nSize;
self.MsgBin:Put(msg);
end
end
function ChatThrottleLib.OnEvent()
-- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too.
self = ChatThrottleLib;
if(event == "PLAYER_ENTERING_WORLD") then
self.HardThrottlingBeginTime=GetTime(); -- Throttle hard for a few seconds after zoning
self.avail = 0;
end
end
function ChatThrottleLib.OnUpdate()
self = ChatThrottleLib;
self.OnUpdateDelay = self.OnUpdateDelay + arg1;
if(self.OnUpdateDelay < 0.08) then
return;
end
self.OnUpdateDelay = 0;
self:UpdateAvail();
if(self.avail<0) then
return; -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
end
-- See how many of or priorities have queued messages
local n=0;
for prioname,Prio in pairs(self.Prio) do
if(Prio.Ring.pos or Prio.avail<0) then
n=n+1;
end
end
-- Anything queued still?
if(n<1) then
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
for prioname,Prio in pairs(self.Prio) do
self.avail = self.avail + Prio.avail;
Prio.avail = 0;
end
self.bQueueing = false;
self.Frame:Hide();
return;
end
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
local avail= self.avail/n;
self.avail = 0;
for prioname,Prio in pairs(self.Prio) do
if(Prio.Ring.pos or Prio.avail<0) then
Prio.avail = Prio.avail + avail;
if(Prio.Ring.pos and Prio.avail>Prio.Ring.pos[1].nSize) then
self:Despool(Prio);
end
end
end
-- Expire recycled tables if needed
self.MsgBin:Tidy();
self.PipeBin:Tidy();
end
-----------------------------------------------------------------------
-- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname];
local pipe = Prio.ByName[pipename];
if(not pipe) then
self.Frame:Show();
pipe = self.PipeBin:Get();
pipe.name = pipename;
Prio.ByName[pipename] = pipe;
Prio.Ring:Add(pipe);
end
tinsert(pipe, msg);
self.bQueueing = true;
end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination)
if(not (self and prio and text and self.Prio[prio] ) ) then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2);
end
prefix = prefix or tostring(this); -- each frame gets its own queue if prefix is not given
local nSize = strlen(text) + MSG_OVERHEAD;
-- Check if there's room in the global available bandwidth gauge to send directly
if(not self.bQueueing and nSize < self:UpdateAvail()) then
self.avail = self.avail - nSize;
self.ORIG_SendChatMessage(text, chattype, language, destination);
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize;
return;
end
-- Message needs to be queued
msg=self.MsgBin:Get();
msg.f=self.ORIG_SendChatMessage
msg[1]=text;
msg[2]=chattype or "SAY";
msg[3]=language;
msg[4]=destination;
msg.n = 4
msg.nSize = nSize;
self:Enqueue(prio, format("%s/%s/%s", prefix, chattype, destination or ""), msg);
end
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype)
if(not (self and prio and prefix and text and chattype and self.Prio[prio] ) ) then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype")', 0);
end
local nSize = strlen(prefix) + 1 + strlen(text) + MSG_OVERHEAD;
-- Check if there's room in the global available bandwidth gauge to send directly
if(not self.bQueueing and nSize < self:UpdateAvail()) then
self.avail = self.avail - nSize;
self.ORIG_SendAddonMessage(prefix, text, chattype);
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize;
return;
end
-- Message needs to be queued
msg=self.MsgBin:Get();
msg.f=self.ORIG_SendAddonMessage;
msg[1]=prefix;
msg[2]=text;
msg[3]=chattype;
msg.n = 3
msg.nSize = nSize;
self:Enqueue(prio, format("%s/%s", prefix, chattype), msg);
end
-----------------------------------------------------------------------
-- Get the ball rolling!
ChatThrottleLib:Init();
--[[ WoWBench debugging snippet
if(WOWB_VER) then
local function SayTimer()
print("SAY: "..GetTime().." "..arg1);
end
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer);
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY");
end
]]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,14 @@
## Interface: 20003
## LoadOnDemand: 1
## Title: Lib: GraphLib
## Version: 1.0
## Notes: A library allowing for easy creation of graphs
## Author: Cryect
## X-Category: Library
## X-AceLibrary-Graph-1.0: true
## OptionalDeps: Ace2
## X-Embeds: Ace2
AceLibrary\AceLibrary.lua
Graph-1.0\Graph-1.0.lua
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,446 @@
--[[
Name: Babble-Boss-2.2
Revision: $Rev: 17545 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Babble-Boss-2.2
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Boss-2.2
Description: A library to provide localizations for bosses.
Dependencies: AceLibrary, AceLocale-2.2
Rewritten a little and added some "bosses" by Shino
]]
if (GetLocale()=="deDE") then
local bosses = {
["Feueranbeter"] = true,
["Avalanchion"] = true,
["Der Windpl\195\188nderer"] = true,
["Baron Charr"] = true,
["Prinzessin Tempestria"] = true,
["Grethok der Aufseher"] = true,
["Flickwerk"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Thaddius"] = true,
["Feugen"] = true,
["Stalagg"] = true,
["Anub'Rekhan"] = true,
["Großwitwe Faerlina"] = true,
["Maexxna"] = true,
["Instrukteur Razuvious"] = true,
["Reservist der Todesritter"] = true,
["Gothik der Seelenjäger"] = true,
["Hochlord Mograine"] = true,
["Thane Korth'azz"] = true,
["Lady Blaumeux"] = true,
["Sire Zeliek"] = true,
["Die Vier Reiter"]= true,
["Noth der Seuchenfürst"] = true,
["Heigan der Unreine"] = true,
["Loatheb"] = true,
["Saphiron"] = true,
["Kel'Thuzad"] = true,
["Lord Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz der Verdorbene"] = true,
["Razorgore der Ungezähmte"] = true,
["Brutwächter Dreschbringer"] = true,
["Chromaggus"] = true,
["Schattenschwinge"] = true,
["Feuerschwinge"] = true,
["Flammenmaul"] = true,
["Majordomus Exekutus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg der Verbrenner"] = true,
["Garr"] = true,
["Sulfuronherold"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Smariss"] = true,
["Taerar"] = true,
["Lethon"] = true,
["Jin'do der Verhexer"] = true,
["Blutfürst Mandokir"] = true,
["Hakkar"] = true,
["Lord Kazzak"] = true,
["Ysondre"] = true,
["Hohepriesterin Jeklik"] = true,
["Hohepriester Venoxis"] = true,
["Hohepriester Thekal"] = true,
["Hohepriesterin Arlokk"] = true,
["Hohepriesterin Mar'li"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Ayamiss der Jäger"] = true,
["Buru der Verschlinger"] = true,
["General Rajaxx"] = true,
["Generallieutenant Andorov"] = true,
["Moam"] = true,
["Beschützer des Anubisath"] = true,
["Ossirian der Narbenlose"] = true,
["Lord Kri"] = true,
["Prinzessin Yauj"] = true,
["Vem"] = true,
["Die Käferfamilie"] = true,
["Auge von C'Thun"] = true,
["C'Thun"] = true,
["Verteidiger des Anubisath"] = true,
["Fankriss der Unnachgiebige"] = true,
["Prinzessin Huhuran"] = true,
["Ouro"] = true,
["Schlachtwache Sartura"] = true,
["Der Prophet Skeram"] = true,
["Imperator Vek'lor"] = true,
["Imperator Vek'nilash"] = true,
["Die Zwillings-Imperatoren"] = true,
["Viscidus"] = true,
["Alzzin der Wildformer"] = true,
["Botschafter Flamelash"] = true,
["Anger'rel"] = true,
["Archivar Galford"] = true,
["Atal'alarion"] = true,
["Avatar von Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baroness Anastari"] = true,
["Baron Rivendare"] = true,
["Captain Kromcrush"] = true,
["Celebras der Verfluchte"] = true,
["Kristallfangzahn"] = true,
["Dunkelmeister Gandling"] = true,
["Doktor Theolen Krastinov"] = true,
["Un'rel"] = true,
["Trott'rel"] = true,
["Traumsense"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["General Angerforge"] = true,
["General Drakkisath"] = true,
["Dunk'rel"] = true,
["Golemlord Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Hass'rel"] = true,
["Hazzas"] = true,
["Herdsinger Forresten"] = true,
["Hochlord Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrobrut"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instrukteurin Malicia"] = true,
["Jammal'an der Prophet"] = true,
["Jandice Barov"] = true,
["Kirtonos der Herold"] = true,
["Lady Illucia Barov"] = true,
["Erdrutsch"] = true,
["Lethtendris"] = true,
["Hüter des Wissens Polkelt"] = true,
["Loro"] = true,
["Magister Kalendris"] = true,
["Magistrat Barthilas"] = true,
["Magmus"] = true,
["Maleki der Leichenblasse"] = true,
["Marduk Blackpool"] = true,
["Meshlok der Ernter"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Mutter Glimmernetz"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom der Elende"] = true,
["Oberanführer Wyrmthalak"] = true,
["Phalanx"] = true,
["Plugger Spazzring"] = true,
["Postmeister Malown"] = true,
["Prinzessin Moira Bronzebeard"] = true,
["Prinzessin Theradras"] = true,
["Prinz Tortheldrin"] = true,
["Pusillin"] = true,
["Feuerwache Glutseher"] = true,
["Ramstein der Verschlinger"] = true,
["Blutrippe"] = true,
["Schlingwurzler"] = true,
["Ribbly Screwspigot"] = true,
["Faulschnapper"] = true,
["Wut'rel"] = true,
["Eranikus' Schemen"] = true,
["Solakar Feuerkrone"] = true,
["Stampfer Kreeg"] = true,
["Tendris Wucherborke"] = true,
["Timmy der Grausame"] = true,
["Tüftler Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Bös'rel"] = true,
["Wirker"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
["Kanonenmeister Willey"] = true,
["Imperator Dagran Thaurissan"] = true,
["Wache Fengus"] = true,
["Wache Mol'dar"] = true,
["Wache Slip'kik"] = true,
["Verhörmeisterin Gerstahn"] = true,
["König Gordok"] = true,
["Lord Alexei Barov"] = true,
["Lord Incendius"] = true,
["Lord Schlangenzunge"] = true,
["Ras Frostraunen"] = true,
["Kriegshäuptling Rend Blackhand"] = true,
["Schattenjägerin Vosh'gajin"] = true,
["Die Bestie"] = true,
["Der Ravenier"] = true,
["Kriegsmeister Voone"] = true,
-- From Mendeleev
["Cho'Rush der Beobachter"] = true,
["Lord Hel'nurath"] = true,
["Pimgib"] = true,
["Knot Thimblejack's True"] = true,
["Kanonnenmeister Willey"] = true,
["Imperator Dagran Thaurissian"] = true,
["Erzmagier Arugal"] = true,
["Erzmagier Arugal's Leerwanderer"] = true,
["Baron Silberleine"] = true,
["Kommander Frühlingvale"] = true,
["Todeswachen Captain"] = true,
["Fenrus der Fresser"] = true,
["Odo der Blindwächter"] = true,
["Rasiermesserklaue der Metzger"] = true,
["Wolfmeister Nados"] = true,
["Rend Blackhand"] = true,
["Kurinnaxx"] = true,
-- Costum bosses
["Firesworn"] = true,
["Avalanchion"] = true,
["The Windreaver"] = true,
["Baron Charr"] = true,
["Princess Tempestria"] = true,
["Grethok the Controller"] = true,
["Patchwerk"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Feugen"] = true,
["Stalagg"] = true,
["Thaddius"] = true,
["Anub'Rekhan"] = true,
["Grand Widow Faerlina"] = true,
["Maexxna"] = true,
["Instructor Razuvious"] = true,
--["Deathknight Understudy"] = true,
["Gothik the Harvester"] = true,
["Highlord Mograine"] = true,
["Thane Korth'azz"] = true,
["Lady Blaumeux"] = true,
["Sir Zeliek"] = true,
["The Four Horsemen"] = true,
["Noth the Plaguebringer"] = true,
["Heigan the Unclean"] = true,
["Loatheb"] = true,
["Sapphiron"] = true,
["Kel'Thuzad"] = true,
["Lord Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz the Corrupt"] = true,
["Razorgore the Untamed"] = true,
["Broodlord Lashlayer"] = true,
["Chromaggus"] = true,
["Ebonroc"] = true,
["Firemaw"] = true,
["Flamegor"] = true,
["Majordomo Executus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg the Incinerator"] = true,
["Garr"] = true,
["Sulfuron Harbinger"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Lord Kazzak"] = true,
["Ysondre"] = true,
["Emeriss"] = true,
["Taerar"] = true,
["Lethon"] = true,
["High Priestess Jeklik"] = true,
["High Priest Venoxis"] = true,
["High Priest Thekal"] = true,
["High Priestess Arlokk"] = true,
["High Priestess Mar'li"] = true,
["Jin'do the Hexxer"] = true,
["Bloodlord Mandokir"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Hakkar"] = true,
["Ayamiss the Hunter"] = true,
["Buru the Gorger"] = true,
["General Rajaxx"] = true,
["Lieutenant General Andorov"] = true,
["Moam"] = true,
["Ossirian the Unscarred"] = true,
["Lord Kri"] = true,
["Princess Yauj"] = true,
["Vem"] = true,
["The Bug Family"] = true,
["Eye of C'Thun"] = true,
["C'Thun"] = true,
["Fankriss the Unyielding"] = true,
["Princess Huhuran"] = true,
["Ouro"] = true,
["Battleguard Sartura"] = true,
["The Prophet Skeram"] = true,
["Emperor Vek'lor"] = true,
["Emperor Vek'nilash"] = true,
["The Twin Emperors"] = true,
["Viscidus"] = true,
["Alzzin the Wildshaper"] = true,
["Ambassador Flamelash"] = true,
["Anger'rel"] = true,
["Archivist Galford"] = true,
["Atal'alarion"] = true,
["Avatar of Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baroness Anastari"] = true,
["Baron Rivendare"] = true,
["Cannon Master Willey"] = true,
["Captain Kromcrush"] = true,
["Celebras the Cursed"] = true,
["Crystal Fang"] = true,
["Darkmaster Gandling"] = true,
["Doctor Theolen Krastinov"] = true,
["Doom'rel"] = true,
["Dope'rel"] = true,
["Dreamscythe"] = true,
["Emperor Dagran Thaurissan"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["General Angerforge"] = true,
["General Drakkisath"] = true,
["Gloom'rel"] = true,
["Golem Lord Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Guard Fengus"] = true,
["Guard Mol'dar"] = true,
["Guard Slip'kik"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Hate'rel"] = true,
["Hazzas"] = true,
["Hearthsinger Forresten"] = true,
["High Interrogator Gerstahn"] = true,
["Highlord Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrospawn"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instructor Malicia"] = true,
["Jammal'an the Prophet"] = true,
["Jandice Barov"] = true,
["King Gordok"] = true,
["Kirtonos the Herald"] = true,
["Lady Illucia Barov"] = true,
["Landslide"] = true,
["Lethtendris"] = true,
["Lord Alexei Barov"] = true,
["Lord Incendius"] = true,
["Lord Vyletongue"] = true,
["Lorekeeper Polkelt"] = true,
["Loro"] = true,
["Magister Kalendris"] = true,
["Magistrate Barthilas"] = true,
["Magmus"] = true,
["Maleki the Pallid"] = true,
["Marduk Blackpool"] = true,
["Meshlok the Harvester"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Mother Smolderweb"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom the Wretched"] = true,
["Overlord Wyrmthalak"] = true,
["Phalanx"] = true,
["Plugger Spazzring"] = true,
["Postmaster Malown"] = true,
["Princess Moira Bronzebeard"] = true,
["Princess Theradras"] = true,
["Prince Tortheldrin"] = true,
["Pusillin"] = true,
["Pyroguard Emberseer"] = true,
["Ramstein the Gorger"] = true,
["Ras Frostwhisper"] = true,
["Rattlegore"] = true,
["Razorlash"] = true,
["Warchief Rend Blackhand"] = true,
["Ribbly Screwspigot"] = true,
["Rotgrip"] = true,
["Seeth'rel"] = true,
["Shade of Eranikus"] = true,
["Shadow Hunter Vosh'gajin"] = true,
["Solakar Flamewreath"] = true,
["Stomper Kreeg"] = true,
["Tendris Warpwood"] = true,
["The Beast"] = true,
["The Ravenian"] = true,
["Timmy the Cruel"] = true,
["Tinkerer Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Vile'rel"] = true,
["War Master Voone"] = true,
["Weaver"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
-- From Mendeleev
["Cho'Rush the Observer"] = true,
["Lord Hel'nurath"] = true,
["Pimgib"] = true,
["Knot Thimblejack's Cache"] = true,
["Cannonmaster Willey"] = true,
["Emperor Dagran Thaurissian"] = true,
["Archmage Arugal"] = true,
["Archmage Arugal's Voidwalker"] = true,
["Baron Silverlaine"] = true,
["Commander Springvale"] = true,
["Deathsworn Captain"] = true,
["Fenrus the Devourer"] = true,
["Odo the Blindwatcher"] = true,
["Razorclaw the Butcher"] = true,
["Wolf Master Nandos"] = true,
["Rend Blackhand"] = true,
["Kurinnaxx"] = true,
}
BabbleBoss = {}
function BabbleBoss:Contains(name)
return bosses[name]
end
DPSMate.BabbleBoss = BabbleBoss
end
@@ -0,0 +1,442 @@
--[[
Name: Babble-Boss-2.2
Revision: $Rev: 17545 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Babble-Boss-2.2
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Boss-2.2
Description: A library to provide localizations for bosses.
Dependencies: AceLibrary, AceLocale-2.2
Rewritten a little and added some "bosses" by Shino
]]
if (GetLocale()=="frFR") then
local bosses = {
["Avalanchion"] = true,
["Ouraganien"] = true,
["Baron Charr"] = true,
["Princesse Tempestria"] = true,
["Grethok le Contr\195\180leur"] = true,
["Le Recousu"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Feugen"] = true, -- CHECK
["Stalagg"] = true, -- CHECK
["Thaddius"] = true,
["Anub'Rekhan"] = true,
["Grande veuve Faerlina"] = true,
["Maexxna"] = true,
["Instructeur Razuvious"] = true,
["Doublure de chevalier de la mort"] = true, -- CHECK
["Gothik le Moissonneur"] = true,
["Grand Seigneur Mograine"] = true, -- CHECK
["Thane Korth'azz"] = true, -- CHECK
["Dame Blaumeux"] = true, -- CHECK
["Sir Zeliek "] = true, -- CHECK
["Les 4 Cavaliers"] = true,
["Noth the Plaguebringer"] ="Noth le Porte-peste",
["Heigan l'Impur"] = true,
["Horreb"] = true,
["Sapphiron"] = true,
["Kel'Thuzad"] = true,
["Seigneur Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz le Corrompu"] = true,
["Tranchetripe l'Indompt\195\169"] = true,
["Seigneur des couv\195\169es Lashlayer"] = true,
["Chromaggus"] = true,
["Roch\195\169b\195\168ne"] = true,
["Gueule-de-feu"] = true,
["Flamegor"] = true,
["Chambellan Executus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg l'Incin\195\169rateur"] = true,
["Garr"] = true,
["Messager de Sulfuron"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Seigneur Kazzak"] = true,
["Ysondre"] = true,
["Emeriss"] = true,
["Taerar"] = true,
["L\195\169thon"] = true,
["Grande pr\195\170tresse Jeklik"] = true,
["Grand pr\195\170tre Venoxis"] = true,
["Grand pr\195\170tre Thekal"] = true,
["Grande pr\195\170tresse Arlokk"] = true,
["Grande pr\195\170tresse Mar'li"] = true,
["Jin'do le Mal\195\169ficieur"] = true,
["Seigneur sanglant Mandokir"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Hakkar"] = true,
["Ayamiss le Chasseur"] = true,
["Buru Grandgosier"] = true,
["G\195\169n\195\169ral Rajaxx"] = true,
["G\195\169n\195\169ral de division Andorov"] = true,
["Moam"] = true,
["Gardien Anubisath"] = true,
["Ossirian l'Intouch\195\169"] = true,
["Seigneur Kri"] = true,
["Princesse Yauj"] = true,
["Vem"] = true,
["La famille insecte"] = true,
["Oeil de C'Thun"] = true,
["C'Thun"] = true,
["D\195\169fenseur Anubisath"] = true,
["Fankriss l'Inflexible"] = true,
["Princesse Huhuran"] = true,
["Ouro"] = true,
["Garde de guerre Sartura"] = true,
["Le Proph\195\168te Skeram"] = true,
["Empereur Vek'lor"] = true,
["Empereur Vek'nilash"] = true,
["Les Empereurs jumeaux"] = true,
["Viscidus"] = true,
["Alzzin le Modeleur"] = true,
["Ambassadeur Cinglefouet"] = true,
["Col\195\169'rel"] = true,
["Archiviste Galford"] = true,
["Atal'alarion"] = true,
["Avatar d'Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baronne Anastari"] = true,
["Baron Rivendare"] = true,
["Ma\195\174tre canonnier Willey"] = true,
["Capitaine Kromcrush"] = true,
["Celebras le Maudit"] = true,
["Croc cristallin"] = true,
["Sombre Ma\195\174tre Gandling"] = true,
["Docteur Theolen Krastinov"] = true,
["Tragi'rel"] = true,
["Demeu'rel"] = true,
["Fauche-r\195\170ve"] = true,
["Empereur Dagran Thaurissan"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["G\195\169n\195\169ral Angerforge"] = true,
["G\195\169n\195\169ral Drakkisath"] = true,
["Fun\195\169b'rel"] = true,
["Seigneur golem Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Garde Fengus"] = true,
["Garde Mol'dar"] = true,
["Garde Slip'kik"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Haine'rel"] = true,
["Hazzas"] = true,
["Hearthsinger Forresten"] = true,
["Grand Interrogateur Gerstahn"] = true,
["G\195\169n\195\169ralissime Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrog\195\169nos"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instructeur Malicia"] = true,
["Jammal'an le proph\195\168te"] = true,
["Jandice Barov"] = true,
["Roi Gordok"] = true,
["Kirtonos le H\195\169raut"] = true,
["Dame Illucia Barov"] = true,
["Glissement de terrain"] = true,
["Lethtendris"] = true,
["Seigneur Alexei Barov"] = true,
["Seigneur Incendius"] = true,
["Seigneur Vylelangue"] = true,
["Gardien du savoir Polkelt"] = true,
["Loro"] = true,
["Magist\195\168re Kalendris"] = true,
["Magistrat Barthilas"] = true,
["Magmus"] = true,
["Maleki le Blafard"] = true,
["Marduk Noir\195\169tang"] = true,
["Meshlok le Moissonneur"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Matriarche Couveuse"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom le Mis\195\169rable"] = true,
["Seigneur Wyrmthalak"] = true,
["Phalange"] = true,
["Plugger Spazzring"] = true,
["Postier Malown"] = true,
["Princesse Moira Bronzebeard"] = true,
["Princesse Theradras"] = true,
["Prince Tortheldrin"] = true,
["Pusillin"] = true,
["Pyrogarde Proph\195\168te ardent"] = true,
["Ramstein Grandgosier"] = true,
["Ras Murmegivre"] = true,
["Cliquettripes"] = true,
["Tranchefouet"] = true,
["Chef de guerre Rend Blackhand"] = true,
["Ribbly Screwspigot"] = true,
["Grippe-charogne"] = true,
["Fulmi'rel"] = true,
["Ombre d'Eranikus"] = true,
["Chasseresse des ombres Vosh'gajin"] = true,
["Solakar Voluteflamme"] = true,
["Kreeg le Marteleur"] = true,
["Tendris Crochebois"] = true,
["La B\195\170te"] = true,
["Le Voracien"] = true,
["Timmy le Cruel"] = true,
["Artisan Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Ignobl'rel"] = true,
["Ma\195\174tre de guerre Voone"] = true,
["Tisserand"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
-- From Mendeleev
["Cho'Rush l'Observateur"] = true,
["Seigneur Hel'nurath"] = true,
["Pimgib"] = true,
["R\195\169serve de Knot Thimblejack"] = true,
["Archimage Arugal"] = true,
["Marcheur du Vide d'Arugal"] = true,
["Baron d'Argelaine"] = true,
["Commandant Springvale"] = true,
["Capitaine Ligemort"] = true,
["Fenrus le D\195\169voreur"] = true,
["Odo l'Aveugle"] = true,
["Tranchegriffe le Boucher"] = true,
["Ma\195\174tre-loup Nandos"] = true,
["Kurinnaxx"] = true,
-- Costum bosses
["Firesworn"] = true,
["Avalanchion"] = true,
["The Windreaver"] = true,
["Baron Charr"] = true,
["Princess Tempestria"] = true,
["Grethok the Controller"] = true,
["Patchwerk"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Feugen"] = true,
["Stalagg"] = true,
["Thaddius"] = true,
["Anub'Rekhan"] = true,
["Grand Widow Faerlina"] = true,
["Maexxna"] = true,
["Instructor Razuvious"] = true,
--["Deathknight Understudy"] = true,
["Gothik the Harvester"] = true,
["Highlord Mograine"] = true,
["Thane Korth'azz"] = true,
["Lady Blaumeux"] = true,
["Sir Zeliek"] = true,
["The Four Horsemen"] = true,
["Noth the Plaguebringer"] = true,
["Heigan the Unclean"] = true,
["Loatheb"] = true,
["Sapphiron"] = true,
["Kel'Thuzad"] = true,
["Lord Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz the Corrupt"] = true,
["Razorgore the Untamed"] = true,
["Broodlord Lashlayer"] = true,
["Chromaggus"] = true,
["Ebonroc"] = true,
["Firemaw"] = true,
["Flamegor"] = true,
["Majordomo Executus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg the Incinerator"] = true,
["Garr"] = true,
["Sulfuron Harbinger"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Lord Kazzak"] = true,
["Ysondre"] = true,
["Emeriss"] = true,
["Taerar"] = true,
["Lethon"] = true,
["High Priestess Jeklik"] = true,
["High Priest Venoxis"] = true,
["High Priest Thekal"] = true,
["High Priestess Arlokk"] = true,
["High Priestess Mar'li"] = true,
["Jin'do the Hexxer"] = true,
["Bloodlord Mandokir"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Hakkar"] = true,
["Ayamiss the Hunter"] = true,
["Buru the Gorger"] = true,
["General Rajaxx"] = true,
["Lieutenant General Andorov"] = true,
["Moam"] = true,
["Ossirian the Unscarred"] = true,
["Lord Kri"] = true,
["Princess Yauj"] = true,
["Vem"] = true,
["The Bug Family"] = true,
["Eye of C'Thun"] = true,
["C'Thun"] = true,
["Fankriss the Unyielding"] = true,
["Princess Huhuran"] = true,
["Ouro"] = true,
["Battleguard Sartura"] = true,
["The Prophet Skeram"] = true,
["Emperor Vek'lor"] = true,
["Emperor Vek'nilash"] = true,
["The Twin Emperors"] = true,
["Viscidus"] = true,
["Alzzin the Wildshaper"] = true,
["Ambassador Flamelash"] = true,
["Anger'rel"] = true,
["Archivist Galford"] = true,
["Atal'alarion"] = true,
["Avatar of Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baroness Anastari"] = true,
["Baron Rivendare"] = true,
["Cannon Master Willey"] = true,
["Captain Kromcrush"] = true,
["Celebras the Cursed"] = true,
["Crystal Fang"] = true,
["Darkmaster Gandling"] = true,
["Doctor Theolen Krastinov"] = true,
["Doom'rel"] = true,
["Dope'rel"] = true,
["Dreamscythe"] = true,
["Emperor Dagran Thaurissan"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["General Angerforge"] = true,
["General Drakkisath"] = true,
["Gloom'rel"] = true,
["Golem Lord Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Guard Fengus"] = true,
["Guard Mol'dar"] = true,
["Guard Slip'kik"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Hate'rel"] = true,
["Hazzas"] = true,
["Hearthsinger Forresten"] = true,
["High Interrogator Gerstahn"] = true,
["Highlord Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrospawn"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instructor Malicia"] = true,
["Jammal'an the Prophet"] = true,
["Jandice Barov"] = true,
["King Gordok"] = true,
["Kirtonos the Herald"] = true,
["Lady Illucia Barov"] = true,
["Landslide"] = true,
["Lethtendris"] = true,
["Lord Alexei Barov"] = true,
["Lord Incendius"] = true,
["Lord Vyletongue"] = true,
["Lorekeeper Polkelt"] = true,
["Loro"] = true,
["Magister Kalendris"] = true,
["Magistrate Barthilas"] = true,
["Magmus"] = true,
["Maleki the Pallid"] = true,
["Marduk Blackpool"] = true,
["Meshlok the Harvester"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Mother Smolderweb"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom the Wretched"] = true,
["Overlord Wyrmthalak"] = true,
["Phalanx"] = true,
["Plugger Spazzring"] = true,
["Postmaster Malown"] = true,
["Princess Moira Bronzebeard"] = true,
["Princess Theradras"] = true,
["Prince Tortheldrin"] = true,
["Pusillin"] = true,
["Pyroguard Emberseer"] = true,
["Ramstein the Gorger"] = true,
["Ras Frostwhisper"] = true,
["Rattlegore"] = true,
["Razorlash"] = true,
["Warchief Rend Blackhand"] = true,
["Ribbly Screwspigot"] = true,
["Rotgrip"] = true,
["Seeth'rel"] = true,
["Shade of Eranikus"] = true,
["Shadow Hunter Vosh'gajin"] = true,
["Solakar Flamewreath"] = true,
["Stomper Kreeg"] = true,
["Tendris Warpwood"] = true,
["The Beast"] = true,
["The Ravenian"] = true,
["Timmy the Cruel"] = true,
["Tinkerer Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Vile'rel"] = true,
["War Master Voone"] = true,
["Weaver"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
-- From Mendeleev
["Cho'Rush the Observer"] = true,
["Lord Hel'nurath"] = true,
["Pimgib"] = true,
["Knot Thimblejack's Cache"] = true,
["Cannonmaster Willey"] = true,
["Emperor Dagran Thaurissian"] = true,
["Archmage Arugal"] = true,
["Archmage Arugal's Voidwalker"] = true,
["Baron Silverlaine"] = true,
["Commander Springvale"] = true,
["Deathsworn Captain"] = true,
["Fenrus the Devourer"] = true,
["Odo the Blindwatcher"] = true,
["Razorclaw the Butcher"] = true,
["Wolf Master Nandos"] = true,
["Rend Blackhand"] = true,
["Kurinnaxx"] = true,
}
BabbleBoss = {}
function BabbleBoss:Contains(name)
return bosses[name]
end
DPSMate.BabbleBoss = BabbleBoss
end
@@ -0,0 +1,631 @@
--[[
Name: Babble-Boss-2.2
Revision: $Rev: 17545 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Babble-Boss-2.2
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Boss-2.2
Description: A library to provide localizations for bosses.
Dependencies: AceLibrary, AceLocale-2.2
Rewritten a little and added some "bosses" by Shino
]]
if (GetLocale()=="koKR") then
local bosses = {
["아누비사스 문지기"] = true,
["전투감시병 살투라"] = true,
[""] = true,
["제왕 베클로어"] = true,
["제왕 베크닐라쉬"] = true,
["쑨의 눈"] = true,
["불굴의 판크리스"] = true,
["군주 크리"] = true,
["아우로"] = true,
["공주 후후란"] = true,
["공주 야우즈"] = true,
["벌레 무리"] = true,
["예언자 스케람"] = true,
["쌍둥이 제왕"] = true,
[""] = true,
["비시디우스"] = true,
["총독 말라다르"] = true,
["죽음의 감시인 쉴라크"] = true,
["연합왕자 샤파르"] = true,
["팬더모니우스"] = true,
["타바로크"] = true,
["사자 지옥아귀"] = true,
["선동자 검은심장"] = true,
["단장 보르필"] = true,
["울림"] = true,
["안주"] = true, --summoned boss
["흑마술사 시스"] = true,
["갈퀴대왕 이키스"] = true,
["아쿠마이"] = true,
["남작 아쿠아니스"] = true,
["겔리하스트"] = true,
["가무라 "] = true,
["여왕 사레베스"] = true,
["늙은 세라키스"] = true,
["황혼의 군주 켈리스"] = true,
["사자 화염채찍"] = true,
["격노의 문지기"] = true,
["아눕쉬아"] = true,
["벨가르"] = true,
["Chest of The Seven"] = true,
["운명의 문지기"] = true,
["최면의 문지기"] = true,
["제왕 다그란 타우릿산"] = true,
["적출자"] = true,
["파이너스 다크바이어"] = true,
["사령관 앵거포지"] = true,
["그늘의 문지기"] = true,
["골렘군주 아젤마크"] = true,
["광신자 고로쉬"] = true, --check
["그리즐"] = true,
["증오의 문지기"] = true,
["왕거미 헤드룸"] = true,
["대심문관 게르스탄"] = true,
["타우릿산의 대여사제"] = true,
["사냥개조련사 그렙마르"] = true,
["헐레이 블랙브레스"] = true,
["군주 인센디우스"] = true,
["불의군주 록코르"] = true,
["마그무스"] = true,
["파괴자 오크토르"] = true,
["무적의 판저"] = true,
["팔란스"] = true,
["플러거스파즈링"] = true,
["공주 모이라 브론즈비어드"] = true,
["화염술사 로어그레인"] = true,
["리블리 스크류스피곳"] = true,
["불안의 문지기"] = true,
["The Seven Dwarves"] = true,
["베레크"] = true,
["타락의 문지기"] = true,
["문지기 스틸기스"] = true,
["반노크 그림액스"] = true,
["불타는 지옥수호병"] = true,
["수정 맹독 거미"] = true,
["고크 배시구드"] = true,
["흉포한 기즈룰"] = true,
["할리콘"] = true,
["대군주 오모크"] = true,
["모르 그레이후프"] = true,
["여왕 불그물거미"] = true,
["대군주 윔타라크"] = true,
["병참장교 지그리스"] = true,
["어둠사냥꾼 보쉬가진"] = true,
["뾰족바위일족 전투대장"] = true,
["뾰족바위일족 학살자"] = true,
["뾰족바위일족 마법사장"] = true,
["우르크 둠하울"] = true,
["대장군 부네"] = true,
["사령관 드라키사스"] = true,
["고랄루크 앤빌크랙"] = true,
["기스"] = true,
["제드 룬와처"] = true,
["군주 발타라크"] = true,
["불의 수호자 엠버시어"] = true,
["화염고리 솔라카르"] = true,
["괴수"] = true,
["대족장 렌드 블랙핸드"] = true,
["용기대장 래쉬레이어"] = true,
["크로마구스"] = true,
["에본로크"] = true,
["화염아귀"] = true,
["플레임고르"] = true,
["감시자 그레토크"] = true,
["군주 빅터 네파리우스"] = true,
["네파리안"] = true,
["폭군 서슬송곳니"] = true,
["타락한 밸라스트라즈"] = true,
["머쉬고그"] = true,
["무적의 스카르"] = true,
["라자"] = true,
["칼날바람 알진"] = true,
["히드로스폰"] = true,
["이살리엔"] = true,
["레스텐드리스"] = true,
["핌기브"] = true,
["푸실린"] = true,
["제브림 쏜후프"] = true,
["대장 크롬크러쉬"] = true,
["정찰병 초루쉬"] = true,
["경비병 펜구스"] = true,
["경비병 몰다르"] = true,
["경기병 슬립킥"] = true,
["왕 고르독"] = true,
["천둥발 크리그"] = true,
["일샨나 레이븐호크"] = true,
["이몰타르"] = true,
["군주 헬누라스"] = true,
["마법사 칼렌드리스"] = true,
["왕자 토르텔드린"] = true,
["굽이나무 텐드리스"] = true,
["츄지"] = true,
["고철 압축기 9-60"] = true,
["검은무쇠단 사절"] = true,
["기계화 문지기 6000"] = true,
["그루비스 "] = true,
["멕기니어 텔마플러그"] = true,
["첨단로봇"] = true,
["방사성 폐기물"] = true,
["저주받은 셀레브라스"] = true,
["겔크"] = true,
["콜크"] = true,
["산사태"] = true,
["군주 바일텅"] = true,
["마그라"] = true,
["마라우도스"] = true,
["정원사 메슬로크"] = true,
["녹시온"] = true,
["공주 테라드라스"] = true,
["칼날채찍"] = true,
["썩은 아귀"] = true,
["땜장이 기즐록"] = true,
[""] = true,
["남작 게돈"] = true,
["Cache of the Firelord"] = true,
["가르"] = true,
["게헨나스"] = true,
["초열의 골레마그"] = true,
["루시프론"] = true,
["마그마다르"] = true,
["청지기 이그젝큐투스"] = true,
["라그나로스"] = true,
["샤즈라"] = true,
["설퍼론 사자"] = true,
["아눕레칸"] = true,
["죽음의 기사 수습생"] = true,
["퓨진"] = true,
["Four Horsemen Chest"] = true,
["글루스"] = true,
["영혼 착취자 고딕"] = true,
["귀부인 팰리나"] = true,
["그라불루스"] = true,
["부정의 헤이건"] = true,
["대영주 모그레인"] = true,
["훈련교관 라주비어스"] = true,
["켈투자드"] = true,
["여군주 블라미우스"] = true,
["로데브"] = true,
["맥스나"] = true,
["역병술사 노스"] = true,
["패치워크"] = true,
["사피론"] = true,
["젤리에크 경"] = true,
["스탈라그"] = true,
["타디우스"] = true,
["영주 코스아즈"] = true,
["4인의 기병대"] = true,
["오닉시아"] = true,
["바잘란"] = true,
["기원사 제로쉬"] = true,
["마우르 그림토템"] = true,
["욕망의 타라가만"] = true,
["혹한의 암네나르"] = true,
["게걸먹보"] = true,
["불꽃눈 모드레쉬"] = true,
["썩어가는 역병아귀"] = true,
["너덜주둥이"] = true,
["투텐카쉬"] = true,
["흉포한 아가테로스"] = true,
["장님 사냥꾼"] = true,
["서슬깃 차를가"] = true,
["죽음의 예언자 잘그바"] = true,
["대지술사 함가르"] = true,
["대군주 램터스크"] = true,
["아누비사스 감시자"] = true,
["사냥꾼 아야미스"] = true,
["먹보 부루"] = true,
["장군 라작스"] = true,
["쿠린낙스"] = true,
["사령관 안도로브"] = true,
["모암"] = true,
["무적의 오시리안"] = true,
["헤로드"] = true,
["종교재판관 페어뱅크스"] = true,
["종교재판관 화이트메인"] = true,
["붉은십자군 사령관 모그레인"] = true,
["잠들지 않는 아즈시르"] = true,
["혈법사 탈노스"] = true,
["타락한 용사"] = true,
["심문관 비샤스"] = true,
["무쇠해골"] = true,
["신비술사 도안"] = true,
["사냥개 조련사 록시"] = true,
["키르토노스의 혈지기"] = true,
["암흑스승 간틀링"] = true,
["죽음의 기사 다크리버"] = true,
["학자 테올린 크라스티노브"] = true,
["조교 말리시아"] = true,
["잔다이스 바로브"] = true,
["사자 키르토노스"] = true,
["코르모크"] = true,
["여군주 일루시아 바로브"] = true,
["군주 알렉세이 바로브"] = true,
["현자 폴켈트"] = true,
["마르두크 블랙풀"] = true,
["라스 프로스트위스퍼"] = true,
["들창어금니"] = true,
["라베니안"] = true,
["벡투스"] = true,
["대마법사 아루갈"] = true,
["아루갈의 보이드워커"] = true,
["남작 실버레인"] = true,
["사령관 스프링베일"] = true,
["죽음의 경비대장"] = true, -- check
["파멸의 펜루스"] = true,
["눈먼감시자 오도"] = true,
["도살자 칼날발톱"] = true,
["늑대왕 난도스"] = true,
["기록관 갈포드"] = true,
["발나자르"] = true,
["남작 리븐데어"] = true,
["남작부인 아나스타리"] = true,
["검은호위대 검제작자"] = true,
["포병대장 윌리"] = true,
["진홍십자군 대장장이"] = true,
["프라스 샤비"] = true,
["하스싱어 포레스턴"] = true,
["집정관 바실라스"] = true,
["냉혈한 말레키"] = true,
["네룹엔칸"] = true,
["우체국장 말로운"] = true,
["먹보 람스타인"] = true,
["스컬"] = true,
["뾰족바위"] = true,
["용서받지 못한 자"] = true,
["잔혹한 티미"] = true,
["세뇌당한 귀족"] = true,
["선장 그린스킨"] = true,
["쿠키"] = true,
["에드윈 밴클리프"] = true,
["현장감독 시슬네틀"] = true,
["길니드"] = true,
["마리사 두페이지"] = true,
["광부 존슨"] = true,
["미스터 스마이트"] = true,
["라크조르"] = true,
["스니드"] = true,
["스니드의 벌목기"] = true,
["바질 스레드"] = true,
["무쇠주먹 브루갈"] = true,
["덱스트렌 워드"] = true,
["햄혹"] = true,
["캄 딥퓨리"] = true,
["흉악범 타고르"] = true,
["아탈알라리온"] = true,
["학카르의 화신"] = true,
["드림사이드"] = true,
["게이셔"] = true,
["하자스"] = true,
["후쿠"] = true,
["제이드"] = true,
["예언자 잠말란"] = true,
["타락한 카즈카즈"] = true,
["로로"] = true,
["마이잔"] = true,
["몰파즈"] = true,
["비운의 오그옴"] = true,
["에라니쿠스의 사령"] = true,
["식인트롤 베이쟉"] = true,
["위버"] = true,
["젝키스"] = true,
["졸로"] = true,
["줄로"] = true,
["고대 바위 문지기"] = true,
["아카에다스"] = true,
["밸로그"] = true,
["발굴단장 쇼벨플랜지"] = true,
["갈간 파이어해머"] = true,
["그림로크"] = true,
["아이로나야"] = true,
["흑요석 파수꾼"] = true,
["레벨로쉬"] = true,
["보안"] = true,
["돌연변이 요정용"] = true,
["크레쉬"] = true,
["여군주 아나콘드라"] = true,
["군주 코브란"] = true,
["군주 피타스"] = true,
["군주 서펜디스"] = true,
["광기의 매글리시"] = true,
["걸신들린 무타누스"] = true,
["스컴"] = true,
["채찍꼬리 트리고어"] = true,
["영생의 베르단"] = true,
["아발란치온"] = true,
["아주어고스"] = true,
["남작 차르"] = true,
["남작 카줌"] = true,
["파멸의 군주 카자크"] = true,
["파멸의 절단기"] = true,
["에메리스"] = true,
["대장군 휠락시스"] = true, -- check
["레손"] = true,
["군주 스퀄"] = true,
["왕자 스칼레녹스"] = true,
["공주 템페스트리아"] = true,
["타에라"] = true,
["칼날바람"] = true,
["이손드레"] = true,
["안투술"] = true,
["족장 우코르즈 샌드스칼프"] = true,
["더스트레이스"] = true,
["가즈릴라"] = true,
["유체술사 벨라타"] = true,
["무르타 그림구트"] = true,
["네크룸 거트츄어"] = true,
["오로 아이가우지"] = true,
["루즐루"] = true,
["Sandarr Dunereaver"] = true,
["성난모래부족 사형집행인"] = true,
["하사관 블라이"] = true,
["어둠의사제 세즈지즈"] = true,
["순교자 데카"] = true,
["의술사 줌라"] = true,
["제릴리스"] = true,
["줄파락 죽음의 영웅"] = true,
["혈군주 만도키르"] = true,
["가즈란카"] = true,
["그리렉"] = true,
["학카르"] = true,
["하자라"] = true,
["대사제 데칼"] = true,
["대사제 베녹시스"] = true,
["대여사제 알로크"] = true,
["대여사제 제클릭"] = true,
["대여사제 말리"] = true,
["주술사 진도"] = true,
["레나타키"] = true,
["우슬레이"] = true,
-- Costum bosses
["Firesworn"] = true,
["Avalanchion"] = true,
["The Windreaver"] = true,
["Baron Charr"] = true,
["Princess Tempestria"] = true,
["Grethok the Controller"] = true,
["Patchwerk"] = true,
["Grobbulus"] = true,
["Gluth"] = true,
["Feugen"] = true,
["Stalagg"] = true,
["Thaddius"] = true,
["Anub'Rekhan"] = true,
["Grand Widow Faerlina"] = true,
["Maexxna"] = true,
["Instructor Razuvious"] = true,
--["Deathknight Understudy"] = true,
["Gothik the Harvester"] = true,
["Highlord Mograine"] = true,
["Thane Korth'azz"] = true,
["Lady Blaumeux"] = true,
["Sir Zeliek"] = true,
["The Four Horsemen"] = true,
["Noth the Plaguebringer"] = true,
["Heigan the Unclean"] = true,
["Loatheb"] = true,
["Sapphiron"] = true,
["Kel'Thuzad"] = true,
["Lord Victor Nefarius"] = true,
["Nefarian"] = true,
["Vaelastrasz the Corrupt"] = true,
["Razorgore the Untamed"] = true,
["Broodlord Lashlayer"] = true,
["Chromaggus"] = true,
["Ebonroc"] = true,
["Firemaw"] = true,
["Flamegor"] = true,
["Majordomo Executus"] = true,
["Ragnaros"] = true,
["Baron Geddon"] = true,
["Golemagg the Incinerator"] = true,
["Garr"] = true,
["Sulfuron Harbinger"] = true,
["Shazzrah"] = true,
["Lucifron"] = true,
["Gehennas"] = true,
["Magmadar"] = true,
["Onyxia"] = true,
["Azuregos"] = true,
["Lord Kazzak"] = true,
["Ysondre"] = true,
["Emeriss"] = true,
["Taerar"] = true,
["Lethon"] = true,
["High Priestess Jeklik"] = true,
["High Priest Venoxis"] = true,
["High Priest Thekal"] = true,
["High Priestess Arlokk"] = true,
["High Priestess Mar'li"] = true,
["Jin'do the Hexxer"] = true,
["Bloodlord Mandokir"] = true,
["Gahz'ranka"] = true,
["Gri'lek"] = true,
["Hazza'rah"] = true,
["Renataki"] = true,
["Wushoolay"] = true,
["Hakkar"] = true,
["Ayamiss the Hunter"] = true,
["Buru the Gorger"] = true,
["General Rajaxx"] = true,
["Lieutenant General Andorov"] = true,
["Moam"] = true,
["Ossirian the Unscarred"] = true,
["Lord Kri"] = true,
["Princess Yauj"] = true,
["Vem"] = true,
["The Bug Family"] = true,
["Eye of C'Thun"] = true,
["C'Thun"] = true,
["Fankriss the Unyielding"] = true,
["Princess Huhuran"] = true,
["Ouro"] = true,
["Battleguard Sartura"] = true,
["The Prophet Skeram"] = true,
["Emperor Vek'lor"] = true,
["Emperor Vek'nilash"] = true,
["The Twin Emperors"] = true,
["Viscidus"] = true,
["Alzzin the Wildshaper"] = true,
["Ambassador Flamelash"] = true,
["Anger'rel"] = true,
["Archivist Galford"] = true,
["Atal'alarion"] = true,
["Avatar of Hakkar"] = true,
["Bael'Gar"] = true,
["Balnazzar"] = true,
["Baroness Anastari"] = true,
["Baron Rivendare"] = true,
["Cannon Master Willey"] = true,
["Captain Kromcrush"] = true,
["Celebras the Cursed"] = true,
["Crystal Fang"] = true,
["Darkmaster Gandling"] = true,
["Doctor Theolen Krastinov"] = true,
["Doom'rel"] = true,
["Dope'rel"] = true,
["Dreamscythe"] = true,
["Emperor Dagran Thaurissan"] = true,
["Fineous Darkvire"] = true,
["Gasher"] = true,
["General Angerforge"] = true,
["General Drakkisath"] = true,
["Gloom'rel"] = true,
["Golem Lord Argelmach"] = true,
["Goraluk Anvilcrack"] = true,
["Guard Fengus"] = true,
["Guard Mol'dar"] = true,
["Guard Slip'kik"] = true,
["Gyth"] = true,
["Halycon"] = true,
["Hate'rel"] = true,
["Hazzas"] = true,
["Hearthsinger Forresten"] = true,
["High Interrogator Gerstahn"] = true,
["Highlord Omokk"] = true,
["Hukku"] = true,
["Hurley Blackbreath"] = true,
["Hydrospawn"] = true,
["Illyanna Ravenoak"] = true,
["Immol'thar"] = true,
["Instructor Malicia"] = true,
["Jammal'an the Prophet"] = true,
["Jandice Barov"] = true,
["King Gordok"] = true,
["Kirtonos the Herald"] = true,
["Lady Illucia Barov"] = true,
["Landslide"] = true,
["Lethtendris"] = true,
["Lord Alexei Barov"] = true,
["Lord Incendius"] = true,
["Lord Vyletongue"] = true,
["Lorekeeper Polkelt"] = true,
["Loro"] = true,
["Magister Kalendris"] = true,
["Magistrate Barthilas"] = true,
["Magmus"] = true,
["Maleki the Pallid"] = true,
["Marduk Blackpool"] = true,
["Meshlok the Harvester"] = true,
["Mijan"] = true,
["Morphaz"] = true,
["Mother Smolderweb"] = true,
["Nerub'enkan"] = true,
["Noxxion"] = true,
["Ogom the Wretched"] = true,
["Overlord Wyrmthalak"] = true,
["Phalanx"] = true,
["Plugger Spazzring"] = true,
["Postmaster Malown"] = true,
["Princess Moira Bronzebeard"] = true,
["Princess Theradras"] = true,
["Prince Tortheldrin"] = true,
["Pusillin"] = true,
["Pyroguard Emberseer"] = true,
["Ramstein the Gorger"] = true,
["Ras Frostwhisper"] = true,
["Rattlegore"] = true,
["Razorlash"] = true,
["Warchief Rend Blackhand"] = true,
["Ribbly Screwspigot"] = true,
["Rotgrip"] = true,
["Seeth'rel"] = true,
["Shade of Eranikus"] = true,
["Shadow Hunter Vosh'gajin"] = true,
["Solakar Flamewreath"] = true,
["Stomper Kreeg"] = true,
["Tendris Warpwood"] = true,
["The Beast"] = true,
["The Ravenian"] = true,
["Timmy the Cruel"] = true,
["Tinkerer Gizlock"] = true,
["Tsu'zee"] = true,
["Vectus"] = true,
["Vile'rel"] = true,
["War Master Voone"] = true,
["Weaver"] = true,
["Zevrim Thornhoof"] = true,
["Zolo"] = true,
["Zul'Lor"] = true,
-- From Mendeleev
["Cho'Rush the Observer"] = true,
["Lord Hel'nurath"] = true,
["Pimgib"] = true,
["Knot Thimblejack's Cache"] = true,
["Cannonmaster Willey"] = true,
["Emperor Dagran Thaurissian"] = true,
["Archmage Arugal"] = true,
["Archmage Arugal's Voidwalker"] = true,
["Baron Silverlaine"] = true,
["Commander Springvale"] = true,
["Deathsworn Captain"] = true,
["Fenrus the Devourer"] = true,
["Odo the Blindwatcher"] = true,
["Razorclaw the Butcher"] = true,
["Wolf Master Nandos"] = true,
["Rend Blackhand"] = true,
["Kurinnaxx"] = true,
}
BabbleBoss = {}
function BabbleBoss:Contains(name)
return bosses[name]
end
DPSMate.BabbleBoss = BabbleBoss
end

Some files were not shown because too many files have changed in this diff Show More