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.

601 lines
20 KiB

--------------------------------------------------------------------------------
-- TODO List:
-- - Get/Confirm timers for all difficulties on live
-- LFR (✘) - Normal (✘) - Heroic (✔) - Mythic (✔)
-- - Horn of Valor CD in p2
--------------------------------------------------------------------------------
-- Module Declaration
--
local mod, CL = BigWigs:NewBoss("Odyn-TrialOfValor", 1648, 1819)
if not mod then return end
mod:RegisterEnableMob(114263, 114361, 114360) -- Odyn, Hymdall, Hyrja
mod.engageId = 1958
mod.respawnTime = 30
--------------------------------------------------------------------------------
-- Locals
--
local phase = 1
local hornCount = 1
local shieldCount = 1
local expelCount = 1
local spearCount = 1
local stormCount = 1
local runesUp = 0
local myAddGUID = ""
local castingHorn = false
local addGUIDs = {}
local isHymdallFighting, isHyrjaFighting = false, false
local revivifyBarTexts = {}
local addFixates = {}
local proxLists = {
[231311] = {}, -- Boss_OdunRunes_Purple
[231342] = {}, -- Boss_OdunRunes_Orange
[231344] = {}, -- Boss_OdunRunes_Yellow
[231345] = {}, -- Boss_OdunRunes_Blue
[231346] = {}, -- Boss_OdunRunes_Green
}
local timers = { -- Mythic P1 is timed
[228012] = {8, 22, 20, 35, 53}, -- Horn of Valor
[228162] = {20, 20, 33, 22, 20, 35}, -- Shield of Light
[228029] = {25, 20, 15, 30, 20, 15}, -- ExpelLight
}
--------------------------------------------------------------------------------
-- Localization
--
local L = mod:GetLocale()
if L then
L.odyn = -14003
L.odyn_icon = "inv_misc_horn_05" -- inv_misc_horn_05 = Item: Odyn's Horn
L.hymdall = -14005
L.hymdall_icon = "inv_helm_mail_vrykuldragonrider_b_01" -- 214382 / Follower: Hymdall
L.hyrja = -14006
L.hyrja_icon = "inv_shield_1h_hyrja_d_01"
L.say = {}
L.say[227490] = "{rt3} %s {rt3}" -- Boss_OdunRunes_Purple
L.say[227491] = "{rt2} %s {rt2}" -- Boss_OdunRunes_Orange
L.say[227498] = "{rt1} %s {rt1}" -- Boss_OdunRunes_Yellow
L.say[227499] = "{rt6} %s {rt6}" -- Boss_OdunRunes_Blue
L.say[227500] = "{rt4} %s {rt4}" -- Boss_OdunRunes_Green
L.yields = "%s yields" -- used when Hymdall and Helya leave the fight in P2: "Hymdall yields"
L[227490] = "|cFF800080Top Right|r (|T1323037:15:15:0:0:64:64:4:60:4:60|t)" -- Boss_OdunRunes_Purple
L[227491] = "|cFFFFA500Bottom Right|r (|T1323039:15:15:0:0:64:64:4:60:4:60|t)" -- Boss_OdunRunes_Orange
L[227498] = "|cFFFFFF00Bottom Left|r (|T1323038:15:15:0:0:64:64:4:60:4:60|t)" -- Boss_OdunRunes_Yellow
L[227499] = "|cFF0000FFTop Left|r (|T1323035:15:15:0:0:64:64:4:60:4:60|t)" -- Boss_OdunRunes_Blue
L[227500] = "|cFF008000Top|r (|T1323036:15:15:0:0:64:64:4:60:4:60|t)" -- Boss_OdunRunes_Green
end
--------------------------------------------------------------------------------
-- Initialization
--
function mod:GetOptions()
return {
--[[ General ]]--
"stages",
--[[ Stage One: Might of the Valarjar ]]--
228018, -- Valarjar's Bond
228171, -- Revivify
--[[ Hymdall ]]--
{228012, "PROXIMITY"}, -- Horn of Valor
--[[ Hyrja ]]--
{228029, "SAY", "ICON", "PROXIMITY"}, -- Expel Light
{228162, "SAY", "SAY_COUNTDOWN", "ICON"}, -- Shield of Light
--[[ Odyn ]]--
227503, -- Draw Power
227629, -- Unerring Blast
{227626, "TANK"}, -- Odyn's Test
{-14495, "INFOBOX", "SAY", "FLASH", "PULSE"}, -- Runic Brand
{229584, "EMPHASIZE"}, -- Protected
--[[ Stage Two: The Prime Designate ]]--
-14404, -- Test of the Ages
--[[ Stage Three: The Final Test ]]--
{228918, "SAY", "ICON"}, -- Stormforged Spear
{227807, "SAY", "FLASH"}, -- Storm of Justice
227475, -- Cleansing Flame
{197961, "PROXIMITY", "SAY", "FLASH", "PULSE"}, -- Runic Brand
231350, -- Radiant Smite
},{
["stages"] = "general",
[228018] = -14002, -- Stage One: Might of the Valarjar
[228012] = -14005, -- Hymdall
[228029] = -14006, -- Hyrja
[227503] = -14003, -- Odyn
[-14404] = -14010, -- Stage Two: The Prime Designate
[228918] = -14011, -- Stage Three: The Final Test
}
end
function mod:OnBossEnable()
self:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", nil, "boss1")
self:Log("SPELL_CAST_START", "UnerringBlast", 227629)
self:Log("SPELL_CAST_START", "ShieldOfLight", 228162)
self:Log("SPELL_CAST_SUCCESS", "ShieldOfLightSuccess", 228162)
self:Log("SPELL_CAST_START", "HornOfValor", 228012)
self:Log("SPELL_CAST_SUCCESS", "HornOfValorSuccess", 228012)
self:Log("SPELL_AURA_APPLIED", "StormOfJustice", 227807)
self:Log("SPELL_CAST_SUCCESS", "StormOfJusticeSuccess", 227807)
self:Log("SPELL_AURA_APPLIED_DOSE", "OdynsTest", 227626)
self:Log("SPELL_AURA_APPLIED", "StormforgedSpear", 228918)
self:Log("SPELL_AURA_APPLIED", "StormforgedSpearDebuff", 228932) -- Tank got hit
self:Log("SPELL_CAST_SUCCESS", "ExpelLightSuccess", 228028)
self:Log("SPELL_AURA_APPLIED", "ExpelLightApplied", 228029)
self:Log("SPELL_AURA_REMOVED", "ExpelLightRemoved", 228029)
self:Log("SPELL_CAST_START", "Revivify", 228171)
self:Log("SPELL_AURA_APPLIED", "BrandedFixate", 227490, 227491, 227498, 227499, 227500) -- Add Fixates
self:Log("SPELL_AURA_REMOVED", "BrandedFixateRemoved", 227490, 227491, 227498, 227499, 227500) -- Add Fixates
self:Log("SPELL_CAST_SUCCESS", "RunicShield", 227594, 227595, 227596, 227597, 227598) -- Add regains shield
self:Death("RunebearerDeath", 114996)
self:Log("SPELL_AURA_APPLIED", "Branded", 229579, 229580, 229581, 229582, 229583) -- Mythic Debuffs
self:Log("SPELL_AURA_APPLIED", "Protected", 229584) -- Mythic Debuffs
self:Log("SPELL_AURA_APPLIED", "RunicBrand", 231311, 231342, 231344, 231345, 231346) -- Mythic P3 Debuffs
self:Log("SPELL_AURA_REMOVED", "RunicBrandRemoved", 231311, 231342, 231344, 231345, 231346) -- Mythic P3 Debuffs
self:Log("SPELL_CAST_SUCCESS", "RadiantSmite", 231350)
self:Log("SPELL_AURA_APPLIED", "CleansingFlameDamage", 227475) -- different spellIds for aura and damage
self:Log("SPELL_DAMAGE", "CleansingFlameDamage", 228683) -- different spellIds for aura and damage
self:Log("SPELL_MISSED", "CleansingFlameDamage", 228683) -- different spellIds for aura and damage
end
function mod:OnEngage()
phase = 1
hornCount = 1
shieldCount = 1
expelCount = 1
spearCount = 1
stormCount = 1
runesUp = 0
myAddGUID = ""
addGUIDs = {}
isHymdallFighting = true
isHyrjaFighting = true
castingHorn = false
revivifyBarTexts = {}
addFixates = {}
proxLists = {
[231311] = {}, -- Boss_OdunRunes_Purple
[231342] = {}, -- Boss_OdunRunes_Orange
[231344] = {}, -- Boss_OdunRunes_Yellow
[231345] = {}, -- Boss_OdunRunes_Blue
[231346] = {}, -- Boss_OdunRunes_Green
}
self:RegisterUnitEvent("UNIT_AURA", nil, "boss1", "boss2", "boss3") -- Valarjar's Bond
self:Bar(228012, self:Easy() and 10 or 8, CL.count:format(self:SpellName(228012), hornCount)) -- Horn of Valor
self:Bar(228162, self:Easy() and 30 or self:Mythic() and 20 or 24, CL.count:format(self:SpellName(228162), shieldCount)) -- Shield of Light
self:Bar(228029, self:Easy() and 40 or self:Mythic() and 25 or 32) -- Expel Light
self:Bar(227503, self:Easy() and 45 or self:Mythic() and 35 or 40) -- Draw Power
self:Bar(227629, self:Easy() and 78 or self:Mythic() and 68 or 73) -- Unerring Blast
end
--------------------------------------------------------------------------------
-- Event Handlers
--
function mod:UNIT_SPELLCAST_SUCCEEDED(_, _, _, spellId)
if spellId == 229168 then -- Test for Players (Phase 1 end)
phase = 2
isHymdallFighting = false
isHyrjaFighting = false
self:UnregisterUnitEvent("UNIT_AURA", "boss1", "boss2", "boss3") -- Valarjar's Bond
self:MessageOld("stages", "cyan", "long", CL.stage:format(2), false)
for _,barText in pairs(revivifyBarTexts) do
self:StopBar(barText)
end
self:StopBar(CL.count:format(self:SpellName(228162), shieldCount)) -- Shield of Light
self:StopBar(228029) -- Expel Light
self:StopBar(CL.count:format(self:SpellName(228012), hornCount)) -- Horn of Valor
self:StopBar(227503) -- Draw Power
self:CDBar("stages", 8, self:SpellName(L.odyn), L.odyn_icon)
elseif spellId == 227882 then -- Leap into Battle (Phase 2 start)
if not self:Easy() then
self:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
self:Bar(-14404, 16, L.hyrja, L.hyrja_icon)
end
self:Bar(227503, self:Mythic() and 37.5 or 43) -- Draw Power
self:Bar(227629, self:Mythic() and 70 or 73) -- Unerring Blast
elseif spellId == 228740 then
phase = 3
self:MessageOld("stages", "cyan", "long", CL.stage:format(3), false)
self:StopBar(L.hyrja)
self:StopBar(L.hymdall)
self:StopBar(227503) -- Draw Power
self:StopBar(227629) -- Unerring Blast
self:Bar(227807, 4) -- Storm of Justice
self:Bar(228918, 9) -- Stormforged Spear
if self:Mythic() then
self:Bar(197961, 21) -- Runic Brand
end
elseif spellId == 229576 or spellId == 227503 then -- Draw Power, 229576 = mythic, 227503 = others
runesUp = (self:Easy() and phase == 1 and 3) or 5 -- could be :Normal(), not sure about LFR
self:MessageOld(227503, "yellow", "long")
elseif spellId == 231297 then -- Runic Brand P3, Mythic
self:Bar(231350, 7.5) -- Radiant Smite
end
end
function mod:INSTANCE_ENCOUNTER_ENGAGE_UNIT()
if phase ~= 2 then return end
local hymdallFound, hyrjaFound = nil, nil
for i = 1, 5 do
local unit = ("boss%d"):format(i)
local guid = self:UnitGUID(unit)
if guid then
local mobId = self:MobId(guid)
if mobId == 114361 then -- Hymdall
hymdallFound = true
if not isHymdallFighting then
isHymdallFighting = true
hornCount = 1
self:MessageOld(-14404, "cyan", "info", self:SpellName(L.hymdall), false)
self:CDBar(228012, 10) -- Horn of Valor
self:CDBar(-14404, self:Mythic() and 66 or 69.5, L.hyrja, L.hyrja_icon)
end
elseif mobId == 114360 then -- Hyrja
hyrjaFound = true
if not isHyrjaFighting then
isHyrjaFighting = true
shieldCount = 1
self:MessageOld(-14404, "cyan", "info", self:SpellName(L.hyrja), false)
self:CDBar(228029, 5) -- Expel Light
self:CDBar(228162, 9.5) -- Shield of Light
self:CDBar(-14404, self:Mythic() and 66 or 69.5, L.hymdall, L.hymdall_icon)
end
end
end
end
if not hymdallFound and isHymdallFighting then
isHymdallFighting = false
if castingHorn then
castingHorn = false
self:CloseProximity(228012) -- Horn of Valor
end
self:MessageOld(-14404, "green", "info", L.yields:format(self:SpellName(L.hymdall)), false)
self:StopBar(CL.count:format(self:SpellName(228012), hornCount)) -- Horn of Valor
end
if not hyrjaFound and isHyrjaFighting then
isHyrjaFighting = false
self:MessageOld(-14404, "green", "info", L.yields:format(self:SpellName(L.hyrja)), false)
self:StopBar(CL.count:format(self:SpellName(228162), shieldCount)) -- Shield of Light
self:StopBar(228029) -- Expel Light
end
end
do
local protected = mod:SpellName(229584)
function mod:UnerringBlast(args)
self:MessageOld(args.spellId, "orange", "alert", CL.casting:format(args.spellName))
self:CastBar(args.spellId, 3)
self:Bar(227503, self:Easy() and 45 or 35) -- Draw Power
self:Bar(args.spellId, self:Easy() and 78 or (self:Mythic() and (phase == 2 and 69 or 68)) or 73)
if self:Mythic() and not self:UnitDebuff("player", protected) then
self:MessageOld(229584, "blue", nil, CL.no:format(protected))
end
end
end
do
local function printTarget(self, player, guid)
local t = self:Easy() and 5 or 4
if self:Me(guid) then
self:Say(228162)
self:SayCountdown(228162, t)
end
self:PrimaryIcon(228162, player)
self:TargetMessageOld(228162, player, "red", "alarm", nil, nil, true)
self:TargetBar(228162, t, player)
end
function mod:ShieldOfLight(args)
self:GetBossTarget(printTarget, 0.4, args.sourceGUID)
shieldCount = shieldCount + 1
local t = 0
if self:Easy() then
t = 75
else
t = (self:Mythic() and (timers[args.spellId][shieldCount] or 20)) or phase == 2 and 25.5 or shieldCount % 2 == 0 and 32 or 38
end
self:Bar(args.spellId, t, CL.count:format(args.spellName, shieldCount))
end
function mod:ShieldOfLightSuccess(args)
self:PrimaryIcon(args.spellId)
end
end
function mod:HornOfValor(args)
castingHorn = true
self:MessageOld(args.spellId, "orange", "alert", CL.casting:format(args.spellName))
self:CastBar(args.spellId, self:Easy() and 5 or 4.5, CL.count:format(args.spellName, hornCount))
hornCount = hornCount + 1
local t = 0
if self:Easy() then
t = 75
else
t = (self:Mythic() and (timers[args.spellId][hornCount] or 20)) or hornCount % 2 == 0 and 27 or 43 -- TODO phase 2 CD
end
self:Bar(args.spellId, t, CL.count:format(args.spellName, hornCount))
self:OpenProximity(args.spellId, 5)
end
function mod:HornOfValorSuccess(args)
castingHorn = false
self:CloseProximity(args.spellId)
end
function mod:StormOfJustice(args)
if self:Me(args.destGUID) then
self:TargetMessageOld(args.spellId, args.destName, "blue", "alarm")
self:TargetBar(args.spellId, 5, args.destName)
self:Say(args.spellId)
self:Flash(args.spellId)
end
end
function mod:StormOfJusticeSuccess(args)
self:Bar(args.spellId, stormCount % 3 == 0 and 13.5 or 11)
stormCount = stormCount + 1
end
do
local prev = 0
function mod:UNIT_AURA(_, unit)
if self:UnitBuff(unit, self:SpellName(228018), 228018) and GetTime() - prev > 4 then -- We want this repeated
prev = GetTime()
self:MessageOld(228018, "red", "alarm") -- Valarjar's Bond
end
end
end
function mod:OdynsTest(args)
if args.amount % 3 == 0 then
-- This is the buff the boss gains if he is hitting the same tank. It's not really a stack message on the tank, but this is a clearer way of presenting it.
self:StackMessage(args.spellId, self:UnitName("boss1target"), args.amount, "yellow")
end
end
function mod:StormforgedSpear(args)
self:TargetMessageOld(args.spellId, args.destName, "red", "alarm")
self:TargetBar(args.spellId, 6, args.destName)
self:Bar(args.spellId, spearCount % 3 == 0 and 13.5 or 11)
self:PrimaryIcon(args.spellId, args.destName)
if self:Me(args.destGUID) then
self:Say(args.spellId)
end
spearCount = spearCount + 1
end
function mod:StormforgedSpearDebuff()
self:PrimaryIcon(228918)
end
function mod:ExpelLightSuccess()
expelCount = expelCount + 1
local t = 0
if self:Easy() then
t = expelCount % 2 == 0 and 20 or 55
else
t = (self:Mythic() and (timers[228029][expelCount] or 20)) or phase == 2 and 18 or expelCount % 2 == 0 and 32 or 38
end
self:Bar(228029, t)
end
do
function mod:ExpelLightApplied(args)
self:TargetMessageOld(args.spellId, args.destName, "red", "alarm")
self:PrimaryIcon(args.spellId, args.destName)
if self:Me(args.destGUID) then
self:Say(args.spellId)
self:OpenProximity(args.spellId, 8)
else
self:OpenProximity(args.spellId, 8, args.destName)
end
end
function mod:ExpelLightRemoved(args)
self:PrimaryIcon(args.spellId)
self:CloseProximity(args.spellId)
end
end
function mod:Revivify(args)
if castingHorn and self:MobId(args.sourceGUID) == 114361 then -- Hymdall
castingHorn = false
self:CloseProximity(228012) -- Horn of Valor
end
self:TargetMessageOld(args.spellId, args.sourceName, "green", "long")
local text = CL.other:format(args.sourceName, args.spellName)
revivifyBarTexts[#revivifyBarTexts+1] = text
self:Bar(args.spellId, self:Easy() and 15 or 10, text)
end
local function updateInfoBox()
local addsAlive = 0
for i,spellId in pairs({227490, 227491, 227498, 227499, 227500}) do
mod:SetInfo(-14495, i*2-1, L[spellId])
if addFixates[spellId] then
mod:SetInfo(-14495, i*2, addFixates[spellId])
addsAlive = addsAlive + 1
else
mod:SetInfo(-14495, i*2, "")
end
end
if addsAlive > 0 then
mod:OpenInfo(-14495, mod:SpellName(227490))
else
mod:CloseInfo(-14495)
end
end
function mod:BrandedFixate(args)
if self:Me(args.destGUID) then
self:MessageOld(-14495, "blue", "warning", L[args.spellId], args.spellId)
self:Flash(-14495, args.spellId)
self:Say(-14495, L.say[args.spellId]:format(args.spellName))
myAddGUID = args.sourceGUID
end
addFixates[args.spellId] = self:ColorName(args.destName)
addGUIDs[args.spellId] = args.sourceGUID
updateInfoBox()
end
function mod:BrandedFixateRemoved(args)
if self:Me(args.destGUID) then
myAddGUID = ""
end
addFixates[args.spellId] = nil
updateInfoBox()
end
function mod:RunicShield(args)
if args.sourceGUID == myAddGUID then
self:MessageOld(-14495, "blue", "warning", CL.on:format(args.spellName, args.sourceName), args.spellId)
end
end
do
local texTable = {
[227490] = "|T1323037:15:15:0:0:64:64:4:60:4:60|t", -- Boss_OdunRunes_Purple
[227491] = "|T1323039:15:15:0:0:64:64:4:60:4:60|t", -- Boss_OdunRunes_Orange
[227498] = "|T1323038:15:15:0:0:64:64:4:60:4:60|t", -- Boss_OdunRunes_Yellow
[227499] = "|T1323035:15:15:0:0:64:64:4:60:4:60|t", -- Boss_OdunRunes_Blue
[227500] = "|T1323036:15:15:0:0:64:64:4:60:4:60|t", -- Boss_OdunRunes_Green
}
function mod:RunebearerDeath(args)
local addsUp = ""
for spellId,tex in pairs(texTable) do
if addGUIDs[spellId] == args.destGUID then
addGUIDs[spellId] = nil
end
if addGUIDs[spellId] then
addsUp = addsUp .. tex
end
end
runesUp = runesUp - 1
self:ScheduleTimer("MessageOld", 0.3, 227503, "green", nil, CL.add_remaining:format(runesUp) .. addsUp)
end
end
do
local lookupTable = {
[229579] = 227490, -- Boss_OdunRunes_Purple
[229580] = 227491, -- Boss_OdunRunes_Orange
[229581] = 227498, -- Boss_OdunRunes_Yellow
[229582] = 227499, -- Boss_OdunRunes_Blue
[229583] = 227500, -- Boss_OdunRunes_Green
}
function mod:Branded(args)
if self:Me(args.destGUID) then
self:MessageOld(-14495, "blue", "warning", L[lookupTable[args.spellId]], lookupTable[args.spellId])
self:Flash(-14495, args.spellId)
end
end
end
function mod:Protected(args)
if self:Me(args.destGUID) then
self:MessageOld(args.spellId, "green", "info", CL.you:format(args.spellName))
end
end
do
local isOnMe = 0
local lookupTable = {
[231311] = 227490, -- Boss_OdunRunes_Purple
[231342] = 227491, -- Boss_OdunRunes_Orange
[231344] = 227498, -- Boss_OdunRunes_Yellow
[231345] = 227499, -- Boss_OdunRunes_Blue
[231346] = 227500, -- Boss_OdunRunes_Green
}
local function updateProximity(self)
local totalList = {} -- everyone who has another debuff
for spellId,table in pairs(proxLists) do
if isOnMe ~= spellId then
for _,player in pairs(table) do
totalList[#totalList+1] = player
end
end
end
if #totalList > 0 then
self:OpenProximity(197961, 15, totalList)
else
self:CloseProximity(197961)
end
end
local function wipeProxLists(self)
proxLists = {
[231311] = {}, -- Boss_OdunRunes_Purple
[231342] = {}, -- Boss_OdunRunes_Orange
[231344] = {}, -- Boss_OdunRunes_Yellow
[231345] = {}, -- Boss_OdunRunes_Blue
[231346] = {}, -- Boss_OdunRunes_Green
}
updateProximity(self)
end
function mod:RunicBrand(args)
if self:Me(args.destGUID) then
local tanslatedSpellId = lookupTable[args.spellId]
isOnMe = args.spellId
self:MessageOld(197961, "blue", "warning", CL.other:format(args.spellName, L[tanslatedSpellId]), args.spellId)
self:Flash(197961, args.spellId)
self:Say(197961, L.say[tanslatedSpellId]:format(args.spellName))
self:TargetBar(197961, 10, args.destName, nil, args.spellId)
end
proxLists[args.spellId][#proxLists[args.spellId]+1] = args.destName
updateProximity(self)
end
function mod:RunicBrandRemoved(args)
if self:Me(args.destGUID) then
isOnMe = 0
end
tDeleteItem(proxLists[args.spellId], args.destName)
updateProximity(self)
end
function mod:RadiantSmite(args)
self:MessageOld(args.spellId, "red", "long")
wipeProxLists(self)
self:Bar(197961, 28)
end
end
do
local prev = 0
function mod:CleansingFlameDamage(args)
local t = GetTime()
if self:Me(args.destGUID) and t-prev > 2 then
prev = t
self:MessageOld(227475, "blue", "alarm", CL.underyou:format(args.spellName))
end
end
end