local Details = _G.Details local addonName, Details222 = ... local detailsFramework = DetailsFramework local _ local debugmode = false --print debug lines local verbosemode = false --auto open the chart panel local UnitClass = UnitClass local IsInInstance = IsInInstance local GetNumGroupMembers = GetNumGroupMembers local GetInstanceInfo = GetInstanceInfo local time = time local floor = math.floor local C_Timer = C_Timer local C_ChallengeMode = C_ChallengeMode --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 mythicDungeonFrames = Details222.MythicPlus.Frames local mythicDungeonCharts = Details222.MythicPlus.Charts.Listener --debug _G.DetailsMythicDungeonChartHandler = mythicDungeonCharts function mythicDungeonCharts:Debug(...) if (debugmode or verbosemode) then print("Details! DungeonCharts: ", ...) end end local addPlayerDamage = function(unitCleuName) --get the player data local playerData = mythicDungeonCharts.ChartTable.Players[unitCleuName] --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 = detailsFramework:RemoveRealmName(unitCleuName), ChartData = {max_value = 0}, Class = select(2, UnitClass(Details:Ambiguate(unitCleuName))), --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[unitCleuName] = 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", unitCleuName) end local actorTable = currentCombat:GetActor(DETAILS_ATTRIBUTE_DAMAGE, unitCleuName) 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 table.insert(playerData.ChartData, eDps) --mythicDungeonCharts:Debug("Added dps for " , unitCleuName, ":", 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 table.insert(playerData.ChartData, damageDiff) --mythicDungeonCharts:Debug("Added damage for " , unitCleuName, ":", 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 table.insert(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 ---@type cleuname local cleuName = Details:GetFullName("party" .. i) if (cleuName) then addPlayerDamage(cleuName) end end addPlayerDamage(Details:GetFullName("player")) end function mythicDungeonCharts:OnBossDefeated() local currentCombat = Details:GetCurrentCombat() local segmentType = currentCombat:GetCombatType() local bossInfo = currentCombat:GetBossInfo() local mythicLevel = C_ChallengeMode and C_ChallengeMode.GetActiveKeystoneInfo() if (mythicLevel and mythicLevel > 0) then if (mythicDungeonCharts.ChartTable and mythicDungeonCharts.ChartTable.Running and bossInfo) then local tCopiedBossInfo = Details:GetFramework().table.copy({}, bossInfo) table.insert(mythicDungeonCharts.ChartTable.BossDefeated, {time() - mythicDungeonCharts.ChartTable.StartTime, tCopiedBossInfo, currentCombat:GetCombatTime()}) mythicDungeonCharts:Debug("Boss defeated, time saved", currentCombat:GetCombatTime()) else if (mythicDungeonCharts.ChartTable and 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) table.insert(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 else mythicDungeonCharts:Debug("Boss defeated, but isn't a mythic dungeon boss fight") 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") if (verbosemode) then mythicDungeonCharts:Debug("OnStartMythicDungeon() not allowed") end 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 (Details222.Debug.MythicPlusChartWindowDebug) then Details.mythic_plus.last_mythicrun_chart = mythicDungeonCharts.ChartTable end if (verbosemode) then mythicDungeonCharts:Debug("OnStartMythicDungeon() success") end end function mythicDungeonCharts:OnEndMythicDungeon() if (mythicDungeonCharts.ChartTable and mythicDungeonCharts.ChartTable.Running) then --stop capturinfg 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 --check if is inside the dungeon --many players just leave the dungeon in order the re-enter and start the run again, the chart window is showing in these cases data to an imcomplete run. local isInsideDungeon = IsInInstance() if (not isInsideDungeon) then mythicDungeonCharts:Debug("OnEndMythicDungeon() player wasn't inside the dungeon.") return end if (verbosemode) then mythicDungeonCharts:Debug("OnEndMythicDungeon() success!") end else mythicDungeonCharts:Debug("Dungeon ended, no chart data was running") if (verbosemode) then mythicDungeonCharts:Debug("OnEndMythicDungeon() fail") end end end mythicDungeonCharts:RegisterEvent("COMBAT_MYTHICDUNGEON_START", "OnStartMythicDungeon") mythicDungeonCharts:RegisterEvent("COMBAT_MYTHICDUNGEON_END", "OnEndMythicDungeon") mythicDungeonCharts:RegisterEvent("COMBAT_BOSS_DEFEATED", "OnBossDefeated") --SetPortraitTexture(texture, unitId) -- /run _G.DetailsMythicDungeonChartHandler.ShowChart(); DetailsMythicDungeonChartFrame.ShowChartFrame() -- /run mythicDungeonFrames.ShowEndOfMythicPlusPanel()