You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

489 lines
16 KiB

5 years ago
--------------------------------------------------------------------------------
-- Module Declaration
--
local mod, CL = BigWigs:NewBoss("Lady Inerva Darkvein", 2296, 2420)
if not mod then return end
mod:RegisterEnableMob(165521) -- Lady Inerva Darkvein
mod:SetEncounterID(2406)
mod:SetRespawnTime(30)
--------------------------------------------------------------------------------
-- Locals
--
local anima = {}
local concentratedAnimaCount = 1
local conjuredManifestationList = {}
local mobCollector = {}
local conjuredManifestationCount = 1
local enabledContainer = 0 -- 1: Desires, 2: Bottles, 3: Sins, 4: Adds
--------------------------------------------------------------------------------
-- Localization
--
local L = mod:GetLocale()
if L then
L.times = "%dx %s"
L.level = "%s (Level |cffffff00%d|r)"
L.full = "%s (|cffff0000FULL|r)"
L.anima_adds = "Concentrated Anima Adds"
L.anima_adds_desc = "Show a timer for when adds spawn from the Concentrated Anima debuffs."
L.custom_off_experimental = "Enable experimental features"
L.custom_off_experimental_desc = "These features are |cffff0000not tested|r and could |cffff0000spam|r."
L.anima_tracking = "Anima Tracking |cffff0000(Experimental)|r"
L.anima_tracking_desc = "Messages and Bars to track anima levels in the containers.|n|cffaaff00Tip: You might want to disable the information box or bars, depending your preference."
L.anima_tracking_icon = "achievement_boss_darkanimus"
L.custom_on_stop_timers = "Always show ability bars"
L.custom_on_stop_timers_desc = "Just for testing right now"
L.desires = "Desires"
L.bottles = "Bottles"
L.sins = "Sins"
end
--------------------------------------------------------------------------------
-- Initialization
--
local sharedSufferingMarker = mod:AddMarkerOption(false, "player", 1, 324983, 1, 2, 3) -- Shared Suffering
local concentratedAnimaMarker = mod:AddMarkerOption(false, "player", 8, 332664, 8, 7, 6) -- Concentrated Anima
local conjuredManifestationMarker = mod:AddMarkerOption(true, "npc", 8, -22618, 8, 7) -- Conjured Manifestation
function mod:GetOptions()
return {
"custom_off_experimental",
{"anima_tracking", "INFOBOX"},
"custom_on_stop_timers",
331870, -- Focus Anima
-- Container of Desire
{341621, "TANK_HEALER"}, -- Expose Desires
{325382, "TANK"}, -- Warped Desires
{340452, "SAY", "SAY_COUNTDOWN", "ME_ONLY", "ME_ONLY_EMPHASIZE"}, -- Change of Heart
325936, -- Shared Cognition
-- Container of Bottled Anima
325769, -- Bottled Anima
325713, -- Lingering Anima
-- Container of Sin
{324983, "SAY", "ME_ONLY_EMPHASIZE"}, -- Shared Suffering
sharedSufferingMarker,
-- Container of Concentrated Anima
{332664, "SAY", "SAY_COUNTDOWN", "PROXIMITY"}, -- Concentrated Anima
"anima_adds",
concentratedAnimaMarker,
conjuredManifestationMarker,
{331573, "ME_ONLY"}, -- Unconscionable Guilt
331550, -- Condemn
},{
[331870] = "general",
[325379] = -22571, -- Container of Desire
[325769] = -22592, -- Container of Bottled Anima
[324983] = -22599, -- Container of Sin
[332664] = -22567, -- Container of Concentrated Anima
},{
[340452] = CL.bomb, -- Change of Heart (Bomb)
[341621] = L.desires, -- Expose Desires (Desires)
[325769] = L.bottles, -- Bottled Anima (Bottles)
[324983] = L.sins, -- Shared Suffering (Sins)
[332664] = CL.adds, -- Concentrated Anima (Adds)
}
end
function mod:OnBossEnable()
self:RegisterEvent("UPDATE_UI_WIDGET", "WIDGET") -- need to fix BossPrototype implementation before using mod:RegisterWidgetEvent
self:RegisterMessage("BigWigs_BarCreated", "BarCreated")
-- General
self:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", nil, "boss1")
-- Container of Desire
self:Log("SPELL_CAST_START", "ExposeDesires", 341621, 341623, 341625) -- Expose Desires, Expose Cognition, Expose Heart // Each stage of the empowerment.
self:Log("SPELL_AURA_APPLIED", "WarpedDesiresApplied", 325382)
self:Log("SPELL_AURA_APPLIED_DOSE", "WarpedDesiresApplied", 325382)
self:Log("SPELL_AURA_APPLIED", "SharedCognitionApplied", 325936)
self:Log("SPELL_AURA_REMOVED", "SharedCognitionRemoved", 325936)
self:Log("SPELL_AURA_APPLIED", "ChangeOfHeartApplied", 340452)
self:Log("SPELL_AURA_REMOVED", "ChangeOfHeartRemoved", 340452)
-- Container of Bottled Anima
self:Log("SPELL_CAST_START", "BottledAnima", 342280, 342281, 342282) -- Bottled Anima, Lingering Anima, Replicating Anima
-- Container of Sin
self:Log("SPELL_AURA_APPLIED", "SharedSufferingPreDebuffApplied", 355553) -- Shared Suffering Pre-Debuff
self:Log("SPELL_AURA_REMOVED", "SharedSufferingRemoved", 324983) -- Shared Suffering Normal Debuff
-- Container of Concentrated Anima
self:Log("SPELL_CAST_START", "ConcentratedAnima", 342320, 342321) -- Lightly Concentrated Anima, Concentrated Anima
self:Log("SPELL_AURA_APPLIED", "ConcentratedAnimaApplied", 332664, 340477) -- Concentrated Anima, Highly Concentrated Anima
self:Log("SPELL_AURA_REMOVED", "ConcentratedAnimaRemoved", 332664, 340477)
self:Log("SPELL_AURA_APPLIED", "UnconscionableGuiltApplied", 331573)
self:Log("SPELL_AURA_APPLIED_DOSE", "UnconscionableGuiltApplied", 331573)
self:Log("SPELL_CAST_START", "Condemn", 331550)
self:Log("SPELL_AURA_APPLIED", "GroundDamage", 325713) -- Lingering Anima
self:Log("SPELL_PERIODIC_DAMAGE", "GroundDamage", 325713)
self:Log("SPELL_PERIODIC_MISSED", "GroundDamage", 325713)
end
function mod:OnEngage()
conjuredManifestationList = {}
mobCollector = {}
conjuredManifestationCount = 1
concentratedAnimaCount = 1
enabledContainer = 0
anima = {}
self:Bar(341621, 12, L.desires) -- Expose Desires
self:Bar(324983, 23, L.sins) -- Shared Suffering
self:Bar(325769, 33, L.bottles) -- Bottled Anima
self:Bar(332664, self:Mythic() and 44 or 54, CL.count:format(CL.adds, concentratedAnimaCount)) -- Concentrated Anima
if self:GetOption("custom_off_experimental") then
self:OpenInfo("anima_tracking", L.anima_tracking)
end
if self:GetOption(conjuredManifestationMarker) then
self:RegisterTargetEvents("ConjuredManifestationMarker")
end
end
--------------------------------------------------------------------------------
-- Event Handlers
--
do
local abilitysToPause = {
[325064] = true, -- Sins and Suffering
[324983] = true, -- Shared Suffering
[325769] = true, -- Bottled Anima
[332664] = true, -- Concentrated Anima
}
local castPattern = CL.cast:gsub("%%s", ".+")
local function stopAtZeroSec(bar)
if bar.remaining < 0.15 then -- Pause at 0.0
bar:SetDuration(0.01) -- Make the bar look full
bar:Start()
bar:Pause()
bar:SetTimeVisibility(false)
end
end
function mod:BarCreated(_, _, bar, _, key, text)
if self:GetOption("custom_on_stop_timers") and abilitysToPause[key] and not text:match(castPattern) then
bar:AddUpdateFunction(stopAtZeroSec)
end
end
end
function mod:ConjuredManifestationMarker(event, unit, guid)
if self:MobId(guid) == 170197 and conjuredManifestationList[guid] then -- Conjured Manifestation
self:CustomIcon(conjuredManifestationMarker, unit, conjuredManifestationList[guid])
end
end
do
local widgetIds = {
[2380] = {pos = 1, name = "Desires", icon = 325379}, -- Expose Desires
[2399] = {pos = 2, name = "Bottles", icon = 325769}, -- Bottled Anima
[2400] = {pos = 3, name = "Sins", icon = 325064}, -- Sins and Suffering
[2401] = {pos = 4, name = CL.add, icon = 332664}, -- Concentrated Anima
}
local getStatusBarInfo = C_UIWidgetManager.GetStatusBarWidgetVisualizationInfo
function mod:UpdateAnimaInfoBox(pos, text, time)
self:SetInfo("anima_tracking", pos*2-1, text)
if time > 60 then
self:SetInfo("anima_tracking", pos*2, ("%d:%02d"):format(time/60, time%60))
elseif time > 0 then
self:SetInfo("anima_tracking", pos*2, ("%d"):format(time))
else
self:SetInfo("anima_tracking", pos*2, "")
end
end
local soundPrev = 0
function mod:WIDGET(tbl)
if not self:GetOption("custom_off_experimental") then return end
local spell = widgetIds[tbl.widgetID]
if not spell then return end
local info = getStatusBarInfo(tbl.widgetID)
if not info or not info.barValue then return end
local oldInfo = anima[spell.icon]
local curLevel = math.floor(info.barValue / (info.barMax / 3)) + 1
if not oldInfo then -- first time we're seeing it
anima[spell.icon] = {value = info.barValue, level = curLevel, lastUpdate = GetTime()}
else
if curLevel ~= oldInfo.level then
if curLevel > 3 then -- it's full
self:Message("anima_tracking", "cyan", L.full:format(spell.name), spell.icon)
self:StopBar(L.full:format(spell.name))
else
self:Message("anima_tracking", "cyan", L.level:format(spell.name, curLevel), spell.icon)
self:StopBar(L.level:format(spell.name, oldInfo.level))
end
local t = GetTime()
if t-soundPrev > 10 then -- high threshold in case something is really wrong
soundPrev = t
self:PlaySound("anima_tracking", "info")
end
end
local timeDiff = (GetTime() - oldInfo.lastUpdate)
local gain = (info.barValue - oldInfo.value) / timeDiff
if gain > 0 then
local nextLevelAtAnima = (info.barMax / 3) * curLevel
local animaToNext = nextLevelAtAnima - info.barValue
local t = math.ceil(animaToNext / gain)
if animaToNext > 0 then -- safety
local text = curLevel > 2 and L.full:format(spell.name) or L.level:format(spell.name, curLevel + 1)
if math.abs(t - self:BarTimeLeft(text)) > 1 then -- avoid restarting the bar on small differences
self:Bar("anima_tracking", t, text, spell.icon)
end
self:UpdateAnimaInfoBox(spell.pos, text, animaToNext / gain)
end
elseif gain < 0 then
self:StopBar(L.level:format(spell.name, 2)) -- Stopping all for now, just in case
self:StopBar(L.level:format(spell.name, 3))
self:StopBar(L.full:format(spell.name))
self:UpdateAnimaInfoBox(spell.pos, "", 0)
end
anima[spell.icon].value = info.barValue
anima[spell.icon].level = curLevel
anima[spell.icon].lastUpdate = GetTime()
end
end
end
function mod:UNIT_SPELLCAST_SUCCEEDED(_, _, _, spellId)
if spellId == 331844 then -- Focus Anima: Desires
self:Message(331870, "cyan", CL.other:format(self:SpellName(331870), L.desires))
self:PlaySound(331870, "long")
enabledContainer = 1
self:Bar(331870, 97, CL.other:format(self:SpellName(331870), L.bottles)) -- She picks the next one 3s early, hidden cast?
elseif spellId == 331870 then -- Focus Anima: Bottles
self:StopBar(CL.other:format(self:SpellName(331870), L.bottles))
self:Message(331870, "cyan", CL.other:format(self:SpellName(331870), L.bottles))
self:PlaySound(331870, "long")
enabledContainer = 2
self:Bar(331870, 97, CL.other:format(self:SpellName(331870), L.sins))
elseif spellId == 331872 then -- Focus Anima: Sins
self:StopBar(CL.other:format(self:SpellName(331870), L.sins))
self:Message(331870, "cyan", CL.other:format(self:SpellName(331870), L.sins))
self:PlaySound(331870, "long")
enabledContainer = 3
self:Bar(331870, 97, CL.other:format(self:SpellName(331870), CL.adds))
elseif spellId == 331873 then -- Focus Anima: Adds
self:StopBar(CL.other:format(self:SpellName(331870), CL.adds))
self:Message(331870, "cyan", CL.other:format(self:SpellName(331870), CL.adds))
self:PlaySound(331870, "long")
enabledContainer = 4
end
end
function mod:ExposeDesires(args)
self:Message(341621, "purple", CL.casting:format(args.spellName))
self:Bar(341621, enabledContainer == 1 and 9.7 or 12.9, L.desires)
if self:Tanking("boss1") or self:Healer() then
self:PlaySound(341621, "alert")
end
end
function mod:WarpedDesiresApplied(args)
local amount = args.amount or 1
self:NewStackMessage(args.spellId, "purple", args.destName, amount, 2)
if amount > 1 and not self:Tanking("boss1") then
self:PlaySound(args.spellId, "alarm")
end
end
do
local playerList = {}
local prev = 0
function mod:SharedCognitionApplied(args)
local t = args.time
if t-prev > 3 then
prev = t
playerList = {}
end
playerList[#playerList+1] = args.destName
if self:Me(args.destGUID) then
self:PlaySound(args.spellId, "alarm")
self:TargetBar(args.spellId, 21, args.destName)
end
self:NewTargetsMessage(args.spellId, "yellow", playerList)
end
function mod:SharedCognitionRemoved(args)
if self:Me(args.destGUID) then
self:StopBar(args.spellId, args.destName)
end
end
end
function mod:ChangeOfHeartApplied(args)
if self:Me(args.destGUID) then
self:Say(args.spellId, CL.bomb)
self:SayCountdown(args.spellId, 4)
self:PlaySound(args.spellId, "warning")
end
self:TargetBar(args.spellId, 4, args.destName, CL.bomb)
self:TargetMessage(args.spellId, "purple", args.destName, CL.bomb)
end
function mod:ChangeOfHeartRemoved(args)
if self:Me(args.destGUID) then
self:CancelSayCountdown(args.spellId)
end
self:StopBar(args.spellId, args.destName)
end
function mod:BottledAnima(args)
self:Message(325769, "orange", L.bottles)
self:PlaySound(325769, "info")
self:Bar(325769, enabledContainer == 2 and (self:Mythic() and 15 or 30) or (self:Mythic() and 30 or 45), L.bottles)
end
do
local playerList, prev = {}, 0
function mod:SharedSufferingPreDebuffApplied(args)
local t = args.time
if t-prev > 3 then
prev = t
playerList = {}
end
if self:Me(args.destGUID) then
self:Say(324983, L.sins)
self:PlaySound(324983, "warning")
end
local count = #playerList+1
playerList[count] = args.destName
playerList[args.destName] = count -- Set raid marker
self:NewTargetsMessage(324983, "yellow", playerList, 3, L.sins)
self:CustomIcon(sharedSufferingMarker, args.destName, count)
if count == 1 then
self:Bar(324983, enabledContainer == 3 and (self:Mythic() and 30 or 35) or 51, L.sins)
end
end
function mod:SharedSufferingRemoved(args)
self:CustomIcon(sharedSufferingMarker, args.destName)
end
end
do
local playerList, proxList = {}, {}
function mod:ConcentratedAnima()
playerList, proxList = {}, {}
conjuredManifestationList = {}
conjuredManifestationCount = 1
self:StopBar(CL.count:format(CL.adds, concentratedAnimaCount))
concentratedAnimaCount = concentratedAnimaCount + 1
self:CDBar(332664, enabledContainer == 4 and (self:Mythic() and 43 or 51) or (self:Mythic() and 65 or 60), CL.count:format(CL.adds, concentratedAnimaCount))
end
local isOnMe = false
function mod:ConcentratedAnimaApplied(args)
local count = #playerList+1
local icon = 9-count -- 8, 7, 6
proxList[count] = args.destName
playerList[count] = args.destName
playerList[args.destName] = icon -- Set raid marker
if #playerList == 1 then
self:Bar("anima_adds", 10, CL.spawning:format(CL.adds), 332664) -- Adds Spawning
end
if self:Me(args.destGUID) then
isOnMe = true
self:PlaySound(332664, "alarm")
self:Say(332664, CL.rticon:format(args.spellId == 340477 and CL.big_add or CL.small_add, icon))
self:SayCountdown(332664, 10, icon)
self:OpenProximity(332664, 8)
end
self:NewTargetsMessage(332664, "yellow", playerList, CL.adds)
self:CustomIcon(concentratedAnimaMarker, args.destName, icon)
if not isOnMe then
self:OpenProximity(332664, 8, proxList)
end
end
function mod:ConcentratedAnimaRemoved(args)
tDeleteItem(proxList, args.destName)
if self:Me(args.destGUID) then
isOnMe = nil
self:CancelSayCountdown(332664)
self:CloseProximity(332664)
end
if not isOnMe then
if #proxList == 0 then
self:CloseProximity(332664)
else
self:OpenProximity(332664, 8, proxList)
end
end
self:CustomIcon(concentratedAnimaMarker, args.destName)
end
end
function mod:UnconscionableGuiltApplied(args)
local amount = args.amount or 1
self:NewStackMessage(args.spellId, "yellow", args.destName, amount)
self:PlaySound(args.spellId, "alarm", nil, args.destName)
end
function mod:Condemn(args)
local canDo, ready = self:Interrupter(args.sourceGUID)
if canDo then
self:Message(args.spellId, "yellow")
if ready then
self:PlaySound(args.spellId, "alert")
end
end
if self:GetOption(conjuredManifestationMarker) and not mobCollector[args.sourceGUID] and not conjuredManifestationList[args.sourceGUID] then
mobCollector[args.sourceGUID] = true
conjuredManifestationList[args.sourceGUID] = 9-conjuredManifestationCount -- 8, 7 (max 2 adds per wave)
conjuredManifestationCount = conjuredManifestationCount + 1
for k, v in next, conjuredManifestationList do
local unit = self:GetUnitIdByGUID(k)
if unit then
self:CustomIcon(conjuredManifestationMarker, unit, v)
end
end
end
end
do
local prev = 0
function mod:GroundDamage(args)
if self:Me(args.destGUID) then
local t = args.time
if t-prev > 2 then
prev = t
self:PlaySound(args.spellId, "underyou")
self:PersonalMessage(args.spellId, "underyou")
end
end
end
end