From 29f8cfbf75b17ff0bca61e6f255249ab5bb5d5f3 Mon Sep 17 00:00:00 2001 From: Tercioo Date: Sun, 10 Mar 2019 21:36:25 -0300 Subject: [PATCH] - Changed the way mythic dungeons are handled internally. - Added events: COMBAT_MYTHICDUNGEON_START, COMBAT_MYTHICDUNGEON_END, COMBAT_ENCOUNTER_END, COMBAT_ENCOUNTER_START. - Added API: Details:GetCombatFromBreakdownWindow() - Added wasted time in the segment tooltip for mythic dungeon overall and trash overall. - Added Fel Eruption crowd control. --- Libs/DF/fw.lua | 18 +- Libs/DF/panel.lua | 3 +- Libs/DF/spells.lua | 1 + boot.lua | 6 +- classes/classe_combate.lua | 8 + classes/container_historico.lua | 14 +- core/control.lua | 36 ++-- core/parser.lua | 23 +- functions/events.lua | 4 + gumps/janela_info.lua | 5 + gumps/janela_principal.lua | 34 ++- startup.lua | 364 ++++++++++++-------------------- 12 files changed, 250 insertions(+), 266 deletions(-) diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua index dff3d4da..0ee6adc2 100644 --- a/Libs/DF/fw.lua +++ b/Libs/DF/fw.lua @@ -1,5 +1,5 @@ -local dversion = 141 +local dversion = 143 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary (major, minor) @@ -358,6 +358,22 @@ function DF:CommaValue (value) return left .. (num:reverse():gsub ('(%d%d%d)','%1,'):reverse()) .. right end +function DF:GroupIterator (func, ...) + if (IsInRaid()) then + for i = 1, GetNumGroupMembers() do + DF:QuickDispatch (func, "raid" .. i, ...) + end + + elseif (IsInGroup()) then + for i = 1, GetNumGroupMembers() - 1 do + DF:QuickDispatch (func, "party" .. i, ...) + end + + else + DF:QuickDispatch (func, "player", ...) + end +end + function DF:IntegerToTimer (value) return "" .. floor (value/60) .. ":" .. format ("%02.f", value%60) end diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua index e34b0b84..f4efdb0a 100644 --- a/Libs/DF/panel.lua +++ b/Libs/DF/panel.lua @@ -8978,6 +8978,7 @@ DF.TimeLineBlockFunctions = { local timelineData = lineData.timeline for i = 1, #timelineData do + local blockInfo = timelineData [i] local time = blockInfo [1] @@ -8986,7 +8987,7 @@ DF.TimeLineBlockFunctions = { local text = blockInfo [4] local icon = blockInfo [5] local tooltip = blockInfo [6] - + local xOffset = pixelPerSecond * time local width = pixelPerSecond * length diff --git a/Libs/DF/spells.lua b/Libs/DF/spells.lua index 9ecb7a9f..c4b980a5 100644 --- a/Libs/DF/spells.lua +++ b/Libs/DF/spells.lua @@ -677,6 +677,7 @@ DF.CrowdControlSpells = { [217832] = "DEMONHUNTER", --Imprison [200166] = "DEMONHUNTER", --Metamorphosis [207685] = "DEMONHUNTER", --Sigil of Misery + [211881] = "DEMONHUNTER", -- Fel Eruption } DF.SpecIds = { diff --git a/boot.lua b/boot.lua index 060d33bf..d85cf6f4 100644 --- a/boot.lua +++ b/boot.lua @@ -4,11 +4,11 @@ _ = nil _detalhes = LibStub("AceAddon-3.0"):NewAddon("_detalhes", "AceTimer-3.0", "AceComm-3.0", "AceSerializer-3.0", "NickTag-1.0") - _detalhes.build_counter = 6924 - _detalhes.alpha_build_counter = 6924 --if this is higher than the regular counter, use it instead + _detalhes.build_counter = 6923 + _detalhes.alpha_build_counter = 6968 --if this is higher than the regular counter, use it instead _detalhes.game_version = "v8.1.0" _detalhes.userversion = "v8.1.0." .. _detalhes.build_counter - _detalhes.realversion = 137 --core version, this is used to check API version for scripts and plugins (see alias below) + _detalhes.realversion = 136 --core version, this is used to check API version for scripts and plugins (see alias below) _detalhes.APIVersion = _detalhes.realversion --core version _detalhes.version = _detalhes.userversion .. " (core " .. _detalhes.realversion .. ")" --simple stirng to show to players diff --git a/classes/classe_combate.lua b/classes/classe_combate.lua index 4ccfd31b..90b7d6a3 100644 --- a/classes/classe_combate.lua +++ b/classes/classe_combate.lua @@ -337,6 +337,10 @@ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> internals + function combate:CreateNewCombatTable() + return combate:NovaTabela() + end + --class constructor function combate:NovaTabela (iniciada, _tabela_overall, combatId, ...) @@ -395,6 +399,10 @@ esta_tabela.TimeData = _detalhes:TimeDataCreateCombatTables() esta_tabela.PhaseData = {{1, 1}, damage = {}, heal = {}, damage_section = {}, heal_section = {}} --[1] phase number [2] phase started + --> for external plugin usage + esta_tabela.spells_cast_timeline = {} + esta_tabela.cleu_timeline = {} + --> Skill cache (not used) esta_tabela.CombatSkillCache = {} diff --git a/classes/container_historico.lua b/classes/container_historico.lua index b957cd3d..1004cf99 100644 --- a/classes/container_historico.lua +++ b/classes/container_historico.lua @@ -272,17 +272,17 @@ function historico:adicionar (tabela) local canAddToOverall = _detalhes:CanAddCombatToOverall (tabela) if (canAddToOverall) then - if (InCombatLockdown()) then - _detalhes:ScheduleAddCombatToOverall (tabela) - if (_detalhes.debug) then - _detalhes:Msg ("(debug) overall data flag match > in combat scheduling overall addition.") - end - else + --if (InCombatLockdown()) then + -- _detalhes:ScheduleAddCombatToOverall (tabela) + -- if (_detalhes.debug) then + -- _detalhes:Msg ("(debug) overall data flag match > in combat scheduling overall addition.") + -- end + --else if (_detalhes.debug) then _detalhes:Msg ("(debug) overall data flag match addind the combat to overall data.") end historico:adicionar_overall (tabela) - end + --end end --> erase trash segments diff --git a/core/control.lua b/core/control.lua index 36d77099..a72e9755 100644 --- a/core/control.lua +++ b/core/control.lua @@ -417,7 +417,7 @@ --> combat creation is completed, remove the flag _detalhes.tabela_vigente.IsBeingCreated = nil - + _detalhes:SendEvent ("COMBAT_PLAYER_ENTER", nil, _detalhes.tabela_vigente, _detalhes.encounter_table and _detalhes.encounter_table.id) if (_detalhes.tabela_vigente.is_boss) then --> the encounter was found through encounter_start event @@ -574,20 +574,16 @@ end --> tag as a mythic dungeon segment, can be any type of segment, this tag also avoid the segment to be tagged as trash - if (_detalhes.MythicPlus.Started) then + local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() + if (mythicLevel and mythicLevel >= 2) then _detalhes.tabela_vigente.is_mythic_dungeon_segment = true _detalhes.tabela_vigente.is_mythic_dungeon_run_id = _detalhes.mythic_dungeon_id - else - local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() - if (mythicLevel and mythicLevel >= 2) then - _detalhes.tabela_vigente.is_mythic_dungeon_segment = true - _detalhes.tabela_vigente.is_mythic_dungeon_run_id = _detalhes.mythic_dungeon_id - end end --> send item level after a combat if is in raid or party group C_Timer.After (1, _detalhes.ScheduleSyncPlayerActorData) + --if this segment isn't a boss fight if (not _detalhes.tabela_vigente.is_boss) then if (_detalhes.tabela_vigente.is_pvp or _detalhes.tabela_vigente.is_arena) then @@ -601,10 +597,8 @@ local in_instance = IsInInstance() --> garrison returns party as instance type. if ((InstanceType == "party" or InstanceType == "raid") and in_instance) then if (InstanceType == "party") then - if (not _detalhes.tabela_vigente.is_mythic_dungeon_segment) then - --> tag the combat as trash clean up - _detalhes.tabela_vigente.is_trash = true - else + if (_detalhes.tabela_vigente.is_mythic_dungeon_segment) then --setted just above + --is inside a mythic+ dungeon and this is not a boss segment, so tag it as a dungeon mythic+ trash segment local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() _detalhes.tabela_vigente.is_mythic_dungeon_trash = { ZoneName = zoneName, @@ -612,6 +606,9 @@ Level = _detalhes.MythicPlus.Level, EJID = _detalhes.MythicPlus.ejID, } + else + --> tag the combat as trash clean up + _detalhes.tabela_vigente.is_trash = true end else _detalhes.tabela_vigente.is_trash = true @@ -643,13 +640,17 @@ _detalhes:FlagActorsOnCommonFight() --fight_component --_detalhes:CheckMemoryAfterCombat() -- 7.2.5 is doing some weird errors even out of combat else - + + --this segment is a boss fight if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then - _detalhes:FlagActorsOnBossFight() + else - _detalhes.schedule_flag_boss_components = true + --_detalhes.schedule_flag_boss_components = true end + --calling here without checking for combat since the does not ran too long for scripts + _detalhes:FlagActorsOnBossFight() + local boss_id = _detalhes.encounter_table.id if (bossKilled) then @@ -657,9 +658,7 @@ --> add to storage if (not InCombatLockdown() and not UnitAffectingCombat ("player") and not _detalhes.logoff_saving_data) then - --_detalhes.StoreEncounter() - local successful, errortext = pcall (_detalhes.StoreEncounter) if (not successful) then _detalhes:Msg ("error occurred on StoreEncounter():", errortext) @@ -871,10 +870,7 @@ end _detalhes:CheckForTextTimeCounter() - - _detalhes.StoreSpells() - _detalhes:RunScheduledEventsAfterCombat() end diff --git a/core/parser.lua b/core/parser.lua index 691b1740..2a465aec 100644 --- a/core/parser.lua +++ b/core/parser.lua @@ -4232,6 +4232,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 _detalhes.encounter_table.index = boss_index end + _detalhes:SendEvent ("COMBAT_ENCOUNTER_START", nil, ...) end function _detalhes.parser_functions:ENCOUNTER_END (...) @@ -4248,7 +4249,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 if (_detalhes.debug) then _detalhes:Msg ("(debug) the zone type is 'party', ignoring ENCOUNTER_END.") end - return + --return --rnu encounter end for dungeons as well end local encounterID, encounterName, difficultyID, raidSize, endStatus = _select (1, ...) @@ -4285,6 +4286,8 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 end end + _detalhes:SendEvent ("COMBAT_ENCOUNTER_END", nil, ...) + _table_wipe (_detalhes.encounter_table) return true @@ -4484,6 +4487,24 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1 end + function _detalhes.parser_functions:CHALLENGE_MODE_START (...) + --> send mythic dungeon start event + local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() + if (difficultyID == 8) then + _detalhes:SendEvent ("COMBAT_MYTHICDUNGEON_START") + end + + end + + function _detalhes.parser_functions:CHALLENGE_MODE_COMPLETED (...) + --> send mythic dungeon end event + local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() + if (difficultyID == 8) then + _detalhes:SendEvent ("COMBAT_MYTHICDUNGEON_END") + end + + end + function _detalhes.parser_functions:PLAYER_REGEN_ENABLED (...) if (_detalhes.debug) then diff --git a/functions/events.lua b/functions/events.lua index 30ee52e9..2c28dd43 100644 --- a/functions/events.lua +++ b/functions/events.lua @@ -28,6 +28,8 @@ ["DETAILS_DATA_SEGMENTREMOVED"] = {}, --> combat + ["COMBAT_ENCOUNTER_START"] = {}, + ["COMBAT_ENCOUNTER_END"] = {}, ["COMBAT_PLAYER_ENTER"] = {}, ["COMBAT_PLAYER_LEAVE"] = {}, ["COMBAT_PLAYER_TIMESTARTED"] = {}, @@ -90,6 +92,8 @@ local common_events = { ["DETAILS_OPTIONS_MODIFIED"] = true, ["DETAILS_DATA_RESET"] = true, ["DETAILS_DATA_SEGMENTREMOVED"] = true, + ["COMBAT_ENCOUNTER_START"] = true, + ["COMBAT_ENCOUNTER_END"] = true, ["COMBAT_PLAYER_ENTER"] = true, ["COMBAT_PLAYER_LEAVE"] = true, ["COMBAT_PLAYER_TIMESTARTED"] = true, diff --git a/gumps/janela_info.lua b/gumps/janela_info.lua index d12dc688..d5225c22 100644 --- a/gumps/janela_info.lua +++ b/gumps/janela_info.lua @@ -37,6 +37,11 @@ local CONST_TARGET_HEIGHT = 18 --self = instancia --jogador = classe_damage ou classe_heal +--return the combat being used to show the data in the opened breakdown window +function Details:GetCombatFromBreakdownWindow() + return info.instancia and info.instancia.showing +end + function _detalhes:AbreJanelaInfo (jogador, from_att_change, refresh, ShiftKeyDown, ControlKeyDown) --print (debugstack()) diff --git a/gumps/janela_principal.lua b/gumps/janela_principal.lua index 3bb949de..560f08a3 100644 --- a/gumps/janela_principal.lua +++ b/gumps/janela_principal.lua @@ -6236,11 +6236,25 @@ local build_segment_list = function (self, elapsed) if (segmentID == "trashoverall") then CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TIMEINCOMBAT"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") local totalRealTime = endedAt - startedAt - CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (endedAt - startedAt) .. " [|cFFFF3300" .. _detalhes.gump:IntegerToTimer (totalRealTime - decorrido) .. "|r]", 2, "white", "white") + local wasted = totalRealTime - decorrido + + --wasted time + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_WASTED_TIME"] .. ":", "|cFFFF3300" .. _detalhes.gump:IntegerToTimer (wasted) .. " (" .. floor (wasted / totalRealTime * 100) .. "%)|r", 2, "white", "white") + CoolTip:AddStatusBar (100, 2, 0, 0, 0, 0.55, false, false, "Skyline") + + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (endedAt - startedAt), 2, "white", "white") + elseif (isMythicOverallSegment) then CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TIMEINCOMBAT"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") local totalRealTime = endedAt - startedAt - CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (totalRealTime) .. " [|cFFFF3300" .. _detalhes.gump:IntegerToTimer (totalRealTime - decorrido) .. "|r]", 2, "white", "white") + local wasted = totalRealTime - decorrido + + --wasted time + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_WASTED_TIME"] .. ":", "|cFFFF3300" .. _detalhes.gump:IntegerToTimer (wasted) .. " (" .. floor (wasted / totalRealTime * 100) .. "%)|r", 2, "white", "white") + CoolTip:AddStatusBar (100, 2, 0, 0, 0, 0.55, false, false, "Skyline") + + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (totalRealTime), 2, "white", "white") + else CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_COMBATTIME"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") end @@ -6513,13 +6527,27 @@ local build_segment_list = function (self, elapsed) if (segmentID == "trashoverall") then local totalRealTime = endedAt - startedAt + local wasted = totalRealTime - decorrido + CoolTip:AddLine (Loc["STRING_SEGMENTS_LIST_TIMEINCOMBAT"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") + + --wasted time + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_WASTED_TIME"] .. ":", "|cFFFF3300" .. _detalhes.gump:IntegerToTimer (wasted) .. " (" .. floor (wasted / totalRealTime * 100) .. "%)|r", 2, "white", "white") + CoolTip:AddStatusBar (100, 2, 0, 0, 0, 0.55, false, false, "Skyline") + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (endedAt - startedAt) .. " [|cFFFF3300" .. _detalhes.gump:IntegerToTimer (totalRealTime - decorrido) .. "|r]", 2, "white", "white") elseif (isMythicOverallSegment) then CoolTip:AddLine (Loc["STRING_SEGMENTS_LIST_TIMEINCOMBAT"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") local totalRealTime = endedAt - startedAt - CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (totalRealTime) .. " [|cFFFF3300" .. _detalhes.gump:IntegerToTimer (totalRealTime - decorrido) .. "|r]", 2, "white", "white") + local wasted = totalRealTime - decorrido + + + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_TOTALTIME"] .. ":", _detalhes.gump:IntegerToTimer (totalRealTime), 2, "white", "white") + + --wasted time + CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_WASTED_TIME"] .. ":", "|cFFFF3300" .. _detalhes.gump:IntegerToTimer (wasted) .. " (" .. floor (wasted / totalRealTime * 100) .. "%)|r", 2, "white", "white") + CoolTip:AddStatusBar (100, 2, 0, 0, 0, 0.55, false, false, "Skyline") else CoolTip:AddLine (Loc ["STRING_SEGMENTS_LIST_COMBATTIME"] .. ":", _detalhes.gump:IntegerToTimer (decorrido), 2, "white", "white") diff --git a/startup.lua b/startup.lua index 964279c8..a6c43e74 100644 --- a/startup.lua +++ b/startup.lua @@ -283,12 +283,15 @@ function _G._detalhes:Start() self.listener:RegisterEvent ("PLAYER_SPECIALIZATION_CHANGED") self.listener:RegisterEvent ("PLAYER_TALENT_UPDATE") + self.listener:RegisterEvent ("CHALLENGE_MODE_START") + self.listener:RegisterEvent ("CHALLENGE_MODE_COMPLETED") + --test immersion stuff ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ local immersionFrame = CreateFrame ("frame", "DetailsImmersionFrame", UIParent) immersionFrame:RegisterEvent ("ZONE_CHANGED_NEW_AREA") - immersionFrame.DevelopmentDebug = false + immersionFrame.DevelopmentDebug = true --> check if can enabled the immersino stuff @@ -333,7 +336,7 @@ function _G._detalhes:Start() -- ~mythic ~dungeon local newFrame = CreateFrame ("frame", "DetailsMythicPlusFrame", UIParent) - newFrame.DevelopmentDebug = false + newFrame.DevelopmentDebug = true --[ newFrame:RegisterEvent ("CHALLENGE_MODE_START") @@ -476,27 +479,20 @@ function _G._detalhes:Start() --> table exists and there's at least one segment if (segmentsToMerge and segmentsToMerge[1]) then - --> do the merge - --> leave combat if still tagged as combat - if (self.in_combat) then - if (newFrame.DevelopmentDebug) then - print ("Details!", "MergeTrashCleanup() > was in combat, calling SairDoCombate()", _detalhes.tabela_vigente, _detalhes.tabela_vigente.is_boss) - end - self:SairDoCombate() - end - - --> create a new combat to be the overall for the mythic run - self:EntrarEmCombate() + --the first segment is the segment where all other trash segments will be added + local masterSegment = segmentsToMerge[1] + masterSegment.is_mythic_dungeon_trash = nil --> get the current combat just created and the table with all past segments - local newCombat = self:GetCurrentCombat() - local totalTime = 0 + local newCombat = masterSegment + local totalTime = newCombat:GetCombatTime() local startDate, endDate = "", "" local lastSegment --> add segments - for _, pastCombat in ipairs (segmentsToMerge) do + for i = 2, #segmentsToMerge do --segment #1 is the host + pastCombat = segmentsToMerge [i] newCombat = newCombat + pastCombat totalTime = totalTime + pastCombat:GetCombatTime() @@ -541,88 +537,24 @@ function _G._detalhes:Start() --> set the segment date newCombat:SetDate (startDate, endDate) - --> immediatly finishes the segment just started - self:SairDoCombate() - - --o combate agora � _tabela_vigente e [1] na tabela de overall - --seria necessario passar essa tabela para [2] na overall - local segmentHistory = self:GetCombatSegments() - - --> if was scheduled, needs to reorder the segments so it will the in the correct order - if (isFromSchedule) then - local bossSegment = segmentHistory [3] - local currentTrash = segmentHistory [2] - local trashOverall = segmentHistory [1] - - local bossCLID = bossSegment and bossSegment.is_mythic_dungeon and bossSegment.is_mythic_dungeon.EncounterID - local trashCLID = trashOverall and trashOverall.is_mythic_dungeon and trashOverall.is_mythic_dungeon.EncounterID - - --> check if the guessed boss and guessed trash overall segments are from the same boss - if (bossCLID == trashCLID and currentTrash.is_mythic_dungeon_trash) then - --set the boss as the current combat - _detalhes.tabela_vigente = currentTrash - --swap tables - segmentHistory [1] = currentTrash - segmentHistory [2] = bossSegment - segmentHistory [3] = trashOverall - else - --> if it fails to guess which are the boss and trash, just pull the current trash segment to index 1 - local currentTrash = segmentHistory [2] - if (currentTrash) then - --set the boss as the current combat - _detalhes.tabela_vigente = currentTrash - --swap tables - segmentHistory [1] = currentTrash --as the boss combat is done, it is also the first combat in the past combats table - segmentHistory [2] = newCombat --se the overall trash as the second segment on the past table (the semgnet 2 was occupy by the boss segment) - end - end - else - local bossSegment = segmentHistory [2] - if (bossSegment) then - --set the boss as the current combat - _detalhes.tabela_vigente = bossSegment - --swap tables - segmentHistory [1] = bossSegment --as the boss combat is done, it is also the first combat in the past combats table - segmentHistory [2] = newCombat --se the overall trash as the second segment on the past table (the semgnet 2 was occupy by the boss segment) - end - end - if (newFrame.DevelopmentDebug) then print ("Details!", "MergeTrashCleanup() > finished merging trash segments.", _detalhes.tabela_vigente, _detalhes.tabela_vigente.is_boss) end - - for i = #segmentsToMerge, 1, -1 do - local segment = segmentsToMerge [i] - if (segment == _detalhes.tabela_vigente) then - --this exception still exists but is handled now - --_detalhes:Msg ("unhandled exception > merged trash segment is current segment > MergeTrashCleanup() is scheduled:", isFromSchedule) - --happened after killing one mob and leaving the dungeon, lots of /reload has done inside the dungeon - end - end - + --> should delete the trash segments after the merge? if (_detalhes.mythic_plus.delete_trash_after_merge) then local segmentHistory = self:GetCombatSegments() - for _, pastCombat in ipairs (segmentsToMerge) do - for i = #segmentHistory, 1, -1 do - local segment = segmentHistory [i] - if (segment == pastCombat and _detalhes.tabela_vigente ~= segment) then - --> double check if the combat should be added first to overall data - if (_detalhes:CanAddCombatToOverall (segment)) then - --> actuallt is handled, but shouldn't happen, need to know which boss are triggering this - --_detalhes:Msg ("unhandled exception > attempt to erase a segment valid to overall data > MergeTrashCleanup() is scheduled:", isFromSchedule) - _detalhes.historico:adicionar_overall (segment) - end - - --> remove the segment - tremove (segmentHistory, i) - break - end + for i = #segmentHistory, 1, -1 do + local segment = segmentHistory [i] + if (segment and segment._trashoverallalreadyadded) then + tremove (segmentHistory, i) end end + for i = #segmentsToMerge, 1, -1 do tremove (segmentsToMerge, i) end + self:SendEvent ("DETAILS_DATA_SEGMENTREMOVED") else --> clear the segments to merge table @@ -702,14 +634,6 @@ function _G._detalhes:Start() print ("MergeRemainingTrashAfterAllBossesDone() > elapsed time after:", mythicDungeonInfo.EndedAt - mythicDungeonInfo.StartedAt) end - for i = #segmentsToMerge, 1, -1 do - local segment = segmentsToMerge [i] - if (segment == _detalhes.tabela_vigente) then - --this exception still exists but is handled now - --_detalhes:Msg ("unhandled exception > merged trash segment is current segment > MergeRemainingTrashAfterAllBossesDone()") - end - end - --> should delete the trash segments after the merge? if (_detalhes.mythic_plus.delete_trash_after_merge) then local segmentHistory = self:GetCombatSegments() @@ -717,13 +641,6 @@ function _G._detalhes:Start() for i = #segmentHistory, 1, -1 do local segment = segmentHistory [i] if (segment == pastCombat and _detalhes.tabela_vigente ~= segment) then - --> double check if the combat should be added first to overall data - if (_detalhes:CanAddCombatToOverall (segment)) then - --> actuallt is handled, but shouldn't happen, need to know which boss are triggering this - --_detalhes:Msg ("unhandled exception > attempt to erase a segment valid to overall data > MergeRemainingTrashAfterAllBossesDone()") - _detalhes.historico:adicionar_overall (segment) - end - --> remove the segment tremove (segmentHistory, i) break @@ -753,6 +670,7 @@ function _G._detalhes:Start() end --this function is called right after defeat a boss inside a mythic dungeon + --it comes from details! control leave combat function newFrame.BossDefeated (this_is_end_end, encounterID, encounterName, difficultyID, raidSize, endStatus) --hold your breath and count to ten if (newFrame.DevelopmentDebug) then print ("Details!", "BossDefeated() > boss defeated | SegmentID:", self.MythicPlus.SegmentID, " | mapID:", self.MythicPlus.DungeonID) @@ -760,7 +678,7 @@ function _G._detalhes:Start() local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() - --> addon the mythic dungeon info to the combat + --> add the mythic dungeon info to the combat _detalhes.tabela_vigente.is_mythic_dungeon = { StartedAt = self.MythicPlus.StartedAt, --the start of the run EndedAt = time(), --when the boss got killed @@ -774,19 +692,12 @@ function _G._detalhes:Start() Level = self.MythicPlus.Level, EJID = self.MythicPlus.ejID, } - - if (not this_is_end_end) then - --> parser doesn't handle ENCOUNTER_END to party instances, so we close the combat from here - self:SairDoCombate (true, {encounterID, encounterName, difficultyID, raidSize, endStatus}) - if (newFrame.DevelopmentDebug) then - print ("Details!", "BossDefeated() > closing the combat with SairDoCombate()", _detalhes.tabela_vigente, _detalhes.tabela_vigente.is_boss) - end - end - + --> check if need to merge the trash for this boss if (_detalhes.mythic_plus.merge_boss_trash and not self.MythicPlus.IsRestoredState) then --> store on an table all segments which should be merged local segmentsToMerge = newFrame.TrashMergeScheduled or {} + --> table with all past semgnets local segmentHistory = self:GetCombatSegments() @@ -794,7 +705,7 @@ function _G._detalhes:Start() for i = 1, 25 do --> from the newer combat to the oldest local pastCombat = segmentHistory [i] --> does the combat exists - if (pastCombat and not pastCombat._trashoverallalreadyadded) then + if (pastCombat and not pastCombat._trashoverallalreadyadded and pastCombat.is_mythic_dungeon_trash) then --> is the combat a mythic segment from this run? local isMythicSegment, SegmentID = pastCombat:IsMythicDungeon() if (isMythicSegment and SegmentID == self.mythic_dungeon_id and not pastCombat.is_boss) then @@ -818,17 +729,19 @@ function _G._detalhes:Start() newFrame.TrashMergeScheduled = segmentsToMerge - if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then + --there's no more script run too long + --if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then if (newFrame.DevelopmentDebug) then print ("Details!", "BossDefeated() > not in combat, merging trash now") end + --merge the trash clean up newFrame.MergeTrashCleanup() - else - if (newFrame.DevelopmentDebug) then - print ("Details!", "BossDefeated() > player in combatlockdown, scheduling trash merge") - end - _detalhes.schedule_mythicdungeon_trash_merge = true - end + --else + -- if (newFrame.DevelopmentDebug) then + -- print ("Details!", "BossDefeated() > player in combatlockdown, scheduling trash merge") + -- end + -- _detalhes.schedule_mythicdungeon_trash_merge = true + --end end --> close the combat @@ -896,16 +809,20 @@ function _G._detalhes:Start() if (pastCombat.is_boss) then break end + --> is the combat a mythic segment from this run? local isMythicSegment, SegmentID = pastCombat:IsMythicDungeon() - if (isMythicSegment and SegmentID == self.mythic_dungeon_id) then + if (isMythicSegment and SegmentID == self.mythic_dungeon_id and pastCombat.is_mythic_dungeon_trash) then + --> if have mythic dungeon info, cancel the loop local mythicDungeonInfo = pastCombat:GetMythicDungeonInfo() if (mythicDungeonInfo) then break end + --> merge this segment tinsert (segmentsToMerge, pastCombat) + if (newFrame.DevelopmentDebug) then print ("MythicDungeonFinished() > found after last boss combat") end @@ -936,33 +853,34 @@ function _G._detalhes:Start() newFrame.TrashMergeScheduled2 = segmentsToMerge newFrame.TrashMergeScheduled2_OverallCombat = latestTrashOverall - if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then + --there's no more script ran too long + --if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then if (newFrame.DevelopmentDebug) then print ("Details!", "MythicDungeonFinished() > not in combat, merging last pack of trash now") end newFrame.MergeRemainingTrashAfterAllBossesDone() - else - if (newFrame.DevelopmentDebug) then - print ("Details!", "MythicDungeonFinished() > player in combatlockdown, scheduling the merge for last trash packs") - end - _detalhes.schedule_mythicdungeon_endtrash_merge = true - end + --else + -- if (newFrame.DevelopmentDebug) then + -- print ("Details!", "MythicDungeonFinished() > player in combatlockdown, scheduling the merge for last trash packs") + -- end + -- _detalhes.schedule_mythicdungeon_endtrash_merge = true + --end end end --> merge segments if (_detalhes.mythic_plus.make_overall_when_done and not self.MythicPlus.IsRestoredState and not fromZoneLeft) then - if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then + --if (not InCombatLockdown() and not UnitAffectingCombat ("player")) then if (newFrame.DevelopmentDebug) then print ("Details!", "MythicDungeonFinished() > not in combat, creating overall segment now") end newFrame.MergeSegmentsOnEnd() - else - if (newFrame.DevelopmentDebug) then - print ("Details!", "MythicDungeonFinished() > player in combatlockdown, scheduling the creation of the overall segment") - end - _detalhes.schedule_mythicdungeon_overallrun_merge = true - end + --else + -- if (newFrame.DevelopmentDebug) then + -- print ("Details!", "MythicDungeonFinished() > player in combatlockdown, scheduling the creation of the overall segment") + -- end + -- _detalhes.schedule_mythicdungeon_overallrun_merge = true + --end end self.MythicPlus.IsRestoredState = nil @@ -982,31 +900,20 @@ function _G._detalhes:Start() --> flag as a mythic dungeon newFrame.IsDoingMythicDungeon = true - if (newFrame.DevelopmentDebug) then - print ("=========") - print ("Details!", "Thanks for using an alpha version of Details!, please don't mind all these debug lines.") - print ("Details!", "We are developing new stuff.") - print ("=========") - print ("Details!", "MythicDungeonStarted() > CHALLENGE_MODE_START triggered, setting up details!") - end - --> this counter is individual for each character - self.mythic_dungeon_id = self.mythic_dungeon_id + 1 --14 --15 + self.mythic_dungeon_id = self.mythic_dungeon_id + 1 local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo() - local mapID = C_Map.GetBestMapForUnit ("player") if (not mapID) then - --print ("Details! exeption handled: zone has no map") return end local ejID = EJ_GetInstanceForMap (mapID) - --local ejID = EJ_GetCurrentInstance() - + --> setup the mythic run info self.MythicPlus.Started = true self.MythicPlus.DungeonName = zoneName @@ -1043,16 +950,13 @@ function _G._detalhes:Start() if (newFrame.DevelopmentDebug) then print ("Details!", "MythicDungeonStarted() > State set to Mythic Dungeon, new combat starting in 10 seconds.") end + end function newFrame.OnChallengeModeStart() --> is this a mythic dungeon? local _, _, difficulty, _, _, _, _, currentZoneID = GetInstanceInfo() - - if (newFrame.DevelopmentDebug) then - print ("Details!", "Dungeon Dificulty:", difficulty, currentZoneID) - end - + if (difficulty == 8 and newFrame.LastTimer and newFrame.LastTimer+2 > GetTime()) then --> start the dungeon on Details! newFrame.MythicDungeonStarted() @@ -1070,83 +974,31 @@ function _G._detalhes:Start() end end - newFrame:SetScript ("OnEvent", function (_, event, ...) + --make an event listener to sync combat data + newFrame.EventListener = Details:CreateEventListener() + newFrame.EventListener:RegisterEvent ("COMBAT_ENCOUNTER_START") + newFrame.EventListener:RegisterEvent ("COMBAT_ENCOUNTER_END") + newFrame.EventListener:RegisterEvent ("COMBAT_PLAYER_ENTER") + newFrame.EventListener:RegisterEvent ("COMBAT_PLAYER_LEAVE") + newFrame.EventListener:RegisterEvent ("COMBAT_MYTHICDUNGEON_START") + newFrame.EventListener:RegisterEvent ("COMBAT_MYTHICDUNGEON_END") + + function newFrame.EventListener.OnDetailsEvent (contextObject, event, ...) + --these events triggers within Details control functions, they run exactly after details! creates or close a segment + if (event == "COMBAT_PLAYER_ENTER") then + + + elseif (event == "COMBAT_PLAYER_LEAVE") then + --> ignore the event if ignoring mythic dungeon special treatment + if (_detalhes.streamer_config.disable_mythic_dungeon) then + return + end - if (event == "START_TIMER") then - newFrame.LastTimer = GetTime() - - elseif (event == "CHALLENGE_MODE_START") then - --> CHALLENGE_MODE_START does trigger every time the player enters a mythic dungeon already in progress - - --> send mythic dungeon start event - local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() - if (difficultyID == 8) then - _detalhes:SendEvent ("COMBAT_MYTHICDUNGEON_START") - end - - if (newFrame.DevelopmentDebug) then - print ("Details!", event, ...) - end - - --> reset spec cache if broadcaster requested - if (_detalhes.streamer_config.reset_spec_cache) then - wipe (_detalhes.cached_specs) - end - - --> ignore the event if ignoring mythic dungeon special treatment - if (_detalhes.streamer_config.disable_mythic_dungeon) then - return - end - - C_Timer.After (0.5, newFrame.OnChallengeModeStart) - - elseif (event == "CHALLENGE_MODE_COMPLETED") then - if (newFrame.DevelopmentDebug) then - print ("Details!", event, ...) - end - - --> send mythic dungeon end event - local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() - if (difficultyID == 8) then - _detalhes:SendEvent ("COMBAT_MYTHICDUNGEON_END") - end - - --> ignore the event if ignoring mythic dungeon special treatment - if (_detalhes.streamer_config.disable_mythic_dungeon) then - return - end - - --> delay to wait the encounter_end trigger first - --> assuming here the party cleaned the mobs kill objective before going to kill the last boss - C_Timer.After (2, newFrame.MythicDungeonFinished) - - elseif (event == "ENCOUNTER_END") then - if (newFrame.DevelopmentDebug) then - print ("Details!", event, ...) - end - - --> ignore the event if ignoring mythic dungeon special treatment - if (_detalhes.streamer_config.disable_mythic_dungeon) then - return - end - if (newFrame.IsDoingMythicDungeon) then - local encounterID, encounterName, difficultyID, raidSize, endStatus = ... - if (endStatus == 1) then - newFrame.BossDefeated (false, encounterID, encounterName, difficultyID, raidSize, endStatus) - else - --> remove the boss table, so it will be considered trash - if (self.tabela_vigente.is_boss) then - --> check if is still in combat - if (newFrame.DevelopmentDebug) then - print ("Details!", "Boss Wipe, removing the boss table from the segment.") - end - if (self.in_combat) then - if (newFrame.DevelopmentDebug) then - print ("Details!", "Boss Wipe, was in combat, calling SairDoCombate().") - end - self:SairDoCombate() - end + local combatObject = ... + + if (combatObject.is_boss) then + if (not combatObject.is_boss.killed) then --> just in case the combat get tagged as boss fight self.tabela_vigente.is_boss = nil @@ -1158,11 +1010,63 @@ function _G._detalhes:Start() MapID = instanceMapID, Level = _detalhes.MythicPlus.Level, EJID = _detalhes.MythicPlus.ejID, - } - + } + else + newFrame.BossDefeated (false, combatObject.is_boss.id, combatObject.is_boss.name, combatObject.is_boss.diff, 5, 1) end end + end + + elseif (event == "COMBAT_ENCOUNTER_START") then + --> ignore the event if ignoring mythic dungeon special treatment + if (_detalhes.streamer_config.disable_mythic_dungeon) then + return + end + + local encounterID, encounterName, difficultyID, raidSize, endStatus = ... + --nothing + + elseif (event == "COMBAT_ENCOUNTER_END") then + --> ignore the event if ignoring mythic dungeon special treatment + if (_detalhes.streamer_config.disable_mythic_dungeon) then + return + end + + local encounterID, encounterName, difficultyID, raidSize, endStatus = ... + --nothing + + elseif (event == "COMBAT_MYTHICDUNGEON_START") then + --> ignore the event if ignoring mythic dungeon special treatment + if (_detalhes.streamer_config.disable_mythic_dungeon) then + return + end + + --> reset spec cache if broadcaster requested + if (_detalhes.streamer_config.reset_spec_cache) then + wipe (_detalhes.cached_specs) + end + + C_Timer.After (0.5, newFrame.OnChallengeModeStart) + + elseif (event == "COMBAT_MYTHICDUNGEON_END") then + + --> ignore the event if ignoring mythic dungeon special treatment + if (_detalhes.streamer_config.disable_mythic_dungeon) then + return + end + + --> delay to wait the encounter_end trigger first + --> assuming here the party cleaned the mobs kill objective before going to kill the last boss + C_Timer.After (2, newFrame.MythicDungeonFinished) + + end + end + + newFrame:SetScript ("OnEvent", function (_, event, ...) + + if (event == "START_TIMER") then + newFrame.LastTimer = GetTime() elseif (event == "ZONE_CHANGED_NEW_AREA") then if (newFrame.IsDoingMythicDungeon) then