Files
coa-details/plugins/Details_DpsTuning/Details_DpsTuning.lua
T
Tercio 37ab5370c5 - Added Unstable Affliction to common spells with the same name.
- Fixed few issues with built-in plugins.
2016-11-28 16:28:05 -02:00

1243 lines
41 KiB
Lua

local Loc = LibStub ("AceLocale-3.0"):GetLocale ("Details")
--> Main Plugin Object
local DpsTuningPlugin = _detalhes:NewPluginObject ("Details_DpsTuning")
--> Main Frame
local SDF = DpsTuningPlugin.Frame
--> global pointers
local ClockTime = time --> lua library local
local ipairs = ipairs --> lua library local
local pairs = pairs --> lua library local
local floor = floor --> lua library local
local _cstr = string.format --> lua library local
local GetSpellBonusDamage = GetSpellBonusDamage
local UnitAura = UnitAura --> wow api local
local GetTime = GetTime --> wow api local
local _
local _GetSpellInfo =_detalhes.getspellinfo --> details api local
DpsTuningPlugin:SetPluginDescription ("Tool for testing your Dps showing detailed information for each spell, buffs and also graphical charts for abilities.")
local function CreatePluginFrames()
--> get the framework
local fw = _detalhes:GetFramework()
--> player damage done chart code
local string_player_damage_done = [[
-- the goal of this script is get the current combat then get your character and extract your damage done.
-- the first thing to do is get the combat, so, we use here the command "_detalhes:GetCombat ( "overall" "current" or "segment number")"
local current_combat = _detalhes:GetCombat ("current") --> getting the current combat
-- the next step is request your character from the combat
-- to do this, we take the combat which here we named "current_combat" and tells what we want inside parentheses.
local my_self = current_combat (DETAILS_ATTRIBUTE_DAMAGE, _detalhes.playername)
-- _detalhes.playername holds the name of your character.
-- DETAILS_ATTRIBUTE_DAMAGE means we want the damage table, _HEAL _ENERGY _MISC is the other 3 tables.
-- before we proceed, the result needs to be checked to make sure its a valid result.
if (not my_self) then
return 0 -- the combat doesnt have *you*, this happens when you didn't deal any damage in the combat yet.
end
-- now its time to get the total damage.
local my_damage = my_self.total
-- then finally return the amount to the capture.
return my_damage
]]
--> color for spell dps bars
DpsTuningPlugin.BarColor = {.4, .4, .4, .7}
function DpsTuningPlugin:OnDetailsEvent (event, ...)
if (event == "SHOW") then --> plugin shown on screen, actived
SDF:SetResizable (false) --> cant resize, this is a fixed size
SDF:SetSize (300, 300) --> need to be 300x300 to fit details window
--> create the frames on the first shown
if (not DpsTuningPlugin.frames_created) then
DpsTuningPlugin:BuildHeader()
DpsTuningPlugin:BuildSpellBars()
DpsTuningPlugin:BuildSummaryPanel()
DpsTuningPlugin:BuildBuffBlocks()
DpsTuningPlugin:BuildChartPanels()
DpsTuningPlugin.frames_created = true
DpsTuningPlugin.Frame:Show()
--tricky, localize members inside the plugin, so it doesn't need to lookup on _detalhes object every time
DpsTuningPlugin.playername = DpsTuningPlugin.playername
DpsTuningPlugin.comma_value = DpsTuningPlugin.comma_value
DpsTuningPlugin.ToK2 = DpsTuningPlugin.ToK2
DpsTuningPlugin.Sort2 = DpsTuningPlugin.Sort2
DpsTuningPlugin.Sort3 = DpsTuningPlugin.Sort3
end
--> we only want register the player damage done when the plugin is active
DpsTuningPlugin:TimeDataRegister ("Player Damage Done", string_player_damage_done, nil, "Spell Details", "v1.0", "Interface\\Icons\\INV_Fabric_Spellweave", true, true)
elseif (event == "HIDE") then --> plugin hidded, disabled
--> plugin is gone, unregister the chart
DpsTuningPlugin:TimeDataUnregister ("Player Damage Done")
elseif (event == "DETAILS_STARTED") then
--> triggered right after details finish run all ADDON_LOADED functions
local power = {}
for i = 1, 7 do
power [i] = {i, GetSpellBonusDamage (i)}
end
table.sort (power, DpsTuningPlugin.Sort2)
DpsTuningPlugin.PowerType = power [1][1]
elseif (event == "REFRESH") then --> requested a refresh window
--> refresh window happens when there is a invalid combat, like a combat with less then 5 seconds.
--DpsTuningPlugin:Refresh()
elseif (event == "COMBAT_PLAYER_ENTER") then
DpsTuningPlugin:OnCombatStart (...)
elseif (event == "COMBAT_INVALID") then
--DpsTuningPlugin:Reset()
--print ("eh invalido...")
elseif (event == "COMBAT_PLAYER_LEAVE") then
DpsTuningPlugin:OnCombatEnd (...)
elseif (event == "PLUGIN_DISABLED") then
--> plugin got disabled on details options panel
elseif (event == "PLUGIN_ENABLED") then
--> plugin got enabled on details options panel
elseif (event == "DETAILS_DATA_RESET") then
--> data on details! got reseted. need to reset the plugin as well
DpsTuningPlugin:TrackBuffsAtEnd()
DpsTuningPlugin:CancelTicker()
SDF:UnregisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
DpsTuningPlugin:OnDataReset (...)
end
end
local close_button = DpsTuningPlugin:CreateSoloCloseButton()
close_button:SetPoint ("TOPRIGHT", SDF, "TOPRIGHT", -15, 5)
close_button:SetSize (24, 24)
function DpsTuningPlugin.GetActivityTime (thisspell, time)
if (thisspell.tempo_end) then --> o tempo do jogador esta trancado
local t = thisspell.tempo_end - thisspell.start
if (t < 6) then
t = 6
end
return t
elseif (thisspell.onhold) then
local t = thisspell.delay - thisspell.start
if (t < 6) then
t = 6
end
return t
else
if (thisspell.start == 0) then
return 6
end
local t = time - thisspell.start
if (t < 6) then
if (DpsTuningPlugin.in_combat) then
local combat_time = DpsTuningPlugin.CurCombat:GetCombatTime()
if (combat_time < 6) then
return combat_time
end
end
t = 6
end
return t
end
end
local spells = {cur = 0}
local spell_activity = {}
local buff_activity = {}
local buff_graphic_data = {}
local spell_graphic_data = {}
local power_amount_chart_table = {}
power_amount_chart_table.max_value = 0
DpsTuningPlugin.FinishedAt = 0
function DpsTuningPlugin.RefreshSpells()
if (DpsTuningPlugin.db.SpellBarsShowType == 1) then --> execution activity dps
local now = ClockTime()
for spellid, spelltable in pairs (DpsTuningPlugin.CurPlayer:GetActorSpells()) do
local this = spell_activity [spellid]
if (not this) then
local t = {}
t.total = spelltable.total
t.time = ClockTime()
t.start = t.time
t.tempo_end = nil
t.lastevent = t.time
spell_activity [spellid] = t
this = t
else
local lastdamage = this.total
if (lastdamage ~= spelltable.total) then
this.lastevent = now
end
if (this.lastevent+6 < now) then
--hold
if (not this.onhold) then
this.delay = this.lastevent
if (this.delay < this.start) then
this.delay = this.start
end
this.onhold = true
end
else
--exec
if (this.onhold) then
local diff = now - this.delay - 2
if (diff > 0) then
this.start = this.start + diff
end
this.onhold = nil
end
end
this.total = spelltable.total
end
end
local i = 0
for spellid, spelltable in pairs (spell_activity) do
i = i + 1
if (not spells [i]) then
spells [i] = {}
end
spells [i][1] = spellid
spells [i][2] = spelltable.total
spells [i][3] = DpsTuningPlugin.GetActivityTime (spelltable, now)
spells [i][4] = spells [i][2] / spells [i][3] --adps
end
spells.cur = i
for o = #spells, i+1, -1 do
spells [o][1] = 0
spells [o][2] = 0
spells [o][3] = 0
spells [o][4] = 0
end
table.sort (spells, DpsTuningPlugin.Sort4)
DpsTuningPlugin.SpellList = spells
DpsTuningPlugin.SpellScroll:Update()
elseif (DpsTuningPlugin.db.SpellBarsShowType == 2) then --> player activity dps
local player_time = DpsTuningPlugin.CurPlayer:Tempo()
local i = 0
for spellid, spelltable in pairs (DpsTuningPlugin.CurPlayer:GetActorSpells()) do
i = i + 1
if (not spells [i]) then
spells [i] = {}
end
spells [i][1] = spellid
spells [i][2] = spelltable.total
spells [i][3] = spelltable.total/player_time
end
spells.cur = i
for o = #spells, i+1, -1 do
spells [o][1] = 0
spells [o][2] = 0
spells [o][3] = 0
spells [o][4] = 0
end
table.sort (spells, DpsTuningPlugin.Sort3)
DpsTuningPlugin.SpellList = spells
DpsTuningPlugin.SpellScroll:Update()
elseif (DpsTuningPlugin.db.SpellBarsShowType == 3) then --> spell damage
local i = 0
for spellid, spelltable in pairs (DpsTuningPlugin.CurPlayer:GetActorSpells()) do
i = i + 1
if (not spells [i]) then
spells [i] = {}
end
spells [i][1] = spellid
spells [i][2] = spelltable.total
end
spells.cur = i
for o = #spells, i+1, -1 do
spells [o][1] = 0
spells [o][2] = 0
spells [o][3] = 0
spells [o][4] = 0
end
table.sort (spells, DpsTuningPlugin.Sort2)
DpsTuningPlugin.SpellList = spells
DpsTuningPlugin.SpellScroll:Update()
end
end
function update_scroll (self)
local spells = DpsTuningPlugin.SpellList
if (not spells) then
for bar_index = 1, 9 do
local bar = DpsTuningPlugin.SpellBars [bar_index]
bar:Hide()
end
return
end
local offset = FauxScrollFrame_GetOffset (self)
local amt = 0
for index, spell in ipairs (spells) do
if (spell[2] > 0) then
amt = amt + 1
end
end
for bar_index = 1, 9 do
local data = spells [bar_index + offset]
local bar = DpsTuningPlugin.SpellBars [bar_index]
if (DpsTuningPlugin.db.SpellBarsShowType == 1) then --> execution activity dps
if (data and data[3] > 0) then
local name, _, icon = _GetSpellInfo (data [1])
bar.icon = icon
bar.lefttext = name
bar.righttext = DpsTuningPlugin:comma_value (data [2]) .. " (" .. data [3] .. ", " .. DpsTuningPlugin:ToK2 (floor (data [4])) .. ")"
bar.spellid = data [1]
bar:Show()
else
bar:Hide()
end
elseif (DpsTuningPlugin.db.SpellBarsShowType == 2) then --> player activity dps
if (data and data[2] > 0) then
local name, _, icon = _GetSpellInfo (data [1])
bar.icon = icon
bar.lefttext = name
bar.righttext = DpsTuningPlugin:comma_value (data [2]) .. " (" .. DpsTuningPlugin:ToK2 (floor (data [3])) .. ")"
bar.spellid = data [1]
bar:Show()
else
bar:Hide()
end
elseif (DpsTuningPlugin.db.SpellBarsShowType == 3) then --> spell damage
local total = DpsTuningPlugin.CurPlayer.total
if (data and data[2] > 0) then
local name, _, icon = _GetSpellInfo (data [1])
bar.icon = icon
bar.lefttext = name
bar.righttext = DpsTuningPlugin:comma_value (data [2]) .. " (" .. floor (data[2] / total * 100) .. "%)"
bar.spellid = data [1]
bar:Show()
else
bar:Hide()
end
end
end
FauxScrollFrame_Update (self, amt, 9, 15)
end
function DpsTuningPlugin:BuildSummaryPanel()
--total damage
local damage1 = fw:CreateLabel (SDF, "Damage:")
local damage2 = fw:CreateLabel (SDF, "")
damage1:SetPoint ("topleft", SDF, "topleft", 2, -165)
damage2:SetPoint ("left", damage1, "right", 2, 0)
DpsTuningPlugin.total_damage = damage2
--activity dps
local a_dps1 = fw:CreateLabel (SDF, "Dps:")
local a_dps2 = fw:CreateLabel (SDF, "")
a_dps1:SetPoint ("topleft", SDF, "topleft", 2, -180)
a_dps2:SetPoint ("left", a_dps1, "right", 2, 0)
DpsTuningPlugin.activity_dps = a_dps2
--timer
local timer1 = fw:CreateLabel (SDF, "Time:")
local timer2 = fw:CreateLabel (SDF, "")
timer1:SetPoint ("topleft", SDF, "topleft", 2, -195)
timer2:SetPoint ("left", timer1, "right", 2, 0)
DpsTuningPlugin.time_elapsed = timer2
--power
local power1 = fw:CreateLabel (SDF, "Power:")
local power2 = fw:CreateLabel (SDF, "", 15, "orange")
power1:SetPoint ("topleft", SDF, "topleft", 2, -215)
power2:SetPoint ("left", power1, "right", 2, 0)
DpsTuningPlugin.power_amount = power2
end
function DpsTuningPlugin:BuildHeader()
local on_select_spell_type = function (_, _, type_number)
DpsTuningPlugin.db.SpellBarsShowType = type_number
DpsTuningPlugin:UpdateTick()
end
local icon = [[Interface\COMMON\friendship-FistOrc]]
local spell_type_options = {
{value = 1, label = "Execution Activity Dps", desc = "Oder and show the dps following the spell individual activity time.", onclick = on_select_spell_type, icon = icon},
{value = 2, label = "Player Activity Dps", desc = "Order the spells using your activity time to measure the dps for each spell.", onclick = on_select_spell_type, icon = icon},
{value = 3, label = "Damage", desc = "Order the spells following the damage done by each one.", onclick = on_select_spell_type, icon = icon},
}
local select_spell_type = function()
return spell_type_options
end
local dropdown = fw:CreateDropDown (SDF, select_spell_type, DpsTuningPlugin.db.SpellBarsShowType, 160, 18)
local label = fw:CreateLabel (SDF, "Dps Format:")
label:SetPoint (2, -4)
dropdown:SetPoint ("left", label, "right", 2, -1)
end
DpsTuningPlugin.AuraBlocks = {}
local aura_onenter = function (self, capsule)
self:SetBackdropBorderColor (1, 1, 0, 1)
capsule.icontexture.alpha = 1
local buff = capsule.buff
if (buff) then
GameCooltip:Reset()
GameCooltip:SetOwner (self)
GameCooltip:SetType ("tooltip")
DpsTuningPlugin:CooltipPreset (2)
local name, _, icon = _GetSpellInfo (buff.spellid)
GameCooltip:AddLine (name, "", 1, "orange", nil, 13, "Arrial Narrow")
GameCooltip:AddIcon (icon)
GameCooltip:AddLine ("")
local minutos, segundos = floor (buff.uptime/60), floor (buff.uptime%60)
GameCooltip:AddLine ("Uptime:", minutos .. "m " .. segundos .. "s", 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Percent:", _cstr ("%.1f", buff.uptime/DpsTuningPlugin.CurPlayer:Tempo()*100) .. "%", 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:SetOption ("AlignAsBlizzTooltip", true)
GameCooltip:Show()
end
end
local aura_onleave = function (self, capsule)
self:SetBackdropBorderColor (1, 1, 1, 1)
capsule.icontexture.alpha = 0.9
GameCooltip:Hide()
end
local aura_onenter2 = function (self, capsule)
aura_onenter (capsule.block.widget, capsule.block)
end
local aura_onleave2 = function (self, capsule)
aura_onleave (capsule.block.widget, capsule.block)
end
local AuraOnClick = function (block)
if (block.buff) then
block.buff.disabled = not block.buff.disabled
if (block.buff.disabled) then
block.X:Show()
else
block.X:Hide()
end
end
end
function DpsTuningPlugin:BuildBuffBlocks()
local auras = fw:CreateLabel (SDF, "Auras (click to disable):")
auras:SetPoint (170, -165)
local coords = {0.1, 0.9, 0.1, 0.9}
local size = 26
local color = {.7, .7, .7}
for i = 1, 3 do
local block = fw:CreatePanel (SDF, 32, 32)
block:SetFrameLevel (SDF:GetFrameLevel()+2)
block:SetPoint (170 + ((i-1) * 36), -180)
block:SetHook ("OnEnter", aura_onenter)
block:SetHook ("OnLeave", aura_onleave)
block.icontexture = fw:CreateImage (block, nil, size, size, "border", coords)
block.icontexture:SetPoint ("center", block, "center")
block.icontexture.alpha = 0.9
block.icontexture:SetVertexColor (unpack (color))
block.texttime = fw:CreateLabel (block, "", 16, "yellow", "GameFontNormal", nil, nil, "artwork")
block.texttime:SetPoint ("center", block, "center")
block.X = fw:CreateImage (block, [[Interface\Glues\LOGIN\Glues-CheckBox-Check]], size*1.1, size*1.1, "overlay")
block.X:SetPoint ("center", block, "center")
block.X:Hide()
block.button = fw:CreateButton (block, AuraOnClick, 32, 32, "", block)
block.button:SetPoint ("center", box, "center")
block.button:SetHook ("OnEnter", aura_onenter2)
block.button:SetHook ("OnLeave", aura_onleave2)
block.button.block = block
tinsert (DpsTuningPlugin.AuraBlocks, block)
end
for i = 1, 3 do
local block = fw:CreatePanel (SDF, 32, 32)
block:SetFrameLevel (SDF:GetFrameLevel()+2)
block:SetPoint (170 + ((i-1) * 36), -220)
block:SetHook ("OnEnter", aura_onenter)
block:SetHook ("OnLeave", aura_onleave)
block.icontexture = fw:CreateImage (block, nil, size, size, "border", coords)
block.icontexture:SetPoint ("center", block, "center")
block.icontexture.alpha = 0.9
block.icontexture:SetVertexColor (unpack (color))
block.texttime = fw:CreateLabel (block, "", 16, "yellow", "GameFontNormal", nil, nil, "artwork")
block.texttime:SetPoint ("center", block, "center")
block.X = fw:CreateImage (block, [[Interface\Glues\LOGIN\Glues-CheckBox-Check]], size*1.1, size*1.1, "overlay")
block.X:SetPoint ("center", block, "center")
block.X:Hide()
block.button = fw:CreateButton (block, AuraOnClick, 32, 32, "", block)
block.button:SetPoint ("center", box, "center")
block.button:SetHook ("OnEnter", aura_onenter2)
block.button:SetHook ("OnLeave", aura_onleave2)
block.button.block = block
tinsert (DpsTuningPlugin.AuraBlocks, block)
end
for i = 1, 3 do
local block = fw:CreatePanel (SDF, 32, 32)
block:SetFrameLevel (SDF:GetFrameLevel()+2)
block:SetPoint (170 + ((i-1) * 36), -260)
block:SetHook ("OnEnter", aura_onenter)
block:SetHook ("OnLeave", aura_onleave)
block.icontexture = fw:CreateImage (block, nil, size, size, "border", coords)
block.icontexture:SetPoint ("center", block, "center")
block.icontexture.alpha = 0.9
block.icontexture:SetVertexColor (unpack (color))
block.texttime = fw:CreateLabel (block, "", 16, "yellow", "GameFontNormal", nil, nil, "artwork")
block.texttime:SetPoint ("center", block, "center")
block.X = fw:CreateImage (block, [[Interface\Glues\LOGIN\Glues-CheckBox-Check]], size*1.1, size*1.1, "overlay")
block.X:SetPoint ("center", block, "center")
block.X:Hide()
block.button = fw:CreateButton (block, AuraOnClick, 32, 32, "", block)
block.button:SetPoint ("center", box, "center")
block.button:SetHook ("OnEnter", aura_onenter2)
block.button:SetHook ("OnLeave", aura_onleave2)
block.button.block = block
tinsert (DpsTuningPlugin.AuraBlocks, block)
end
end
function DpsTuningPlugin:ClearBuffBlocks()
for index, block in ipairs (DpsTuningPlugin.AuraBlocks) do
block.buff = nil
block.icontexture.texture = nil
block.texttime.text = ""
end
end
function DpsTuningPlugin:UpdateBuffBlocks()
for index, block in ipairs (DpsTuningPlugin.AuraBlocks) do
if (block.buff) then
if (block.buff.actived) then
block.texttime.text = block.buff.uptime + (ClockTime() - block.buff.actived_at)
else
block.texttime.text = block.buff.uptime
end
end
end
end
function DpsTuningPlugin:EnableAuraBlock (block_number, buff_table)
if (block_number <= 9) then
local block = DpsTuningPlugin.AuraBlocks [block_number]
block.icontexture.texture = select (3, _GetSpellInfo (buff_table.spellid))
block.buff = buff_table
end
end
function DpsTuningPlugin:TrackBuffsAtEnd()
for buffIndex = 1, 41 do
local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellid = UnitAura ("player", buffIndex, nil, "HELPFUL")
local buff_table = buff_activity [spellid]
if (buff_table) then
if (buff_table.actived_at and buff_table.actived) then
buff_table.uptime = buff_table.uptime + ClockTime() - buff_table.actived_at
end
buff_table.actived = false
buff_table.actived_at = nil
DpsTuningPlugin:BuffChartEnd (spellid)
end
end
end
function DpsTuningPlugin:BuffChartStart (spellid)
local buff_chart = buff_graphic_data [spellid]
if (not buff_chart) then
buff_chart = {}
buff_graphic_data [spellid] = buff_chart
end
local bufftime = {time_start = DpsTuningPlugin.CurTick, time_end = 0}
tinsert (buff_chart, bufftime)
end
function DpsTuningPlugin:BuffChartEnd (spellid)
local buff_chart = buff_graphic_data [spellid]
if (buff_chart) then
local bufftime = buff_chart [#buff_chart]
bufftime.time_end = DpsTuningPlugin.CurTick
end
end
function DpsTuningPlugin:TrackBuffsAtStart()
for buffIndex = 1, 41 do
local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellid = UnitAura ("player", buffIndex, nil, "HELPFUL")
if (name and unitCaster == "player" and duration > 0 and expirationTime > 0 and not shouldConsolidate) then
local buff_table = buff_activity [spellid]
if (not buff_table) then
buff_table = {uptime = 0, actived = false, activedamt = 0, block = buff_activity.next, spellid = spellid, procs = {}}
buff_activity.next = buff_activity.next + 1
buff_activity [spellid] = buff_table
end
buff_table.actived = true
buff_table.activedamt = 1
buff_table.actived_at = ClockTime()
tinsert (buff_table.procs, DpsTuningPlugin.CurCombat:GetCombatTime())
DpsTuningPlugin:BuffChartStart (spellid)
DpsTuningPlugin:EnableAuraBlock (buff_table.block, buff_table)
end
end
end
function DpsTuningPlugin:AuraApplied (time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
if (tipo == "BUFF") then
local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellid = UnitAura ("player", spellname, nil, "HELPFUL")
if (name and unitCaster == "player" and duration > 0 and expirationTime > 0 and not shouldConsolidate) then
local buff_table = buff_activity [spellid]
if (not buff_table) then
buff_table = {uptime = 0, actived = false, activedamt = 0, block = buff_activity.next, spellid = spellid, procs = {}}
buff_activity.next = buff_activity.next + 1
buff_activity [spellid] = buff_table
end
buff_table.actived = true
buff_table.activedamt = buff_table.activedamt + 1
buff_table.actived_at = ClockTime()
tinsert (buff_table.procs, DpsTuningPlugin.CurCombat:GetCombatTime())
DpsTuningPlugin:BuffChartStart (spellid)
DpsTuningPlugin:EnableAuraBlock (buff_table.block, buff_table)
end
end
end
function DpsTuningPlugin:AuraRefresh (time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
if (tipo == "BUFF") then
local buff_table = buff_activity [spellid]
if (buff_table) then
if (buff_table.actived_at and buff_table.actived) then
buff_table.uptime = buff_table.uptime + ClockTime() - buff_table.actived_at
end
buff_table.actived_at = ClockTime()
buff_table.actived = true
end
end
end
function DpsTuningPlugin:AuraRemoved (time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
if (tipo == "BUFF") then
local buff_table = buff_activity [spellid]
if (buff_table) then
if (buff_table.actived_at and buff_table.actived) then
buff_table.uptime = buff_table.uptime + ClockTime() - buff_table.actived_at
end
buff_table.actived = false
buff_table.actived_at = nil
tinsert (buff_table.procs, DpsTuningPlugin.CurCombat:GetCombatTime())
DpsTuningPlugin:BuffChartEnd (spellid)
end
end
end
local misscolor = {1, 0.3, 0.3}
local bar_onenter_script = function (self, capsule)
if (not DpsTuningPlugin.CurPlayer or not capsule.spellid) then
return
end
GameCooltip:Reset()
GameCooltip:SetOwner (self)
GameCooltip:SetType ("tooltip")
DpsTuningPlugin:CooltipPreset (2)
local spell = DpsTuningPlugin.CurPlayer:GetSpell (capsule.spellid)
local name, _, icon = _GetSpellInfo (capsule.spellid)
GameCooltip:AddLine (name, "", 1, "orange", nil, 13, "Arrial Narrow")
GameCooltip:AddIcon (icon)
GameCooltip:AddLine ("")
GameCooltip:AddLine ("Damage:", DpsTuningPlugin:comma_value (spell.total), 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Hits:", spell.counter, 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Dps:", DpsTuningPlugin:ToK2 (floor (spell.total / DpsTuningPlugin.CurPlayer:Tempo())), 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Percent:", _cstr ("%.1f", spell.total / DpsTuningPlugin.CurPlayer.total_without_pet * 100) .. "%", 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("")
GameCooltip:AddLine ("Average Damage:", DpsTuningPlugin:comma_value (floor (spell.total / spell.counter)), 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Min Hit:", DpsTuningPlugin:comma_value (spell.n_min), 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("Max Hit:", DpsTuningPlugin:comma_value (math.max (spell.n_max, spell.c_max)), 1, "white", nil, 10, "Arrial Narrow")
GameCooltip:AddLine ("")
GameCooltip:AddLine ("Critical Hits:", _cstr ("%.1f", spell.c_amt / spell.counter * 100) .. "%", 1, "white", nil, 10, "Arrial Narrow")
if (spell.c_amt > 0) then
GameCooltip:AddLine ("Critical Average Damage:", DpsTuningPlugin:comma_value (floor (spell.c_dmg / spell.c_amt)), 1, "white", nil, 10, "Arrial Narrow")
else
GameCooltip:AddLine ("Critical Average Damage:", "0", 1, "white", nil, 10, "Arrial Narrow")
end
--uptime
local misc = DpsTuningPlugin.CurCombat (DETAILS_ATTRIBUTE_MISC, DpsTuningPlugin.playername)
if (misc) then
local debuff_uptime = misc.debuff_uptime
if (debuff_uptime) then
local this_spell = misc.debuff_uptime_spells._ActorTable [capsule.spellid]
if (this_spell) then
GameCooltip:AddLine ("")
local uptime = this_spell.uptime
local minutos, segundos = floor (uptime/60), floor (uptime%60)
GameCooltip:AddLine ("Uptime:", minutos .. "m " .. segundos .. "s", 1, "white", nil, 10, "Arrial Narrow")
end
end
end
--miss
GameCooltip:AddLine ("")
local miss = spell ["MISS"]
local parry = spell ["PARRY"]
local dodge = spell ["DODGE"]
if (miss) then
GameCooltip:AddLine ("Miss:", miss .. " (" .. _cstr ("%.1f", miss / spell.counter * 100) .. "%)", 1, misscolor, nil, 10, "Arrial Narrow")
end
if (parry) then
GameCooltip:AddLine ("Parry:", parry .. " (" .. _cstr ("%.1f", parry / spell.counter * 100) .. "%)", 1, misscolor, nil, 10, "Arrial Narrow")
end
if (dodge) then
GameCooltip:AddLine ("Dodge:", dodge .. " (" .. _cstr ("%.1f", dodge / spell.counter * 100) .. "%)", 1, misscolor, nil, 10, "Arrial Narrow")
end
if (spell.g_amt > 0) then
GameCooltip:AddLine ("Glancing:", spell.g_amt .. " (" .. _cstr ("%.1f", spell.g_amt / spell.counter * 100) .. "%)", 1, misscolor, nil, 10, "Arrial Narrow")
end
GameCooltip:SetOption ("AlignAsBlizzTooltip", true)
GameCooltip:Show()
end
local bar_onleanve_script = function (self)
GameCooltip:Hide()
end
function DpsTuningPlugin:BuildSpellBars()
DpsTuningPlugin.SpellBars = {}
local scrollbar = CreateFrame ("scrollframe", "DpsTuningPluginSpellsFauxScroll", DpsTuningPlugin.Frame, "FauxScrollFrameTemplate")
scrollbar:SetSize (275, 150)
scrollbar:SetPoint ("topleft", DpsTuningPlugin.Frame, "topleft", 1, 0)
scrollbar:SetScript ("OnVerticalScroll", function (self, offset) FauxScrollFrame_OnVerticalScroll (self, offset, 15, update_scroll) end)
scrollbar.Update = update_scroll
DpsTuningPlugin.SpellScroll = scrollbar
for i = 1, 9 do
local bar = fw:CreateBar (DpsTuningPlugin.Frame, "Skyline", 275, 14, 100)
bar.color = DpsTuningPlugin.BarColor
bar.textfont = "Arial Narrow"
bar.textsize = 10
bar:SetPoint ("topleft", DpsTuningPlugin.Frame, "topleft", 1, ((i-1) * -15) - 20)
bar:SetHook ("OnEnter", bar_onenter_script)
bar:SetHook ("OnLeave", bar_onleanve_script)
tinsert (DpsTuningPlugin.SpellBars, bar)
end
end
local colors = {
{1, 1, 1}, --white
{1, 0.8, .1}, --orange
{.3, .3, 1}, --blue
{1, .3, .3}, --red
{.3, 1, .3}, --green
{.3, 1, 1}, --cyan
{1, 0.75, 0.79}, --pink
{0.98, 0.50, 0.44}, --salmon
{0.75, 0.75, 0.75}, --silver
{0.60, 0.80, 0.19}, --yellow
{1, .3, 1}, --magenta
}
local linetypes = {"line", "smallline", "thinline"}
function DpsTuningPlugin:BuildChartPanels()
local chart_panel = fw:CreateChartPanel (UIParent, GetScreenWidth()-200, 500)
chart_panel:SetPoint ("topleft", UIParent, "topleft", 100, -100)
chart_panel:SetTitle ("Dps Tuning")
chart_panel:SetFrameStrata ("DIALOG")
chart_panel:CanMove (true)
tinsert (UISpecialFrames, chart_panel:GetName())
chart_panel:Hide()
local open_chart_panel = function()
chart_panel:Reset()
local player_dps = DpsTuningPlugin.CurCombat:GetTimeData ("Player Damage Done")
local combat_time = DpsTuningPlugin.CurCombat:GetCombatTime()
chart_panel:SetTime (combat_time)
chart_panel:SetScale (player_dps.max_value)
chart_panel:AddLine (player_dps, {1, 1, 1, 1}, "Your Damage", combat_time, "line")
chart_panel:AddLine (power_amount_chart_table, {1, .4, .4, 1}, "Spell/Attack Power (x3)", combat_time)
chart_panel:Show()
end
local open_chart_panel2 = function()
chart_panel:Reset()
local GraphicSmoothLevel = 1
--> we need to copy because of the addition of spells with the same icon.
local spell_graphic_data = table_deepcopy (spell_graphic_data)
local consolidate = {}
for spellid, data in pairs (spell_graphic_data) do
local spellname, _, spellicon = _GetSpellInfo (spellid)
if (consolidate [spellicon]) then
local data2 = consolidate [spellicon][3]
local new_max_value = consolidate [spellicon][4]
for i = 1, #data do
data2[i] = data2[i] + data[i] --can be the same table as the default one or it just will add and add over again.
if (data2[i] > new_max_value) then
new_max_value = data2[i]
end
end
consolidate [spellicon][4] = new_max_value
local spelldamage = DpsTuningPlugin.CurPlayer:GetSpell (spellid).total
consolidate [spellicon][5] = consolidate [spellicon][5] + spelldamage
if (string.len (spellname) < string.len (consolidate [spellicon][2])) then
consolidate [spellicon][2] = spellname
end
else
consolidate [spellicon] = {spellid, spellname, data, data.max_value, DpsTuningPlugin.CurPlayer:GetSpell (spellid).total}
end
end
local order = {}
for spellid, data in pairs (consolidate) do
tinsert (order, data)
end
table.sort (order, DpsTuningPlugin.Sort1)
local player_total_damage = DpsTuningPlugin.CurPlayer.total
local max = 0
for index, data in ipairs (order) do
local spellid = data[1]
local spellname = data[2]
local chart_data = data[3]
local max_value = data[4]
if (max_value > max) then
max = max_value
end
local spelldamage = data[5]
if (spelldamage/player_total_damage*100 > 5) then
if (colors [index]) then
chart_panel:AddLine (chart_data, colors [index], spellname, DpsTuningPlugin.CurCombat:GetCombatTime(), nil, GraphicSmoothLevel)
end
end
end
chart_panel:SetTime (DpsTuningPlugin.CurCombat:GetCombatTime())
chart_panel:SetScale (max)
chart_panel:Show()
end
local open_chart_panel3 = function()
chart_panel:Reset()
local player_dps = DpsTuningPlugin.CurCombat:GetTimeData ("Player Damage Done")
chart_panel:AddLine (player_dps, {1, 1, 1, 1}, "Your Damage", DpsTuningPlugin.CurCombat:GetCombatTime(), "line")
chart_panel:SetTime (DpsTuningPlugin.CurCombat:GetCombatTime())
chart_panel:SetScale (player_dps.max_value)
local index = 1
for spellid, bufftable in pairs (buff_activity) do
if (type (bufftable) == "table") then
if (not bufftable.disabled) then
local proctable = bufftable.procs
local spellname, _, spellicon = _GetSpellInfo (spellid)
chart_panel:AddOverlay (bufftable.procs, colors [index], spellname, spellicon)
index = index + 1
end
end
end
chart_panel:Show()
end
local button_open = fw:CreateButton (SDF, open_chart_panel, 120, 18, "Damage x Power", nil, nil, nil, "OpenGraphicButton")
button_open:InstallCustomTexture (nil, nil, nil, nil, true)
button_open:SetPoint ("bottomleft", SDF, "bottomleft", 2, 3)
button_open:Disable()
local button_open2 = fw:CreateButton (SDF, open_chart_panel2, 120, 18, "All Spells", nil, nil, nil, "OpenGraphicButton2")
button_open2:InstallCustomTexture (nil, nil, nil, nil, true)
button_open2:SetPoint ("bottom", button_open, "top", 0, 3)
button_open2:Disable()
local button_open3 = fw:CreateButton (SDF, open_chart_panel3, 120, 18, "Aura Procs", nil, nil, nil, "OpenGraphicButton3")
button_open3:InstallCustomTexture (nil, nil, nil, nil, true)
button_open3:SetPoint ("bottom", button_open2, "top", 0, 3)
button_open3:Disable()
end
function DpsTuningPlugin:UpdateSummary()
if (DpsTuningPlugin.CurPlayer) then
DpsTuningPlugin.total_damage.text = DpsTuningPlugin:comma_value (floor (DpsTuningPlugin.CurPlayer.total))
DpsTuningPlugin.activity_dps.text = DpsTuningPlugin:ToK2 (floor (DpsTuningPlugin.CurPlayer.total / DpsTuningPlugin.CurPlayer:Tempo()))
DpsTuningPlugin.time_elapsed.text = _cstr ("%.1f", GetTime() - DpsTuningPlugin.StartTime)
DpsTuningPlugin.power_amount.text = DpsTuningPlugin:comma_value (GetSpellBonusDamage (DpsTuningPlugin.PowerType))
end
end
function DpsTuningPlugin:UpdateMiliTick()
DpsTuningPlugin:UpdateSummary()
end
function DpsTuningPlugin:UpdateTick()
--check for current player
if (not DpsTuningPlugin.CurPlayer) then
if (not DpsTuningPlugin.CurCombat) then
return
end
DpsTuningPlugin.CurPlayer = DpsTuningPlugin.CurCombat (DETAILS_ATTRIBUTE_DAMAGE, DpsTuningPlugin.playername)
if (not DpsTuningPlugin.CurPlayer) then
return
end
if (DpsTuningPlugin.CurPlayer and not DpsTuningPlugin.MiliSecTick) then
DpsTuningPlugin.MiliSecTick = DpsTuningPlugin:ScheduleRepeatingTimer ("UpdateMiliTick", 0.1)
end
end
DpsTuningPlugin.CurTick = DpsTuningPlugin.CurTick + 1
--refresh bars
DpsTuningPlugin.RefreshSpells()
--refresh buff blocks
DpsTuningPlugin:UpdateBuffBlocks()
--get spells damages
DpsTuningPlugin:ChartDataTick()
end
function DpsTuningPlugin:ChartDataTick()
local power = math.max (GetSpellBonusDamage (1), GetSpellBonusDamage (2)) * 3
tinsert (power_amount_chart_table, power)
if (power_amount_chart_table.max_value < power) then
power_amount_chart_table.max_value = power
end
for spellid, spelltable in pairs (DpsTuningPlugin.CurPlayer:GetActorSpells()) do
if (spelltable.total > 0) then
local chart_table = spell_graphic_data [spelltable.id]
if (not chart_table) then
local new_chart_data = {}
new_chart_data.last_value = 0
new_chart_data.max_value = 0
for i = 1, DpsTuningPlugin.CurTick-1 do
tinsert (new_chart_data, 0)
end
spell_graphic_data [spelltable.id] = new_chart_data
chart_table = new_chart_data
end
local cvalue = spelltable.total - chart_table.last_value
if (chart_table.max_value < cvalue) then
chart_table.max_value = cvalue
end
tinsert (chart_table, cvalue)
chart_table.last_value = spelltable.total
end
end
end
function DpsTuningPlugin:OnDataReset (...)
DpsTuningPlugin.CurCombat = nil
DpsTuningPlugin.CurPlayer = nil
table.wipe (spell_activity)
table.wipe (buff_activity)
table.wipe (spell_graphic_data)
table.wipe (buff_graphic_data)
table.wipe (power_amount_chart_table)
DpsTuningPlugin:ClearBuffBlocks()
SDF.OpenGraphicButton:Disable()
SDF.OpenGraphicButton2:Disable()
SDF.OpenGraphicButton3:Disable()
if (DpsTuningPlugin.SpellBars) then
for bar_index = 1, 9 do
local bar = DpsTuningPlugin.SpellBars [bar_index]
if (bar) then
bar:Hide()
end
end
end
DpsTuningPlugin.FinishedAt = 0
end
function DpsTuningPlugin:OnCombatStart (...)
if (DpsTuningPlugin.FinishedAt+10 > ClockTime()) then
DpsTuningPlugin:Msg ("Ignoring combat start: a combat just finished.")
DpsTuningPlugin.FinishedAt = ClockTime()
return
end
DpsTuningPlugin.CurCombat = ...
DpsTuningPlugin.CurPlayer = DpsTuningPlugin.CurCombat (DETAILS_ATTRIBUTE_DAMAGE, DpsTuningPlugin.playername)
table.wipe (spell_activity)
table.wipe (buff_activity)
table.wipe (spell_graphic_data)
table.wipe (buff_graphic_data)
table.wipe (power_amount_chart_table)
buff_activity.next = 1
power_amount_chart_table.max_value = 0
DpsTuningPlugin:ClearBuffBlocks()
DpsTuningPlugin:TrackBuffsAtStart()
--> enable buff parser
SDF:RegisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
DpsTuningPlugin.LastDps = 0
DpsTuningPlugin.CurTick = 0
DpsTuningPlugin.StartTime = GetTime()
DpsTuningPlugin.TimerTick = DpsTuningPlugin:ScheduleRepeatingTimer ("UpdateTick", 1)
if (DpsTuningPlugin.CurPlayer and not DpsTuningPlugin.MiliSecTick) then
DpsTuningPlugin.MiliSecTick = DpsTuningPlugin:ScheduleRepeatingTimer ("UpdateMiliTick", 0.1)
end
SDF.OpenGraphicButton:Disable()
SDF.OpenGraphicButton2:Disable()
SDF.OpenGraphicButton3:Disable()
end
function DpsTuningPlugin:OnCombatEnd (...)
local combat = ...
if (DpsTuningPlugin.CurCombat and DpsTuningPlugin.CurCombat == combat) then
local now = ClockTime()
DpsTuningPlugin.FinishedAt = now
--> close spells
for spellid, spelltable in pairs (spell_activity) do
if (spelltable.onhold) then
local diff = now - spelltable.delay - 2
if (diff > 0) then
spelltable.start = spelltable.start + diff
end
spelltable.onhold = nil
end
spelltable.tempo_end = now
end
--> close buffs
DpsTuningPlugin:TrackBuffsAtEnd()
--> turn off buff parser
SDF:UnregisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
--> cancel tick
DpsTuningPlugin:CancelTicker()
SDF.OpenGraphicButton:Enable()
SDF.OpenGraphicButton2:Enable()
SDF.OpenGraphicButton3:Enable()
end
end
function DpsTuningPlugin:CancelTicker()
if (DpsTuningPlugin.TimerTick) then
DpsTuningPlugin:CancelTimer (DpsTuningPlugin.TimerTick)
DpsTuningPlugin.TimerTick = nil
end
if (DpsTuningPlugin.MiliSecTick) then
DpsTuningPlugin:CancelTimer (DpsTuningPlugin.MiliSecTick)
DpsTuningPlugin.MiliSecTick = nil
end
end
end
function DpsTuningPlugin:OnEvent (_, event, ...)
if (event == "COMBAT_LOG_EVENT_UNFILTERED") then
local time1, token, hidding, who_serial, who_name, who_flags, who_flags2, alvo_serial, alvo_name, alvo_flags, alvo_flags2, spellid, spellname, spellschool, tipo, amount = select (1, ...)
if (who_name == DpsTuningPlugin.playername and alvo_name == DpsTuningPlugin.playername) then
if (token == "SPELL_AURA_APPLIED") then
DpsTuningPlugin:AuraApplied (time1, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
elseif (token == "SPELL_AURA_REMOVED") then
DpsTuningPlugin:AuraRemoved (time1, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
elseif (token == "SPELL_AURA_REFRESH") then
DpsTuningPlugin:AuraRefresh (time1, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spellschool, tipo, amount)
end
end
elseif (event == "ADDON_LOADED") then
local AddonName = select (1, ...)
if (AddonName == "Details_DpsTuning") then
if (_G._detalhes) then
--> create main plugin object
CreatePluginFrames()
local MINIMAL_DETAILS_VERSION_REQUIRED = 28
local default_settings = {
SpellBarsShowType = 1,
}
--> Install plugin inside details
local install = _G._detalhes:InstallPlugin ("SOLO", "Dps Tuning", "Interface\\Icons\\Ability_Racial_RocketBarrage", DpsTuningPlugin, "DETAILS_PLUGIN_DPS_TUNING", MINIMAL_DETAILS_VERSION_REQUIRED, "Details! Team", "v1.1", default_settings)
if (type (install) == "table" and install.error) then
print (install.error)
end
--> Register needed events
_G._detalhes:RegisterEvent (DpsTuningPlugin, "COMBAT_PLAYER_ENTER")
_G._detalhes:RegisterEvent (DpsTuningPlugin, "COMBAT_PLAYER_LEAVE")
_G._detalhes:RegisterEvent (DpsTuningPlugin, "DETAILS_DATA_RESET")
_G._detalhes:RegisterEvent (DpsTuningPlugin, "COMBAT_INVALID")
end
end
end
end