208ede8e6e
- Removed debug chat messages from the dungeon chart. - Framework update to v67.
438 lines
15 KiB
Lua
438 lines
15 KiB
Lua
|
|
|
|
--> dungeon file
|
|
|
|
|
|
|
|
--local pointer to details object
|
|
local Details = _G._detalhes
|
|
local debugmode = false
|
|
|
|
--constants
|
|
local CONST_USE_PLAYER_EDPS = false
|
|
|
|
--> Generate damage chart for mythic dungeon runs
|
|
|
|
--[=[
|
|
The chart table needs to be stored saparated from the combat
|
|
Should the chart data be volatile?
|
|
|
|
--]=]
|
|
|
|
local mythicDungeonCharts = Details:CreateEventListener()
|
|
|
|
function mythicDungeonCharts:Debug (...)
|
|
if (debugmode) then
|
|
print ("Details! DungeonCharts (debug.Alpha " .. Details.build_counter .. "." .. Details.realversion .. " ): ", ...)
|
|
end
|
|
end
|
|
|
|
local addPlayerDamage = function (unitName, unitRealm)
|
|
|
|
--get the combatlog name
|
|
local CLName
|
|
if (unitRealm and unitRealm ~= "") then
|
|
CLName = unitName .. "-" .. unitRealm
|
|
else
|
|
CLName = unitName
|
|
end
|
|
|
|
--get the player data
|
|
local playerData = mythicDungeonCharts.ChartTable.Players [CLName]
|
|
|
|
--if this is the first tick for the player, ignore the damage done on this tick
|
|
--this is done to prevent a tick tick with all the damage the player did on the previous segment
|
|
local bIsFirstTick = false
|
|
|
|
--check if the player data doesn't exists
|
|
if (not playerData) then
|
|
playerData = {
|
|
Name = unitName,
|
|
ChartData = {max_value = 0},
|
|
Class = select (2, UnitClass (CLName)),
|
|
|
|
--spec zero for now, need to retrive later during combat
|
|
Spec = 0,
|
|
|
|
--last damage to calc difference
|
|
LastDamage = 0,
|
|
|
|
--if started a new combat, need to reset the lastdamage
|
|
LastCombatID = -1,
|
|
}
|
|
|
|
mythicDungeonCharts.ChartTable.Players [CLName] = playerData
|
|
bIsFirstTick = true
|
|
end
|
|
|
|
--get the current combat
|
|
local currentCombat = Details:GetCombat (DETAILS_SEGMENTID_CURRENT)
|
|
if (currentCombat) then
|
|
|
|
local isOverallSegment = false
|
|
|
|
local mythicDungeonInfo = currentCombat.is_mythic_dungeon
|
|
if (mythicDungeonInfo) then
|
|
if (mythicDungeonInfo.TrashOverallSegment or mythicDungeonInfo.OverallSegment) then
|
|
isOverallSegment = true
|
|
end
|
|
end
|
|
|
|
if (not isOverallSegment) then
|
|
--check if the combat has changed
|
|
local segmentId = currentCombat.combat_id
|
|
if (segmentId ~= playerData.LastCombatID) then
|
|
playerData.LastDamage = 0
|
|
playerData.LastCombatID = segmentId
|
|
|
|
--mythicDungeonCharts:Debug ("Combat changed for player", CLName)
|
|
end
|
|
|
|
local actorTable = currentCombat:GetActor (DETAILS_ATTRIBUTE_DAMAGE, CLName)
|
|
if (actorTable) then
|
|
--update the player spec
|
|
playerData.Spec = actorTable.spec
|
|
|
|
if (bIsFirstTick) then
|
|
--ignore previous damage
|
|
playerData.LastDamage = actorTable.total
|
|
end
|
|
|
|
--get the damage done
|
|
local damageDone = actorTable.total
|
|
|
|
--check which data is used, dps or damage done
|
|
if (CONST_USE_PLAYER_EDPS) then
|
|
local eDps = damageDone / currentCombat:GetCombatTime()
|
|
|
|
--add the damage to the chart table
|
|
tinsert (playerData.ChartData, eDps)
|
|
--mythicDungeonCharts:Debug ("Added dps for " , CLName, ":", eDps)
|
|
|
|
if (eDps > playerData.ChartData.max_value) then
|
|
playerData.ChartData.max_value = eDps
|
|
end
|
|
else
|
|
--calc the difference and add to the table
|
|
local damageDiff = floor (damageDone - playerData.LastDamage)
|
|
playerData.LastDamage = damageDone
|
|
|
|
--add the damage to the chart table
|
|
tinsert (playerData.ChartData, damageDiff)
|
|
--mythicDungeonCharts:Debug ("Added damage for " , CLName, ":", damageDiff)
|
|
|
|
if (damageDiff > playerData.ChartData.max_value) then
|
|
playerData.ChartData.max_value = damageDiff
|
|
end
|
|
end
|
|
else
|
|
--player still didn't made anything on this combat, so just add zero
|
|
tinsert (playerData.ChartData, 0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local tickerCallback = function (tickerObject)
|
|
|
|
--check if is inside the dungeon
|
|
local inInstance = IsInInstance();
|
|
if (not inInstance) then
|
|
mythicDungeonCharts:OnEndMythicDungeon()
|
|
return
|
|
end
|
|
|
|
--check if still running the dungeon
|
|
if (not mythicDungeonCharts.ChartTable or not mythicDungeonCharts.ChartTable.Running) then
|
|
tickerObject:Cancel()
|
|
return
|
|
end
|
|
|
|
--tick damage
|
|
local totalPlayers = GetNumGroupMembers()
|
|
for i = 1, totalPlayers-1 do
|
|
local unitName, unitRealm = UnitName ("party" .. i)
|
|
if (unitName) then
|
|
addPlayerDamage (unitName, unitRealm)
|
|
end
|
|
end
|
|
|
|
addPlayerDamage (UnitName ("player"))
|
|
end
|
|
|
|
function mythicDungeonCharts:OnBossDefeated()
|
|
|
|
local currentCombat = Details:GetCurrentCombat()
|
|
local segmentType = currentCombat:GetCombatType()
|
|
local bossInfo = currentCombat:GetBossInfo()
|
|
|
|
if (mythicDungeonCharts.ChartTable and mythicDungeonCharts.ChartTable.Running and bossInfo) then
|
|
|
|
local copiedBossInfo = Details:GetFramework().table.copy ({}, bossInfo)
|
|
tinsert (mythicDungeonCharts.ChartTable.BossDefeated, {time() - mythicDungeonCharts.ChartTable.StartTime, copiedBossInfo, currentCombat:GetCombatTime()})
|
|
mythicDungeonCharts:Debug ("Boss defeated, time saved", currentCombat:GetCombatTime())
|
|
else
|
|
if (mythicDungeonCharts.ChartTable.EndTime ~= -1) then
|
|
local now = time()
|
|
--check if the dungeon just ended
|
|
if (mythicDungeonCharts.ChartTable.EndTime + 2 >= now) then
|
|
|
|
if (bossInfo) then
|
|
local copiedBossInfo = Details:GetFramework().table.copy ({}, bossInfo)
|
|
tinsert (mythicDungeonCharts.ChartTable.BossDefeated, {time() - mythicDungeonCharts.ChartTable.StartTime, copiedBossInfo, currentCombat:GetCombatTime()})
|
|
mythicDungeonCharts:Debug ("Boss defeated, time saved, but used time aproximation:", mythicDungeonCharts.ChartTable.EndTime + 2, now, currentCombat:GetCombatTime())
|
|
end
|
|
end
|
|
else
|
|
mythicDungeonCharts:Debug ("Boss defeated, but no chart capture is running")
|
|
end
|
|
end
|
|
end
|
|
|
|
function mythicDungeonCharts:OnStartMythicDungeon()
|
|
|
|
if (not Details.mythic_plus.show_damage_graphic) then
|
|
mythicDungeonCharts:Debug ("Dungeon started, no capturing mythic dungeon chart data, disabled on profile")
|
|
return
|
|
else
|
|
mythicDungeonCharts:Debug ("Dungeon started, new capture started")
|
|
end
|
|
|
|
mythicDungeonCharts.ChartTable = {
|
|
Running = true,
|
|
Players = {},
|
|
ElapsedTime = 0,
|
|
StartTime = time(),
|
|
EndTime = -1,
|
|
DungeonName = "",
|
|
|
|
--store when each boss got defeated in comparison with the StartTime
|
|
BossDefeated = {},
|
|
}
|
|
|
|
mythicDungeonCharts.ChartTable.Ticker = C_Timer.NewTicker (1, tickerCallback)
|
|
|
|
--save the chart for development
|
|
if (debugmode) then
|
|
_detalhes.mythic_plus.last_mythicrun_chart = mythicDungeonCharts.ChartTable
|
|
end
|
|
end
|
|
|
|
function mythicDungeonCharts:OnEndMythicDungeon()
|
|
if (mythicDungeonCharts.ChartTable and mythicDungeonCharts.ChartTable.Running) then
|
|
mythicDungeonCharts.ChartTable.Running = false
|
|
mythicDungeonCharts.ChartTable.ElapsedTime = time() - mythicDungeonCharts.ChartTable.StartTime
|
|
mythicDungeonCharts.ChartTable.EndTime = time()
|
|
mythicDungeonCharts.ChartTable.Ticker:Cancel()
|
|
|
|
local name, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo()
|
|
mythicDungeonCharts.ChartTable.DungeonName = name
|
|
|
|
mythicDungeonCharts:Debug ("Dungeon ended, chart data capture stopped")
|
|
|
|
C_Timer.After (_detalhes.mythic_plus.delay_to_show_graphic or 5, mythicDungeonCharts.ShowChart)
|
|
else
|
|
mythicDungeonCharts:Debug ("Dungeon ended, no chart data was running")
|
|
end
|
|
end
|
|
|
|
mythicDungeonCharts:RegisterEvent ("COMBAT_MYTHICDUNGEON_START", "OnStartMythicDungeon")
|
|
mythicDungeonCharts:RegisterEvent ("COMBAT_MYTHICDUNGEON_END", "OnEndMythicDungeon")
|
|
mythicDungeonCharts:RegisterEvent ("COMBAT_BOSS_DEFEATED", "OnBossDefeated")
|
|
|
|
function mythicDungeonCharts.ShowChart()
|
|
|
|
if (not mythicDungeonCharts.Frame) then
|
|
|
|
mythicDungeonCharts.Frame = CreateFrame ("frame", "DetailsMythicDungeonChartFrame", UIParent)
|
|
local f = mythicDungeonCharts.Frame
|
|
|
|
f:SetSize (1210, 600)
|
|
f:SetPoint ("center", UIParent, "center", 0, 0)
|
|
f:SetFrameStrata ("LOW")
|
|
f:EnableMouse (true)
|
|
f:SetMovable (true)
|
|
f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
f:SetBackdropColor (0, 0, 0, 0.9)
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
|
|
tinsert (UISpecialFrames, "DetailsMythicDungeonChartFrame")
|
|
|
|
--register to libwindow
|
|
local LibWindow = LibStub ("LibWindow-1.1")
|
|
LibWindow.RegisterConfig (f, Details.mythic_plus.mythicrun_chart_frame)
|
|
LibWindow.RestorePosition (f)
|
|
LibWindow.MakeDraggable (f)
|
|
LibWindow.SavePosition (f)
|
|
|
|
f.ChartFrame = Details:GetFramework():CreateChartPanel (f, 1200, 600, "DetailsMythicDungeonChartGraphicFrame")
|
|
f.ChartFrame:SetPoint ("topleft", f, "topleft", 5, 0)
|
|
|
|
f.ChartFrame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
f.ChartFrame:SetBackdropColor (0, 0, 0, 0.0)
|
|
f.ChartFrame:SetBackdropBorderColor (0, 0, 0, 0)
|
|
|
|
f.ChartFrame.CloseButton:Hide()
|
|
|
|
f.BossWidgetsFrame = CreateFrame ("frame", "$parentBossFrames", f)
|
|
f.BossWidgetsFrame:SetFrameLevel (f:GetFrameLevel()+10)
|
|
f.BossWidgetsFrame.Widgets = {}
|
|
|
|
local closeButton = CreateFrame ("button", "$parentCloseButton", f, "UIPanelCloseButton")
|
|
closeButton:GetNormalTexture():SetDesaturated (true)
|
|
closeButton:SetWidth (20)
|
|
closeButton:SetHeight (20)
|
|
closeButton:SetPoint ("topright", f, "topright", 0, -3)
|
|
closeButton:SetFrameLevel (f:GetFrameLevel()+16)
|
|
|
|
function f.ChartFrame.RefreshBossTimeline (self, bossTable, elapsedTime)
|
|
|
|
for i, bossTable in ipairs (mythicDungeonCharts.ChartTable.BossDefeated) do
|
|
|
|
local bossWidget = f.BossWidgetsFrame.Widgets [i]
|
|
if (not bossWidget) then
|
|
local newBossWidget = CreateFrame ("frame", "$parentBossWidget" .. i, f.BossWidgetsFrame)
|
|
newBossWidget:SetSize (64, 32)
|
|
newBossWidget:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
newBossWidget:SetBackdropColor (0, 0, 0, 0.1)
|
|
newBossWidget:SetBackdropBorderColor (0, 0, 0, 0)
|
|
|
|
local bossAvatar = Details:GetFramework():CreateImage (newBossWidget, "", 64, 32, "border")
|
|
bossAvatar:SetPoint ("bottomleft", newBossWidget, "bottomleft", 0, 0)
|
|
newBossWidget.AvatarTexture = bossAvatar
|
|
|
|
local verticalLine = Details:GetFramework():CreateImage (newBossWidget, "", 1, f.ChartFrame.Graphic:GetHeight(), "overlay")
|
|
verticalLine:SetColorTexture (1, 1, 1, 0.3)
|
|
verticalLine:SetPoint ("bottomleft", newBossWidget, "bottomright", 0, 0)
|
|
|
|
local timeText = Details:GetFramework():CreateLabel (newBossWidget)
|
|
timeText:SetPoint ("bottomright", newBossWidget, "bottomright", 0, 0)
|
|
newBossWidget.TimeText = timeText
|
|
|
|
local timeBackground = Details:GetFramework():CreateImage (newBossWidget, "", 30, 12, "artwork")
|
|
timeBackground:SetColorTexture (0, 0, 0, 0.5)
|
|
timeBackground:SetPoint ("topleft", timeText, "topleft", -2, 2)
|
|
timeBackground:SetPoint ("bottomright", timeText, "bottomright", 2, 0)
|
|
|
|
f.BossWidgetsFrame.Widgets [i] = newBossWidget
|
|
bossWidget = newBossWidget
|
|
end
|
|
|
|
local chartLength = f.ChartFrame.Graphic:GetWidth()
|
|
local secondsPerPixel = chartLength / elapsedTime
|
|
local xPosition = bossTable[1] * secondsPerPixel
|
|
|
|
bossWidget:SetPoint ("bottomright", f.ChartFrame.Graphic, "bottomleft", xPosition, 0)
|
|
|
|
bossWidget.TimeText:SetText (Details:GetFramework():IntegerToTimer (bossTable[1]))
|
|
|
|
if (bossTable[2].bossimage) then
|
|
bossWidget.AvatarTexture:SetTexture (bossTable[2].bossimage)
|
|
else
|
|
local bossAvatar = Details:GetBossPortrait (nil, nil, bossTable[2].name, bossTable[2].ej_instance_id)
|
|
bossWidget.AvatarTexture:SetTexture (bossAvatar)
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:Reset()
|
|
|
|
if (not mythicDungeonCharts.ChartTable and debugmode) then
|
|
--development
|
|
if (Details.mythic_plus.last_mythicrun_chart) then
|
|
--load the last mythic dungeon run chart
|
|
local t = {}
|
|
Details:GetFramework().table.copy (t, Details.mythic_plus.last_mythicrun_chart)
|
|
mythicDungeonCharts.ChartTable = t
|
|
end
|
|
else
|
|
f:Hide()
|
|
return
|
|
end
|
|
|
|
local charts = mythicDungeonCharts.ChartTable.Players
|
|
|
|
for playerName, playerTable in pairs (charts) do
|
|
|
|
local chartData = playerTable.ChartData
|
|
local lineName = playerTable.Name
|
|
|
|
local lineColor = {1, 1, 1, 1}
|
|
local classColor = RAID_CLASS_COLORS [playerTable.Class]
|
|
if (classColor) then
|
|
lineColor [1] = classColor.r
|
|
lineColor [2] = classColor.g
|
|
lineColor [3] = classColor.b
|
|
|
|
--print (playerName, playerTable.Class)
|
|
end
|
|
|
|
local combatTime = mythicDungeonCharts.ChartTable.ElapsedTime
|
|
local texture = "line"
|
|
|
|
--lowess smooth
|
|
--chartData = mythicDungeonCharts.LowessSmoothing (chartData, 75)
|
|
chartData = mythicDungeonCharts.Frame.ChartFrame:CalcLowessSmoothing (chartData, 75)
|
|
|
|
local maxValue = 0
|
|
for i = 1, #chartData do
|
|
if (chartData [i] > maxValue) then
|
|
maxValue = chartData [i]
|
|
end
|
|
end
|
|
chartData.max_value = maxValue
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:AddLine (chartData, lineColor, lineName, combatTime, texture, "SMA")
|
|
|
|
--[=[
|
|
local smoothFactor = 0.075
|
|
local forecastSmoothFactor = 1 - smoothFactor
|
|
local lastForecast = chartData[1]
|
|
local chartLag = {lastForecast}
|
|
local maxValue = lastForecast
|
|
|
|
for i = 2, #chartData do
|
|
local forecast = (chartData[i] * smoothFactor) + (lastForecast * forecastSmoothFactor)
|
|
tinsert (chartLag, forecast)
|
|
lastForecast = forecast
|
|
|
|
if (forecast > maxValue) then
|
|
maxValue = forecast
|
|
end
|
|
end
|
|
chartLag.max_value = maxValue
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:AddLine (chartLag, lineColor, lineName, combatTime, texture, "SMA")
|
|
--]=]
|
|
end
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:RefreshBossTimeline (mythicDungeonCharts.ChartTable.BossDefeated, mythicDungeonCharts.ChartTable.ElapsedTime)
|
|
|
|
--generate boss time table
|
|
local bossTimeTable = {}
|
|
for i, bossTable in ipairs (mythicDungeonCharts.ChartTable.BossDefeated) do
|
|
local combatTime = bossTable [3] or math.random (10, 30)
|
|
|
|
tinsert (bossTimeTable, bossTable[1])
|
|
tinsert (bossTimeTable, bossTable[1] - combatTime)
|
|
end
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:AddOverlay (bossTimeTable, {1, 1, 1, 0.05}, "Show Boss", "")
|
|
|
|
--local phrase = " Average Dps (under development)\npress Escape to hide, Details! Alpha Build." .. _detalhes.build_counter .. "." .. _detalhes.realversion
|
|
local phrase = "Details!: Average Dps for "
|
|
|
|
mythicDungeonCharts.Frame.ChartFrame:SetTitle (mythicDungeonCharts.ChartTable.DungeonName and phrase .. mythicDungeonCharts.ChartTable.DungeonName or phrase)
|
|
Details:GetFramework():SetFontSize (mythicDungeonCharts.Frame.ChartFrame.chart_title, 14)
|
|
|
|
mythicDungeonCharts.Frame:Show()
|
|
end
|
|
|
|
if (debugmode) then
|
|
C_Timer.After (1, mythicDungeonCharts.ShowChart)
|
|
end
|
|
|
|
-- endd
|