local Details = _G.Details local DF = _G.DetailsFramework local addonName, Details222 = ... local _ local time = time local C_Timer = _G.C_Timer local unpack = _G.unpack local GetTime = _G.GetTime local tremove = _G.tremove local GetInstanceInfo = _G.GetInstanceInfo local Loc = _G.LibStub("AceLocale-3.0"):GetLocale("Details") --data for the current mythic + dungeon Details.MythicPlus = { RunID = 0, } local mythicDungeonCharts = Details:CreateEventListener() Details222.MythicPlus.Charts.Listener = mythicDungeonCharts -- ~mythic ~dungeon local DetailsMythicPlusFrame = _G.CreateFrame("frame", "DetailsMythicPlusFrame", UIParent) DetailsMythicPlusFrame.DevelopmentDebug = false --disabling the mythic+ feature if the user is playing in wow classic if (not DF.IsTimewalkWoW()) then DetailsMythicPlusFrame:RegisterEvent("CHALLENGE_MODE_START") DetailsMythicPlusFrame:RegisterEvent("CHALLENGE_MODE_COMPLETED") DetailsMythicPlusFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA") DetailsMythicPlusFrame:RegisterEvent("ENCOUNTER_END") DetailsMythicPlusFrame:RegisterEvent("START_TIMER") end function Details222.MythicPlus.LogStep(log) local today = date("%d/%m/%y %H:%M:%S") table.insert(Details.mythic_plus_log, 1, today .. "|" .. log) tremove(Details.mythic_plus_log, 50) end function DetailsMythicPlusFrame.BossDefeated(this_is_end_end, encounterID, encounterName, difficultyID, raidSize, endStatus) --hold your breath and count to ten --this function is called right after defeat a boss inside a mythic dungeon --it comes from details! control leave combat if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "BossDefeated() > boss defeated | SegmentID:", Details.MythicPlus.SegmentID, " | mapID:", Details.MythicPlus.DungeonID) end --local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() Details222.MythicPlus.OnBossDefeated(encounterID, encounterName) --increase the segment number for the mythic run Details.MythicPlus.SegmentID = Details.MythicPlus.SegmentID + 1 --register the time when the last boss has been killed (started a clean up for the next trash) Details.MythicPlus.PreviousBossKilledAt = time() --update the saved table inside the profile Details:UpdateState_CurrentMythicDungeonRun(true, Details.MythicPlus.SegmentID, Details.MythicPlus.PreviousBossKilledAt) end function DetailsMythicPlusFrame.MythicDungeonFinished(fromZoneLeft) if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "MythicDungeonFinished() > the dungeon was a Mythic+ and just ended.") end DetailsMythicPlusFrame.IsDoingMythicDungeon = false Details.MythicPlus.Started = false Details.MythicPlus.EndedAt = time()-1.9 Details:UpdateState_CurrentMythicDungeonRun() --at this point, details! should not be in combat, but if something triggered a combat start, just close the combat right away if (Details.in_combat) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "MythicDungeonFinished() > was in combat, calling SairDoCombate():", InCombatLockdown()) end Details:SairDoCombate() Details222.MythicPlus.LogStep("MythicDungeonFinished() | Details was in combat.") end --check if there is trash segments after the last boss. need to merge these segments with the trash segment of the last boss local bCanMergeBossTrash = Details.mythic_plus.merge_boss_trash Details222.MythicPlus.LogStep("MythicDungeonFinished() | merge_boss_trash = " .. (bCanMergeBossTrash and "true" or "false")) --check if there's trash after the last boss, if does, merge it with the trash of the last boss defeated if (bCanMergeBossTrash and not Details.MythicPlus.IsRestoredState and not fromZoneLeft) then --is the current combat not a boss fight? --this mean a combat was opened after the last boss of the dungeon was killed if (not Details.tabela_vigente.is_boss and Details.tabela_vigente:GetCombatTime() > 5) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "MythicDungeonFinished() > the last combat isn't a boss fight, might have trash after bosses done.") end Details222.MythicPlus.MergeTrashAfterLastBoss() end end --merge segments if (Details.mythic_plus.make_overall_when_done and not Details.MythicPlus.IsRestoredState and not fromZoneLeft) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "MythicDungeonFinished() > not in combat, creating overall segment now") end DetailsMythicPlusFrame.MergeSegmentsOnEnd() end Details.MythicPlus.IsRestoredState = nil --shutdown parser for a few seconds to avoid opening new segments after the run ends if (not fromZoneLeft) then Details:CaptureSet(false, "damage", false, 15) Details:CaptureSet(false, "energy", false, 15) Details:CaptureSet(false, "aura", false, 15) Details:CaptureSet(false, "energy", false, 15) Details:CaptureSet(false, "spellcast", false, 15) end end end function DetailsMythicPlusFrame.MythicDungeonStarted() --flag as a mythic dungeon DetailsMythicPlusFrame.IsDoingMythicDungeon = true --this counter is individual for each character Details.mythic_dungeon_id = Details.mythic_dungeon_id + 1 local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo() local mapID = C_Map.GetBestMapForUnit("player") if (not mapID) then return end local ejID = Details:GetInstanceEJID(mapID) --setup the mythic run info Details.MythicPlus.Started = true Details.MythicPlus.DungeonName = zoneName Details.MythicPlus.DungeonID = currentZoneID --Details:Msg("(debug) mythic dungeon start time: ", time()+9.7, "time now:", time(), "diff:", time()+9.7-time()) Details.MythicPlus.StartedAt = time()+9.7 --there's the countdown timer of 10 seconds Details.MythicPlus.EndedAt = nil --reset Details.MythicPlus.SegmentID = 1 Details.MythicPlus.Level = mythicLevel Details.MythicPlus.ejID = ejID Details.MythicPlus.PreviousBossKilledAt = time() Details:SaveState_CurrentMythicDungeonRun(Details.mythic_dungeon_id, zoneName, currentZoneID, time()+9.7, 1, mythicLevel, ejID, time()) local name, groupType, difficultyID, difficult = GetInstanceInfo() if (groupType == "party" and Details.overall_clear_newchallenge) then Details.historico:ResetOverallData() Details:Msg("the overall data has been reset.") --localize-me if (Details.debug) then Details:Msg("(debug) timer is for a mythic+ dungeon, overall has been reseted.") end end if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", "MythicDungeonStarted() > State set to Mythic Dungeon, new combat starting in 10 seconds.") end end function DetailsMythicPlusFrame.OnChallengeModeStart() --is this a mythic dungeon? local _, _, difficultyID, _, _, _, _, currentZoneID = GetInstanceInfo() if (difficultyID == 8) then --start the dungeon on Details! DetailsMythicPlusFrame.MythicDungeonStarted() Details222.MythicPlus.LogStep("OnChallengeModeStart()") else --print("D! mythic dungeon was already started!") --from zone changed local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo() if (not Details.MythicPlus.Started and Details.MythicPlus.DungeonID == currentZoneID and Details.MythicPlus.Level == mythicLevel) then Details.MythicPlus.Started = true Details.MythicPlus.EndedAt = nil Details.mythic_dungeon_currentsaved.started = true DetailsMythicPlusFrame.IsDoingMythicDungeon = true --print("D! mythic dungeon was NOT already started! debug 2") end end end --make an event listener to sync combat data DetailsMythicPlusFrame.EventListener = Details:CreateEventListener() DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_ENCOUNTER_START") DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_ENCOUNTER_END") DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_PLAYER_ENTER") DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_PLAYER_LEAVE") DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_MYTHICDUNGEON_START") DetailsMythicPlusFrame.EventListener:RegisterEvent("COMBAT_MYTHICDUNGEON_END") function DetailsMythicPlusFrame.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 (Details.streamer_config.disable_mythic_dungeon) then return end if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then local combatObject = ... if (combatObject.is_boss) then if (not combatObject.is_boss.killed) then local encounterName = combatObject.is_boss.encounter local zoneName = combatObject.is_boss.zone local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() --just in case the combat get tagged as boss fight Details.tabela_vigente.is_boss = nil --tag the combat as mythic dungeon trash local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() Details.tabela_vigente.is_mythic_dungeon_trash = { ZoneName = zoneName, MapID = instanceMapID, Level = Details.MythicPlus.Level, EJID = Details.MythicPlus.ejID, } Details222.MythicPlus.LogStep("COMBAT_PLAYER_LEAVE | wiped on boss | key level: | " .. mythicLevel .. " | " .. (encounterName or "") .. " " .. zoneName) else DetailsMythicPlusFrame.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 (Details.streamer_config.disable_mythic_dungeon) then Details222.MythicPlus.LogStep("COMBAT_ENCOUNTER_START | streamer_config.disable_mythic_dungeon is true and the code cannot continue.") 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 (Details.streamer_config.disable_mythic_dungeon) then Details222.MythicPlus.LogStep("COMBAT_ENCOUNTER_END | streamer_config.disable_mythic_dungeon is true and the code cannot continue.") return end local encounterID, encounterName, difficultyID, raidSize, endStatus = ... --nothing elseif (event == "COMBAT_MYTHICDUNGEON_START") then local lowerInstance = Details:GetLowerInstanceNumber() if (lowerInstance) then lowerInstance = Details:GetInstance(lowerInstance) if (lowerInstance) then C_Timer.After(3, function() --if (lowerInstance:IsEnabled()) then --todo, need localization --lowerInstance:InstanceAlert("Details!" .. " " .. "Damage" .. " " .. "Meter", {[[Interface\AddOns\Details\images\minimap]], 16, 16, false}, 3, {function() end}, false, true) --end end) end end --ignore the event if ignoring mythic dungeon special treatment if (Details.streamer_config.disable_mythic_dungeon) then return end --reset spec cache if broadcaster requested if (Details.streamer_config.reset_spec_cache) then Details:Destroy(Details.cached_specs) end C_Timer.After(0.25, DetailsMythicPlusFrame.OnChallengeModeStart) --debugging local mPlusSettings = Details.mythic_plus local result = "" for key, value in pairs(Details.mythic_plus) do if (type(value) ~= "table") then result = result .. key .. " = " .. tostring(value) .. " | " end end local mythicLevel = C_ChallengeMode.GetActiveKeystoneInfo() local zoneName, _, _, _, _, _, _, currentZoneID = GetInstanceInfo() Details222.MythicPlus.LogStep("COMBAT_MYTHICDUNGEON_START | settings: " .. result .. " | level: " .. mythicLevel .. " | zone: " .. zoneName .. " | zoneId: " .. currentZoneID) elseif (event == "COMBAT_MYTHICDUNGEON_END") then --ignore the event if ignoring mythic dungeon special treatment if (Details.streamer_config.disable_mythic_dungeon) then Details222.MythicPlus.LogStep("COMBAT_MYTHICDUNGEON_END | streamer_config.disable_mythic_dungeon is true and the code cannot continue.") 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, DetailsMythicPlusFrame.MythicDungeonFinished) end end DetailsMythicPlusFrame:SetScript("OnEvent", function(_, event, ...) if (event == "START_TIMER") then --DetailsMythicPlusFrame.LastTimer = GetTime() elseif (event == "ZONE_CHANGED_NEW_AREA") then if (DetailsMythicPlusFrame.IsDoingMythicDungeon) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Details!", event, ...) print("Zone changed and is Doing Mythic Dungeon") end --ignore the event if ignoring mythic dungeon special treatment if (Details.streamer_config.disable_mythic_dungeon) then Details222.MythicPlus.LogStep("ZONE_CHANGED_NEW_AREA | streamer_config.disable_mythic_dungeon is true and the code cannot continue.") return end local _, _, difficulty, _, _, _, _, currentZoneID = GetInstanceInfo() if (currentZoneID ~= Details.MythicPlus.DungeonID) then if (DetailsMythicPlusFrame.DevelopmentDebug) then print("Zone changed and the zone is different than the dungeon") end Details222.MythicPlus.LogStep("ZONE_CHANGED_NEW_AREA | player has left the dungeon and Details! finished the dungeon because of that.") --send mythic dungeon end event Details:SendEvent("COMBAT_MYTHICDUNGEON_END") --finish the segment DetailsMythicPlusFrame.BossDefeated(true) --finish the mythic run DetailsMythicPlusFrame.MythicDungeonFinished(true) end end end end)