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.

448 lines
16 KiB

--------------------------------------------------------------------------------
-- Module Declaration
--
local mod, CL = BigWigs:NewBoss("Halondrus the Reclaimer", 2481, 2463)
if not mod then return end
mod:RegisterEnableMob(180906) -- Halondrus
mod:SetEncounterID(2529)
mod:SetRespawnTime(30)
--------------------------------------------------------------------------------
-- Locals
--
local reclaimCount = 1
local seismicTremorsCount = 1
local misslesCount = 1
local beamCount = 1
local prismCount = 1
local reclamationFormCount = 1
local relocationFormCount = 1
local shatterCount = 1
local intermission = false
local nextStageWarning = 82
--------------------------------------------------------------------------------
-- Timers
--
local missleTimersP3 = {17.1, 25.1, 36.5, 13} -- Earthbreaker Missiles
local intermissionTimersHeroic = {
[364979] = { -- Shatter
[1] = {36, 22.1, 0},
[2] = {29.9, 24.1, 18.0, 0},
},
[365297] = { -- Crushing Prism
[1] = {31.2, 0},
[2] = {47, 0},
},
[361676] = { -- Earthbreaker Missiles
[1] = {10.2, 26.1},
[2] = {6.1, 18.1, 26.1},
}
}
local intermissionTimersMythic = {
[364979] = { -- Shatter
[1] = {24.5, 22.1, 0},
[2] = {18.6, 24.1, 18.0, 0},
},
[365297] = { -- Crushing Prism
[1] = {5.6, 26.0, 14.0, 0},
[2] = {13.6, 18.1, 18.1, 0},
},
[361676] = { -- Earthbreaker Missiles
[1] = {10.5, 26.1, 37.7},
[2] = {6.1, 18.1, 26.1, 46.3},
}
}
local intermissionTimers = mod:Mythic() and intermissionTimersMythic or intermissionTimersHeroic
--------------------------------------------------------------------------------
-- Localization
--
local L = mod:GetLocale()
if L then
L.seismic_tremors = "Motes + Tremors" -- Seismic Tremors
L.earthbreaker_missiles = "Missiles" -- Earthbreaker Missiles
L.crushing_prism = "Prisms" -- Crushing Prism
L.prism = "Prism"
L.ephemeral_fissure = "Fissure"
L.bomb_dropped = "Bomb dropped"
L.custom_on_stop_timers = "Always show ability bars"
L.custom_on_stop_timers_desc = "Halondrus can delay its abilities. When this option is enabled, the bars for those abilities will stay on your screen."
end
--------------------------------------------------------------------------------
-- Initialization
--
local crushingPrismMarker = mod:AddMarkerOption(false, "player", 1, 365297, 1, 2, 3, 4) -- Crushing Prism
function mod:GetOptions()
return {
"stages",
"custom_on_stop_timers",
368969, -- Volatile Charge
360115, -- Reclaim XXX Shield tracker
367079, -- Seismic Tremors
360114, -- Ephemeral Fissure
361676, -- Earthbreaker Missiles
369207, -- Planetcracker Beam
{360977, "TANK"}, -- Lightshatter Beam
{365297, "SAY"}, -- Crushing Prism
crushingPrismMarker,
368363, -- Shattered Prism
364979, -- Shatter
368529, -- Eternity Overdrive
},{
["stages"] = "general",
[360115] = -23915, -- Stage One: The Reclaimer
[362056] = -23917, -- Stage Two: The Shimmering Cliffs
[368529] = -24707, -- Stage Three: A Broken Cycle
},{
[368969] = CL.bomb,
[367079] = L.seismic_tremors,
[360114] = L.ephemeral_fissure,
[361676] = L.earthbreaker_missiles,
[360977] = CL.beam,
[365297] = L.crushing_prism,
}
end
function mod:VerifyEnable(unit)
return UnitCanAttack("player", unit)
end
function mod:OnBossEnable()
self:Log("SPELL_CAST_START", "Reclaim", 360115)
self:Log("SPELL_AURA_APPLIED_DOSE", "ReclaimedDose", 360115)
self:Log("SPELL_AURA_REMOVED", "ReclaimRemoved", 360115)
self:Log("SPELL_CAST_START", "SeismicTremors", 367079)
self:Log("SPELL_CAST_START", "EarthbreakerMissiles", 361676)
self:Log("SPELL_CAST_START", "LightshatterBeam", 360977)
self:Log("SPELL_AURA_APPLIED", "LightshatterBeamApplied", 361309)
self:Log("SPELL_AURA_APPLIED_DOSE", "LightshatterBeamApplied", 361309)
self:Log("SPELL_AURA_APPLIED", "CrushingPrismApplied", 365297)
self:Log("SPELL_AURA_REMOVED", "CrushingPrismRemoved", 365297)
self:Log("SPELL_CAST_START", "ReclamationForm", 359235)
self:Log("SPELL_CAST_START", "RelocationForm", 359236)
self:Log("SPELL_CAST_SUCCESS", "RelocationFormDone", 359236)
self:Log("SPELL_CAST_START", "Shatter", 364979)
self:Log("SPELL_CAST_START", "EternityOverdrive", 368529)
-- Planetcracker Beam, Shattered Prism, Ephemeral Fissure
self:Log("SPELL_AURA_APPLIED", "GroundDamage", 369207, 368363, 360114)
self:Log("SPELL_PERIODIC_DAMAGE", "GroundDamage", 369207, 368363, 360114)
self:Log("SPELL_PERIODIC_MISSED", "GroundDamage", 369207, 368363, 360114)
self:Log("SPELL_AURA_APPLIED", "VolatileChargeApplied", 368969)
self:Log("SPELL_AURA_REMOVED", "VolatileChargeRemoved", 368969)
self:RegisterMessage("BigWigs_BarCreated", "BarCreated")
end
function mod:OnEngage()
self:SetStage(1)
seismicTremorsCount = 1
reclaimCount = 1
misslesCount = 1
beamCount = 1
prismCount = 1
reclamationFormCount = 1
relocationFormCount = 1
shatterCount = 1
intermission = false
nextStageWarning = 79.5
intermissionTimers = self:Mythic() and intermissionTimersMythic or intermissionTimersHeroic
if not self:Easy() then
self:CDBar(360977, 8, CL.beam) -- Lightshatter Beam
end
self:Bar(367079, self:Mythic() and 4.9 or 8, CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:Bar(365297, self:Mythic() and 17 or 21.1, CL.count:format(L.crushing_prism, prismCount))
self:Bar(361676, self:Mythic() and 11 or 43.1, CL.count:format(L.earthbreaker_missiles, misslesCount))
self:Bar(360115, 61.2, CL.count:format(self:SpellName(360115), reclaimCount))
self:RegisterUnitEvent("UNIT_HEALTH", nil, "boss1")
end
--------------------------------------------------------------------------------
-- Event Handlers
--
function mod:UNIT_HEALTH(event, unit)
local currentHealth = self:GetHealth(unit)
if currentHealth < nextStageWarning then -- Intermission at 77.5% and 45%
self:Message("stages", "green", CL.soon:format(CL.intermission), false)
nextStageWarning = nextStageWarning - 32.5
if nextStageWarning < 40 then
self:UnregisterUnitEvent(event, unit)
end
end
end
do
local abilitysToPause = {
[361676] = true, -- Earthbreaker Missiles
[365297] = true, -- Crushing Prism
[367079] = true, -- Seismic Tremors
[360115] = true, -- Reclaim
[360977] = true, -- Lightshattter Beam
}
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:VolatileChargeApplied(args)
if self:Me(args.destGUID) then
self:PersonalMessage(args.spellId, nil, CL.bomb)
self:Bar(args.spellId, 10, CL.explosion)
self:PlaySound(args.spellId, "alarm")
end
end
function mod:VolatileChargeRemoved(args)
if self:Me(args.destGUID) then
self:Message(args.spellId, "green", L.bomb_dropped)
self:StopBar(CL.explosion)
self:PlaySound(args.spellId, "info")
end
end
function mod:Reclaim(args)
self:StopBar(CL.count:format(args.spellName, reclaimCount))
self:StopBar(CL.count:format(L.earthbreaker_missiles, misslesCount))
self:StopBar(CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:StopBar(CL.count:format(L.crushing_prism, prismCount))
self:StopBar(CL.beam) -- Lightshatter Beam
self:Message(args.spellId, "red", CL.count:format(args.spellName, reclaimCount))
self:PlaySound(args.spellId, "long")
self:CastBar(args.spellId, 4, CL.count:format(args.spellName, reclaimCount))
end
function mod:ReclaimedDose(args)
if args.amount > 2 and args.amount % 2 == 1 then -- ramps every 4, warn every other starting with 3
self:Message(args.spellId, "red", ("%dx %s (%d)"):format(args.amount, args.spellName, reclaimCount))
self:PlaySound(args.spellId, "alarm")
end
end
function mod:ReclaimRemoved(args)
self:Message(args.spellId, "green", CL.removed:format(CL.count:format(args.spellName, reclaimCount)))
self:PlaySound(args.spellId, "info")
reclaimCount = reclaimCount + 1
self:Bar(360115, 61.2, CL.count:format(self:SpellName(360115), reclaimCount))
if not self:Easy() then
self:CDBar(360977, 8, CL.beam) -- Lightshatter Beam
end
self:Bar(367079, 4.5, CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:Bar(365297, self:Mythic() and 17 or 8, CL.count:format(L.crushing_prism, prismCount))
self:Bar(361676, 11, CL.count:format(L.earthbreaker_missiles, misslesCount))
end
function mod:SeismicTremors(args)
self:StopBar(CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:Message(args.spellId, "yellow", CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:PlaySound(args.spellId, "alert")
seismicTremorsCount = seismicTremorsCount + 1
if seismicTremorsCount <= reclaimCount * 2 then
self:Bar(args.spellId, self:Mythic() and 27.5 or 26, CL.count:format(L.seismic_tremors, seismicTremorsCount))
end
end
function mod:EarthbreakerMissiles(args)
self:StopBar(CL.count:format(L.earthbreaker_missiles, misslesCount))
self:Message(args.spellId, "orange", CL.count:format(L.earthbreaker_missiles, misslesCount))
self:PlaySound(args.spellId, "alert")
misslesCount = misslesCount + 1
if intermission then
self:CDBar(args.spellId, intermissionTimers[args.spellId][relocationFormCount-1][misslesCount], CL.count:format(L.earthbreaker_missiles, misslesCount))
elseif self:GetStage() == 3 then
if misslesCount < (self:Mythic() and 4 or 5) then
self:CDBar(args.spellId, missleTimersP3[misslesCount] or 0, CL.count:format(L.earthbreaker_missiles, misslesCount))
end
elseif self:Mythic() then
if misslesCount <= reclaimCount * 2 then
self:CDBar(args.spellId, 26, CL.count:format(L.earthbreaker_missiles, misslesCount))
end
elseif (reclaimCount > 1 or relocationFormCount > 1) and misslesCount <= reclaimCount * 2 then
-- only one earthbreaker before the first reclaim in normal/heroic
self:CDBar(args.spellId, 26, CL.count:format(L.earthbreaker_missiles, misslesCount))
end
end
function mod:LightshatterBeam(args)
self:Message(args.spellId, "purple", CL.beam)
self:PlaySound(args.spellId, "alert")
beamCount = beamCount + 1
if beamCount % 2 == 0 then
self:CDBar(args.spellId, 4.9, CL.beam)
else
self:CDBar(args.spellId, 7.0, CL.beam)
end
end
function mod:LightshatterBeamApplied(args)
if self:Tank() then
self:NewStackMessage(360977, "purple", args.destName, args.amount, nil, CL.beam)
if not self:Me(args.destGUID) and not self:Tanking("boss1") then
self:PlaySound(360977, "warning")
end
end
end
do
local prev = 0
local playerList = {}
function mod:CrushingPrismApplied(args)
local t = args.time
if t-prev > 5 then
prev = t
self:StopBar(CL.count:format(L.crushing_prism, prismCount))
prismCount = prismCount + 1
playerList = {}
if intermission then
self:CDBar(args.spellId, intermissionTimers[args.spellId][relocationFormCount-1][prismCount], CL.count:format(L.crushing_prism, prismCount))
elseif prismCount <= reclaimCount * 2 then
self:CDBar(args.spellId, 26, CL.count:format(L.crushing_prism, prismCount))
end
end
local count = #playerList+1
playerList[count] = args.destName
playerList[args.destName] = count -- Set raid marker
if self:Me(args.destGUID) then
self:PlaySound(args.spellId, "alarm")
self:Say(args.spellId, L.prism)
end
self:NewTargetsMessage(args.spellId, "yellow", playerList, nil, CL.count:format(L.crushing_prism, prismCount-1))
self:CustomIcon(crushingPrismMarker, args.destName, count)
end
function mod:CrushingPrismRemoved(args)
if self:Me(args.destGUID) then
self:Message(args.spellId, "green", CL.removed:format(L.prism))
self:PlaySound(args.spellId, "info")
end
self:CustomIcon(crushingPrismMarker, args.destName, 0)
end
end
function mod:ReclamationForm(args)
if not self:IsEngaged() then return end -- Casts it after respawning
local stage = self:GetStage()
stage = stage + 1
self:SetStage(stage)
self:Message("stages", "cyan", CL.stage:format(stage), false)
self:PlaySound("stages", "long")
self:CastBar("stages", 6, CL.cast:format(args.spellName), args.spellId)
reclamationFormCount = reclamationFormCount + 1
intermission = false
self:StopBar(CL.count:format(CL.intermission, reclamationFormCount))
self:StopBar(CL.count:format(L.crushing_prism, prismCount))
self:StopBar(CL.count:format(L.earthbreaker_missiles, misslesCount))
self:StopBar(CL.count:format(self:SpellName(362056), shatterCount))
seismicTremorsCount = 1
beamCount = 1
misslesCount = 1
prismCount = 1
reclaimCount = 1
if not self:Easy() then
self:Bar(360977, 14.1, CL.beam) -- Lightshatter Beam
end
if stage == 2 then
self:Bar(367079, 10, CL.count:format(L.seismic_tremors, seismicTremorsCount)) -- Seismic Tremors
self:Bar(361676, 18, CL.count:format(L.earthbreaker_missiles, misslesCount)) -- Earthbreaker Missiles
self:Bar(365297, 23, CL.count:format(L.crushing_prism, prismCount)) -- Crushing Prism
self:Bar(360115, 69.4, CL.count:format(self:SpellName(360115), reclaimCount)) -- Reclaim
elseif stage == 3 then
self:Bar(368529, 7.6) -- Eternity Overdrive
self:Bar(361676, missleTimersP3[misslesCount], CL.count:format(L.earthbreaker_missiles, misslesCount)) -- Earthbreaker Missiles
end
end
function mod:RelocationForm(args)
self:Message("stages", "cyan", CL.count:format(CL.intermission, relocationFormCount), args.spellId)
self:PlaySound("stages", "long")
self:CastBar("stages", 5.5, CL.cast:format(args.spellName), args.spellId)
self:CDBar("stages", relocationFormCount == 1 and 62 or 85, CL.stage:format(self:GetStage() + 1), args.spellId)
relocationFormCount = relocationFormCount + 1
self:StopBar(CL.beam) -- Lightshatter Beam
-- self:StopBar(CL.count:format(L.earthbreaker_missiles, misslesCount))
-- self:StopBar(CL.count:format(L.seismic_tremors, seismicTremorsCount))
-- self:StopBar(CL.count:format(L.crushing_prism, prismCount))
-- self:StopBar(CL.count:format(self:SpellName(360115), reclaimCount))
end
function mod:RelocationFormDone()
-- Some timers can still trigger just after _START, using _SUCCESS to start bars instead
self:StopBar(CL.count:format(L.earthbreaker_missiles, misslesCount))
self:StopBar(CL.count:format(L.seismic_tremors, seismicTremorsCount))
self:StopBar(CL.count:format(L.crushing_prism, prismCount))
self:StopBar(CL.count:format(self:SpellName(360115), reclaimCount))
intermission = true
misslesCount = 1
shatterCount = 1
prismCount = 1
self:CDBar(361676, intermissionTimers[361676][relocationFormCount-1][misslesCount], CL.count:format(L.earthbreaker_missiles, misslesCount))
self:CDBar(364979, intermissionTimers[364979][relocationFormCount-1][shatterCount], CL.count:format(self:SpellName(364979), shatterCount))
self:CDBar(365297, intermissionTimers[365297][relocationFormCount-1][prismCount], CL.count:format(L.crushing_prism, prismCount))
end
function mod:Shatter(args)
self:StopBar(CL.count:format(args.spellName, shatterCount))
self:Message(args.spellId, "yellow", CL.count:format(args.spellName, shatterCount))
self:PlaySound(args.spellId, "long")
self:CastBar(args.spellId, 6, CL.knockback)
shatterCount = shatterCount + 1
self:Bar(args.spellId, intermissionTimers[args.spellId][relocationFormCount-1][shatterCount], CL.count:format(args.spellName, shatterCount))
end
function mod:EternityOverdrive(args)
self:Message(args.spellId, "red")
self:PlaySound(args.spellId, "long")
end
do
local prev = 0
local message = {
[368363] = L.prism, -- Shattered Prism (Prism)
[360114] = L.ephemeral_fissure, -- Ephemeral Fissure (Fissure)
}
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", message[args.spellId])
end
end
end
end