local mod = DBM:NewMod(1873, "DBM-Raids-Legion", 2, 875) local L = mod:GetLocalizedStrings() mod:SetRevision("20240426185020") mod:SetCreatureID(116939)--Maiden of Valor 120437 mod:SetEncounterID(2038) mod:SetBossHPInfoToHighest() mod:SetUsedIcons(1, 2, 3, 4, 5, 6) mod:SetHotfixNoticeRev(16307) mod.respawnTime = 25 mod:RegisterCombat("combat") mod:RegisterEventsInCombat( "SPELL_CAST_START 239207 239132 235572 233856 233556 240623 235597", "SPELL_CAST_SUCCESS 236494 233556", "SPELL_AURA_APPLIED 234059 236494 240728 239739 241008", "SPELL_AURA_APPLIED_DOSE 236494 240728", "SPELL_AURA_REMOVED 239739 241008", "SPELL_PERIODIC_DAMAGE 239212", "SPELL_PERIODIC_MISSED 239212", "CHAT_MSG_RAID_BOSS_EMOTE", "RAID_BOSS_WHISPER", "UNIT_SPELLCAST_SUCCEEDED boss1 boss2" ) mod:RegisterEvents( "CHAT_MSG_MONSTER_YELL" ) --[[ (ability.id = 239207 or ability.id = 239132 or ability.id = 236571 or ability.id = 233856 or ability.id = 233556 or ability.id = 240623 or ability.id = 239418 or ability.id = 235597 or ability.id = 235572) and type = "begincast" or (ability.id = 236571 or ability.id = 236494) and type = "cast" or (ability.id = 234009 or ability.id = 234059 or ability.id = 239739) and type = "applydebuff" or ability.name = "Shadowy Blades" --]] --Stage One: A Slumber Disturbed local warnUnboundChaos = mod:NewTargetAnnounce(234059, 3, nil, false, 2) local warnShadowyBlades = mod:NewTargetAnnounce(236571, 3) local warnDesolate = mod:NewStackAnnounce(236494, 3, nil, "Healer|Tank") local warnCleansingEnded = mod:NewEndAnnounce(241008, 1) local warnTaintedMatrix = mod:NewCastAnnounce(240623, 3) --Stage Two: An Avatar Awakened local warnPhase2 = mod:NewPhaseAnnounce(2, 2, nil, nil, nil, nil, nil, 2) local warnDarkmark = mod:NewTargetCountAnnounce(239739, 3) --Stage One: A Slumber Disturbed local specWarnTouchofSargerasGround = mod:NewSpecialWarningCount(239207, "-Tank", nil, 2, 1, 2) local specWarnRuptureRealities = mod:NewSpecialWarningRun(239132, nil, nil, nil, 4, 2) local specWarnUnboundChaos = mod:NewSpecialWarningDodge(234059, nil, nil, nil, 2, 2) local yellUnboundChaos = mod:NewYell(234059, nil, false, 2) local specWarnShadowyBlades = mod:NewSpecialWarningMoveAway(236571, nil, nil, nil, 1, 2) local yellShadowyBlades = mod:NewPosYell(236571) local specWarnLingeringDarkness = mod:NewSpecialWarningMove(239212, nil, nil, nil, 1, 2) local specWarnDesolateYou = mod:NewSpecialWarningStack(236494, nil, 2, nil, nil, 1, 6) local specWarnDesolateOther = mod:NewSpecialWarningTaunt(236494, nil, nil, nil, 1, 2) ----Maiden of Valor local specWarnCorruptedMatrix = mod:NewSpecialWarningMoveTo(233556, "Tank", nil, nil, 1, 7) local specWarnCleansingProtocol = mod:NewSpecialWarningSwitch(233856, "-Healer", nil, nil, 3, 2) local specWarnTaintedEssence = mod:NewSpecialWarningStack(240728, nil, 6, nil, nil, 1, 6) local yellTaintedEssence = mod:NewShortFadesYell(240728) --Stage Two: An Avatar Awakened local specWarnDarkMark = mod:NewSpecialWarningYouPos(239739, nil, nil, nil, 1, 2) local specWarnDarkMarkOther = mod:NewSpecialWarningMoveTo(239739, nil, nil, nil, 1, 2) local yellDarkMark = mod:NewPosYell(239739, DBM_CORE_L.AUTO_YELL_CUSTOM_POSITION) local yellDarkMarkFades = mod:NewIconFadesYell(239739) local specWarnRainoftheDestroyer = mod:NewSpecialWarningCount(240396, nil, nil, 2, 3, 2) --Stage One: A Slumber Disturbed local timerRP = mod:NewRPTimer(41) mod:AddTimerLine(SCENARIO_STAGE:format(1)) local timerTouchofSargerasCD = mod:NewCDCountTimer(42, 239207, nil, nil, nil, 3)--42+ local timerRuptureRealitiesCD = mod:NewCDCountTimer(60, 239132, nil, nil, nil, 2, nil, nil, nil, 1, 4) local timerUnboundChaosCD = mod:NewCDCountTimer(35, 234059, nil, nil, nil, 3)--35-60 (lovely huh?) local timerShadowyBladesCD = mod:NewCDTimer(30, 236571, nil, nil, nil, 3)--30-46 local timerDesolateCD = mod:NewCDTimer(11.4, 236494, nil, "Tank", nil, 5, nil, DBM_COMMON_L.TANK_ICON, nil, 2, 3) ----Maiden of Valor mod:AddTimerLine(DBM:EJ_GetSectionInfo(14713)) local timerCorruptedMatrixCD = mod:NewNextTimer(40, 233556, nil, nil, nil, 5, nil, nil, nil, 3, 4) local timerCorruptedMatrix = mod:NewCastTimer(10, 233556, nil, nil, nil, 5) --Stage Two: An Avatar Awakened mod:AddTimerLine(SCENARIO_STAGE:format(2)) local timerDarkMarkCD = mod:NewNextCountTimer(34, 239739, nil, nil, nil, 3, nil, nil, nil, not mod:IsTank() and 2 or nil, 4) local timerRainoftheDestroyerCD = mod:NewNextCountTimer(35, 240396, nil, nil, nil, 3) local timerRainoftheDestroyer = mod:NewCastTimer(5.5, 240396, 206577, nil, nil, 3, nil, nil, nil, 3, 4)--Shortname: Comet Impact local berserkTimer = mod:NewBerserkTimer(420) mod:AddSetIconOption("SetIconOnShadowyBlades", 236571, true) mod:AddSetIconOption("SetIconOnDarkMark", 239739, true) mod:AddBoolOption("InfoFrame", true) mod:AddRangeFrameOption(10, 236571) local abilitiesonCD = { [239207] = true,--Touch of Sargeras [239132] = true,--Rupture Realities [234059] = true,--Unbound Chaos [236571] = true--Shadowy Blades } mod.vb.phase = 1 mod.vb.bladesIcon = 1 mod.vb.shieldActive = false mod.vb.touchCast = 0 mod.vb.darkMarkCast = 0 mod.vb.chaosCount = 0 mod.vb.realityCount = 0 mod.vb.rainCount = 0 local darkMarkTargets = {} local playerName = UnitName("player") local beamName = DBM:GetSpellName(238244) local touch, rupture, unbound, shadowy, shieldName = DBM:GetSpellName(239207), DBM:GetSpellName(239132), DBM:GetSpellName(234059), DBM:GetSpellName(236571), DBM:GetSpellName(241008) local showTouchofSarg = true local function warnDarkMarkTargets(self, spellName) -- table.sort(darkMarkTargets) warnDarkmark:Show(self.vb.darkMarkCast, table.concat(darkMarkTargets, "<, >")) --if self:IsLFR() then return end for i = 1, #darkMarkTargets do local icon = i == 1 and 6 or i == 2 and 4 or i == 3 and 3--Bigwigs icon compatability local name = darkMarkTargets[i] if name == playerName then yellDarkMark:Yell(icon, spellName, icon) local _, _, _, _, _, expires = DBM:UnitDebuff("player", spellName) if expires then local remaining = expires-GetTime() yellDarkMarkFades:Countdown(remaining, nil, icon) end specWarnDarkMark:Show(self:IconNumToTexture(icon)) specWarnDarkMark:Play("targetyou") end if self.Options.SetIconOnDarkMark then self:SetIcon(name, icon) end end if not DBM:UnitDebuff("player", spellName) then specWarnDarkMarkOther:Show(DBM_COMMON_L.ALLY) specWarnDarkMarkOther:Play("gathershare") end end local function setabilityStatus(self, spellId, status) if status == 1 then--Ability on cooldown abilitiesonCD[spellId] = true else--Ability ready to use abilitiesonCD[spellId] = false end end local updateInfoFrame do local lines = {} local sortedLines = {} local function addLine(key, value) -- sort by insertion order lines[key] = value sortedLines[#sortedLines + 1] = key end updateInfoFrame = function() table.wipe(lines) table.wipe(sortedLines) --Maiden shield amount i active first if mod.vb.shieldActive then local absorbAmount = select(16, DBM:UnitBuff("boss2", shieldName)) or select(16, DBM:UnitDebuff("boss2", shieldName)) if absorbAmount then local percent = absorbAmount / mod.vb.shieldActive * 100 addLine(shieldName, math.floor(percent)) end end --Boss Powers second for i = 1, 2 do local uId = "boss"..i if UnitExists(uId) then local currentPower = UnitPower(uId) or 0 addLine(UnitName(uId), currentPower) end end --Fallen Avatar Cooldowns third --addLine(L.Oncooldown, "") if showTouchofSarg then if abilitiesonCD[239207] then--Touch of Sargeras addLine(touch, "|cFF088A08"..YES.."|r") else addLine(touch, "|cffff0000"..NO.."|r") end end if abilitiesonCD[239132] then--Rupture Realities addLine(rupture, "|cFF088A08"..YES.."|r") else addLine(rupture, "|cffff0000"..NO.."|r") end if abilitiesonCD[234059] then--Unbound Chaos addLine(unbound, "|cFF088A08"..YES.."|r") else addLine(unbound, "|cffff0000"..NO.."|r") end if abilitiesonCD[236571] then--Shadowy Blades addLine(shadowy, "|cFF088A08"..YES.."|r") else addLine(shadowy, "|cffff0000"..NO.."|r") end return lines, sortedLines end end function mod:OnCombatStart(delay) table.wipe(darkMarkTargets) self.vb.phase = 1 self.vb.bladesIcon = 1 self.vb.touchCast = 0 self.vb.darkMarkCast = 0 self.vb.chaosCount = 0 self.vb.realityCount = 0 self.vb.rainCount = 0 timerUnboundChaosCD:Start(7-delay, 1)--7 self:Schedule(7, setabilityStatus, self, 234059, 0)--Unbound Chaos timerDesolateCD:Start(13-delay)--13 if not self:IsEasy() then showTouchofSarg = true timerTouchofSargerasCD:Start(14.5-delay, 1) self:Schedule(14.5, setabilityStatus, self, 239207, 0)--Touch of Sargeras else showTouchofSarg = false end timerShadowyBladesCD:Start(27-delay) self:Schedule(27, setabilityStatus, self, 236571, 0)--Shadowy Blades timerRuptureRealitiesCD:Start(31-delay, 1)--31-37 self:Schedule(31, setabilityStatus, self, 239132, 0)--Ruptured Realities if self.Options.InfoFrame then DBM.InfoFrame:SetHeader(OVERVIEW) --DBM.InfoFrame:Show(2, "enemypower", 2) DBM.InfoFrame:Show(7, "function", updateInfoFrame, false, false) end if self:IsLFR() then--7 min in LFR berserkTimer:Start(-delay) end end function mod:OnCombatEnd() if self.Options.RangeFrame then DBM.RangeCheck:Hide() end if self.Options.InfoFrame then DBM.InfoFrame:Hide() end end function mod:SPELL_CAST_START(args) local spellId = args.spellId if spellId == 239207 then self.vb.touchCast = self.vb.touchCast + 1 specWarnTouchofSargerasGround:Show(self.vb.touchCast) specWarnTouchofSargerasGround:Play("helpsoak") self:Unschedule(setabilityStatus, self, 239207)--Unschedule for good measure in case next cast start fires before timer expires (in which case have a bad timer) setabilityStatus(self, 239207, 1)--Set on Cooldown if self:IsMythic() then timerTouchofSargerasCD:Start(60, self.vb.touchCast+1)--42 self:Schedule(60, setabilityStatus, self, 239207, 0)--Set ready to use when CD expires else timerTouchofSargerasCD:Start(42, self.vb.touchCast+1)--42 self:Schedule(42, setabilityStatus, self, 239207, 0)--Set ready to use when CD expires end elseif spellId == 239132 or spellId == 235572 then self.vb.realityCount = self.vb.realityCount + 1 specWarnRuptureRealities:Show() specWarnRuptureRealities:Play("justrun") if self.vb.phase == 2 then timerRuptureRealitiesCD:Start(37, self.vb.realityCount+1) local elapsedDark, totalDark = timerDarkMarkCD:GetTime(self.vb.darkMarkCast+1) local remaining = totalDark - elapsedDark if remaining < 9.8 then if totalDark == 0 then--Timer aleady expired timerDarkMarkCD:Start(9.8, self.vb.darkMarkCast+1) DBM:Debug("Timer extend firing for Dark Mark. Extend amount: ".."9.8", 2) else local extend = 9.8 - totalDark timerDarkMarkCD:Update(elapsedDark, totalDark+extend, self.vb.darkMarkCast+1) DBM:Debug("Timer extend firing for Dark Mark. Extend amount: "..extend, 2) end end else timerRuptureRealitiesCD:Start(60, self.vb.realityCount+1)--60 self:Unschedule(setabilityStatus, self, 239132)--Unschedule for good measure in case next cast start fires before timer expires (in which case have a bad timer) setabilityStatus(self, 239132, 1)--Set on cooldown self:Schedule(60, setabilityStatus, self, 239132, 0)--Set ready to use when CD expires end elseif spellId == 233856 then specWarnCleansingProtocol:Show() specWarnCleansingProtocol:Play("targetchange") elseif spellId == 233556 and self:AntiSpam(2, 2) and self.vb.phase == 1 and not self:IsLFR() then specWarnCorruptedMatrix:Show(beamName) specWarnCorruptedMatrix:Play("bosstobeam") if self:IsMythic() then timerCorruptedMatrix:Start(8) else timerCorruptedMatrix:Start(10) end elseif spellId == 240623 and self:AntiSpam(2, 3) and self.vb.phase == 1 then warnTaintedMatrix:Show() elseif spellId == 235597 then self:Unschedule(setabilityStatus)--Unschedule all self.vb.phase = 2 timerTouchofSargerasCD:Stop() timerShadowyBladesCD:Stop() timerRuptureRealitiesCD:Stop() timerDesolateCD:Stop() timerUnboundChaosCD:Stop() timerCorruptedMatrix:Stop() timerCorruptedMatrixCD:Stop() warnPhase2:Show() warnPhase2:Play("ptwo") timerDesolateCD:Start(19) timerRuptureRealitiesCD:Start(38, 1) if self.Options.InfoFrame then DBM.InfoFrame:Hide() end if self:IsMythic() then timerRainoftheDestroyerCD:Start(15, 1) timerDarkMarkCD:Start(31.6, 1) else timerDarkMarkCD:Start(21, 1) end end end function mod:SPELL_CAST_SUCCESS(args) local spellId = args.spellId if spellId == 236494 then timerDesolateCD:Start() elseif spellId == 233556 and self:AntiSpam(2, 4) then if self:IsMythic() then timerCorruptedMatrixCD:Start(12) else timerCorruptedMatrixCD:Start() end end end function mod:SPELL_AURA_APPLIED(args) local spellId = args.spellId if spellId == 239739 then if not tContains(darkMarkTargets, args.destName) then darkMarkTargets[#darkMarkTargets+1] = args.destName end self:Unschedule(warnDarkMarkTargets) if #darkMarkTargets == 3 then warnDarkMarkTargets(self, args.spellName) else self:Schedule(0.5, warnDarkMarkTargets, self, args.spellName)--At least 0.5, maybe bigger needed if warning still splits end -- if args:IsPlayer() then -- specWarnDarkMark:Show(self:IconNumToString()) -- specWarnDarkMark:Play("targetyou") -- end elseif spellId == 234059 then warnUnboundChaos:CombinedShow(0.3, args.destName) if args:IsPlayer() then yellUnboundChaos:Yell() end elseif spellId == 236494 then local amount = args.amount or 1 if amount >= 2 then if args:IsPlayer() then specWarnDesolateYou:Show(amount) specWarnDesolateYou:Play("stackhigh") else local _, _, _, _, _, expireTime = DBM:UnitDebuff("player", args.spellName) local remaining if expireTime then remaining = expireTime-GetTime() end if not UnitIsDeadOrGhost("player") and (not remaining or remaining and remaining < 10) then specWarnDesolateOther:Show(args.destName) specWarnDesolateOther:Play("tauntboss") else warnDesolate:Show(args.destName, amount) end end else warnDesolate:Show(args.destName, amount) end elseif spellId == 240728 then if args:IsPlayer() then local amount = args.amount or 1 if amount >= 6 then specWarnTaintedEssence:Show(amount) specWarnTaintedEssence:Play("stackhigh") yellTaintedEssence:Yell(amount) end end elseif spellId == 241008 then--Cleansing Protocol Shield self.vb.shieldActive = UnitGetTotalAbsorbs("boss2") end end mod.SPELL_AURA_APPLIED_DOSE = mod.SPELL_AURA_APPLIED function mod:SPELL_AURA_REMOVED(args) local spellId = args.spellId if spellId == 239739 then if args:IsPlayer() then yellDarkMarkFades:Cancel() end if self.Options.SetIconOnDarkMark then self:SetIcon(args.destName, 0) end elseif spellId == 241008 then--Cleansing Protocol Shield self.vb.shieldActive = false warnCleansingEnded:Show() end end function mod:SPELL_PERIODIC_DAMAGE(_, _, _, _, destGUID, _, _, _, spellId) if spellId == 239212 and destGUID == UnitGUID("player") and self:AntiSpam(2, 1) then specWarnLingeringDarkness:Show() specWarnLingeringDarkness:Play("runaway") end end mod.SPELL_PERIODIC_MISSED = mod.SPELL_PERIODIC_DAMAGE function mod:CHAT_MSG_RAID_BOSS_EMOTE(msg, npc, _, _, target) if msg:find("234418") then self.vb.rainCount = self.vb.rainCount + 1 specWarnRainoftheDestroyer:Show(self.vb.rainCount) specWarnRainoftheDestroyer:Play("helpsoak") timerRainoftheDestroyer:Start() timerRainoftheDestroyerCD:Start(nil, self.vb.rainCount+1) end end function mod:RAID_BOSS_WHISPER(msg) if msg:find("236604") then specWarnShadowyBlades:Show() specWarnShadowyBlades:Play("runout") --yellShadowyBlades:Yell() end end function mod:OnTranscriptorSync(msg, targetName) if msg:find("236604") then targetName = Ambiguate(targetName, "none") if self:AntiSpam(4, targetName) then local icon = self.vb.bladesIcon warnShadowyBlades:CombinedShow(0.5, targetName) if self.Options.SetIconOnShadowyBlades then self:SetIcon(targetName, icon, 5) end if targetName == playerName then yellShadowyBlades:Yell(icon, icon, icon) end self.vb.bladesIcon = self.vb.bladesIcon + 1 end end end function mod:CHAT_MSG_MONSTER_YELL(msg, npc, _, _, target) if (msg == L.FallenAvatarDialog or msg:find(L.FallenAvatarDialog)) then self:SendSync("FallenAvatarRP")--Syncing to help unlocalized clients end end function mod:UNIT_SPELLCAST_SUCCEEDED(uId, _, spellId) if spellId == 234057 then self.vb.chaosCount = self.vb.chaosCount + 1 specWarnUnboundChaos:Show() specWarnUnboundChaos:Play("watchstep") timerUnboundChaosCD:Start(nil, self.vb.chaosCount+1)--35 self:Unschedule(setabilityStatus, self, 234059)--Unschedule for good measure in case next cast start fires before timer expires (in which case have a bad timer) setabilityStatus(self, 234059, 1)--Set on cooldown self:Schedule(35, setabilityStatus, self, 234059, 0)--Set ready to use when CD expires elseif spellId == 239739 or spellId == 239825 then table.wipe(darkMarkTargets) self.vb.darkMarkCast = self.vb.darkMarkCast + 1 if self:IsMythic() then timerDarkMarkCD:Start(25, self.vb.darkMarkCast+1) else timerDarkMarkCD:Start(nil, self.vb.darkMarkCast+1)--34 end elseif spellId == 236571 or spellId == 236573 then--Shadow Blades self.vb.bladesIcon = 1--SHOULD always fire first self:Unschedule(setabilityStatus, self, 236571)--Unschedule for good measure in case next cast start fires before timer expires (in which case have a bad timer) setabilityStatus(self, 236571, 1)--Set on cooldown if self:IsEasy() then timerShadowyBladesCD:Start(34) self:Schedule(34, setabilityStatus, self, 236571, 0)--Set ready to use when CD expires else if self:IsMythic() then timerShadowyBladesCD:Start(35) self:Schedule(35, setabilityStatus, self, 236571, 0)--Set ready to use when CD expires else timerShadowyBladesCD:Start(30) self:Schedule(30, setabilityStatus, self, 236571, 0)--Set ready to use when CD expires end end if self.Options.RangeFrame then DBM.RangeCheck:Show(10, nil, nil, nil, nil, 5) end end end function mod:OnSync(msg, targetname) if msg == "FallenAvatarRP" and self:AntiSpam(60, 6) then timerRP:Start() end end