1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
local _;
local select = select;
local type = type;
local UnitGetTotalAbsorbs = VUHDO_unitGetTotalAbsorbs;
local VUHDO_SHIELDS = {
[17] = 15, -- VUHDO_SPELL_ID.POWERWORD_SHIELD -- ok
[123258] = 15, -- Power Word: Shield (Improved)
[11426] = 60, -- VUHDO_SPELL_ID.ICE_BARRIER -- ok
[116849] = 12, -- Life Cocoon
--[77535] = 10, -- Blood Shield (Blood DK) - Physical damage ONLY
[108416] = 20, -- Sacrificial Pact (warlock talent)
[1463] = 8, -- Incanter's Ward (mage talent)
[114893] = 10, -- Stone Bulwark Totem (shaman talent)
[187805] = 15, -- VUHDO_SPELL_ID.BUFF_ETHERALUS
[114908] = 10, -- VUHDO_SPELL_ID.SPIRIT_SHELL
}
--
local VUHDO_PUMP_SHIELDS = {
}
-- HoTs which we want to explicitly update on SPELL_AURA_APPLIED
-- This avoids any display delays on contingent auras (eg. Atonement)
local VUHDO_IMMEDIATE_HOTS = {
[VUHDO_SPELL_ID.ATONEMENT] = true,
}
local VUHDO_ABSORB_DEBUFFS = {
[109379] = function(aUnit) return 200000, 5 * 60; end, -- Searing Plasma
[105479] = function(aUnit) return 200000, 5 * 60; end,
[110214] = function(aUnit) return 280000, 2 * 60; end, -- Consuming Shroud
-- Patch 6.2 - Hellfire Citadel
[189030] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_BEFOULED)), 10 * 60; end, -- Fel Lord Zakuun
[189031] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_BEFOULED)), 10 * 60; end, -- Fel Lord Zakuun
[189032] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_BEFOULED)), 10 * 60; end, -- Fel Lord Zakuun
[180164] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TOUCH_OF_HARM)), 10 * 60; end, -- Tyrant Velhari
[180166] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TOUCH_OF_HARM)), 10 * 60; end, -- Tyrant Velhari
-- Patch 7.0 - Legion
[221772] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_OVERFLOW)), 1 * 60; end, -- Mythic+ affix
-- Patch 7.1 - Legion - Trial of Valor
[228253] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_SHADOW_LICK)), 10 * 60; end, -- Shadow Lick
[232450] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_CORRUPTED_AXION)), 30; end, -- Corrupted Axion
-- Patch 7.1.5 - Legion - Nighthold
[206609] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TIME_RELEASE)), 30; end, -- Chronomatic Anomaly Time Release
[219964] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TIME_RELEASE)), 30; end, -- Chronomatic Anomaly Time Release Geen
[219965] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TIME_RELEASE)), 30; end, -- Chronomatic Anomaly Time Release Yellow
[219966] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_TIME_RELEASE)), 30; end, -- Chronomatic Anomaly Time Release Red
-- Patch 7.2.5 - Legion - Tomb of Sargeras
[233263] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_EMBRACE_OF_THE_ECLIPSE)), 12; end, -- Sisters Embrace of the Eclipse
-- Patch 7.3 - Legion - Antorus, The Burning Throne
[245586] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_CHILLED_BLOOD)), 10; end, -- Coven Chilled Blood
-- Patch 8.0 - Battle for Azeroth - Uldir
[265206] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_IMMUNOSUPPRESSION)), 10 * 60; end, -- Vectis Immunosuppression
-- Patch 8.0 - Battle for Azeroth - The Underrot
[278961] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_DECAYING_MIND)), 30; end, -- Diseased Lasher Decaying Mind
-- Patch 8.1.5 - Battle for Azeroth - Crucible of Storms
[284722] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_UMBRAL_SHELL)), 10 * 60; end, -- Uu'nat Umbral Shell
[286771] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_UMBRAL_SHELL)), 10 * 60; end, -- Uu'nat Umbral Shell
-- Patch 8.3.0 - Battle for Azeroth - Ny'alotha
[306184] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_UNLEASHED_VOID)), 40; end, -- Unleashed Void
-- Patch 9.0.2 - Shadowlands - Castle Nathria
[338600] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_CLOAK_OF_FLAMES)), 10 * 60; end, -- Cloak of Flames
[343026] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_CLOAK_OF_FLAMES)), 10 * 60; end, -- Cloak of Flames
[337859] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_CLOAK_OF_FLAMES)), 10 * 60; end, -- Cloak of Flames
-- Patch 9.0.2 - Shadowlands - Necrotic Wake
[320462] = function(aUnit) return select(17, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_NECROTIC_BOLT)), 1 * 60; end, -- Necrotic Bolt
[320170] = function(aUnit) return select(17, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_NECROTIC_BOLT)), 2 * 60; end, -- Necrotic Bolt
-- Patch 9.0.2 - Shadowlands - Theater of Pain
[330784] = function(aUnit) return select(17, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_NECROTIC_BOLT)), 1 * 60; end, -- Necrotic Bolt
[330868] = function(aUnit) return select(17, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_NECROTIC_BOLT_VOLLEY)), 1 * 60; end, -- Necrotic Bolt Volley
-- Patch 9.0.2 - Death Knight ability
[223929] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_NECROTIC_WOUND)), 18; end, -- Necrotic Wound
-- Patch 9.1.0 - Shadowlands - Sanctum of Domination
-- neither of these Sanctum debuff absorbs tracked the usual way (missing SPELL_HEAL etc. events w/ absorb amount), disable for now
--[347704] = function(aUnit) return select(17, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_VEIL_OF_DARKNESS)), 10 * 60; end, -- Sylvanas Veil of Darkness
--[351091] = function(aUnit) return select(16, VUHDO_unitDebuff(aUnit, VUHDO_SPELL_ID.DEBUFF_DESTABILIZE)), 6; end, -- Mawsworn Hopebreaker Destabilize
--[79105] = function(aUnit) return 280000, 60 * 60; end, -- @TESTING PW:F
};
local sMissedEvents = {
["SWING_MISSED"] = true,
["RANGE_MISSED"] = true,
["SPELL_MISSED"] = true,
["SPELL_PERIODIC_MISSED"] = true,
["ENVIRONMENTAL_MISSED"] = true
};
local VUHDO_SHIELD_LEFT = { };
setmetatable(VUHDO_SHIELD_LEFT, VUHDO_META_NEW_ARRAY);
local VUHDO_SHIELD_SIZE = { };
setmetatable(VUHDO_SHIELD_SIZE, VUHDO_META_NEW_ARRAY);
local VUHDO_SHIELD_EXPIRY = { };
setmetatable(VUHDO_SHIELD_EXPIRY, VUHDO_META_NEW_ARRAY);
local VUHDO_SHIELD_LAST_SOURCE_GUID = { };
setmetatable(VUHDO_SHIELD_LAST_SOURCE_GUID, VUHDO_META_NEW_ARRAY);
local VUHDO_PLAYER_SHIELDS = { };
--
local pairs = pairs;
local ceil = ceil;
local floor = floor;
local GetTime = GetTime;
local select = select;
local GetSpellInfo = GetSpellInfo;
--
local VUHDO_PLAYER_GUID = -1;
local sIsPumpAegis = false;
local sShowAbsorb = false;
function VUHDO_shieldAbsorbInitLocalOverrides()
VUHDO_PLAYER_GUID = UnitGUID("player");
sShowAbsorb = VUHDO_PANEL_SETUP["BAR_COLORS"]["HOTS"]["showShieldAbsorb"];
sIsPumpAegis = VUHDO_PANEL_SETUP["BAR_COLORS"]["HOTS"]["isPumpDivineAegis"];
end
--
local function VUHDO_initShieldValue(aUnit, aShieldName, anAmount, aDuration)
if (anAmount or 0) == 0 then
--VUHDO_xMsg("ERROR: Failed to init shield " .. aShieldName .. " on " .. aUnit, anAmount);
return;
end
VUHDO_SHIELD_LEFT[aUnit][aShieldName] = anAmount;
if sIsPumpAegis and VUHDO_PUMP_SHIELDS[aShieldName] then
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = VUHDO_RAID["player"]["healthmax"] * VUHDO_PUMP_SHIELDS[aShieldName];
elseif aShieldName == VUHDO_SPELL_ID.SPIRIT_SHELL then
-- as of 9.0.5 Priest 'Spirit Shell' cap is 11 times the caster's current intellect
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = select(1, UnitStat("player", 4)) * 11;
else
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = anAmount;
end
VUHDO_SHIELD_EXPIRY[aUnit][aShieldName] = GetTime() + aDuration;
--VUHDO_xMsg("Init shield " .. aShieldName .. " on " .. aUnit .. " for " .. anAmount .. " / " .. VUHDO_SHIELD_SIZE[aUnit][aShieldName], aDuration);
end
--
local function VUHDO_updateShieldValue(aUnit, aShieldName, anAmount, aDuration, aExpirationTime)
if not VUHDO_SHIELD_SIZE[aUnit][aShieldName] then
--VUHDO_xMsg("ERROR: Failed to update shield " .. aShieldName .. " on " .. aUnit);
return;
end
if (anAmount or 0) == 0 then
--VUHDO_xMsg("ERROR: Failed to update shield " .. aShieldName .. " on " .. aUnit, anAmount);
return;
end
if aDuration then
VUHDO_SHIELD_EXPIRY[aUnit][aShieldName] = GetTime() + aDuration;
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = anAmount;
--VUHDO_xMsg("Shield overwritten");
elseif (aExpirationTime or 0) > VUHDO_SHIELD_EXPIRY[aUnit][aShieldName] then
VUHDO_SHIELD_EXPIRY[aUnit][aShieldName] = aExpirationTime;
elseif VUHDO_SHIELD_SIZE[aUnit][aShieldName] < anAmount then
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = anAmount;
end
VUHDO_SHIELD_LEFT[aUnit][aShieldName] = anAmount;
--VUHDO_xMsg("Updated shield " .. aShieldName .. " on " .. aUnit .. " to " .. anAmount, aDuration);
end
--
local function VUHDO_removeShield(aUnit, aShieldName)
if not VUHDO_SHIELD_SIZE[aUnit][aShieldName] then return; end
VUHDO_SHIELD_SIZE[aUnit][aShieldName] = nil;
VUHDO_SHIELD_LEFT[aUnit][aShieldName] = nil;
VUHDO_SHIELD_EXPIRY[aUnit][aShieldName] = nil;
VUHDO_SHIELD_LAST_SOURCE_GUID[aUnit][aShieldName] = nil;
--VUHDO_xMsg("Removed shield " .. aShieldName .. " from " .. aUnit);
end
--
local tNow;
function VUHDO_removeObsoleteShields()
tNow = GetTime();
for tUnit, tAllShields in pairs(VUHDO_SHIELD_EXPIRY) do
for tShieldName, tExpiry in pairs(tAllShields) do
if tExpiry < tNow then
VUHDO_removeShield(tUnit, tShieldName);
end
end
end
end
--
local tInit, tValue, tSourceGuid;
function VUHDO_getShieldLeftCount(aUnit, aShield, aMode)
tInit = sShowAbsorb and VUHDO_SHIELD_SIZE[aUnit][aShield] or 0;
if tInit > 0 then
tSourceGuid = VUHDO_SHIELD_LAST_SOURCE_GUID[aUnit][aShield];
if aMode == 3 or aMode == 0
or (aMode == 1 and tSourceGuid == VUHDO_PLAYER_GUID)
or (aMode == 2 and tSourceGuid ~= VUHDO_PLAYER_GUID) then
tValue = floor(4 * (VUHDO_SHIELD_LEFT[aUnit][aShield] or 0) / tInit);
return tValue > 4 and 4 or (tValue < 1 and 1 or tValue);
end
end
return 0;
end
--
local tExpirationTime;
local tRemain;
local tSpellName;
function VUHDO_updateShield(aUnit, aSpellId)
tSpellName, _, _, _, _, tExpirationTime, _, _, _, _, _, _, _, _, _, tRemain = VUHDO_unitBuff(aUnit, aSpellId);
if tRemain and "number" == type(tRemain) then
if tRemain > 0 then
VUHDO_updateShieldValue(aUnit, tSpellName, tRemain, nil, tExpirationTime);
else
VUHDO_removeShield(aUnit, tSpellName);
end
end
end
--
local function VUHDO_updateShields(aUnit)
for tSpellId, _ in pairs(VUHDO_SHIELDS) do
VUHDO_updateShield(aUnit, tSpellId);
end
end
--
local function VUHDO_getShieldLeftAmount(aUnit, aShieldName)
return VUHDO_SHIELD_LEFT[aUnit][aShieldName] or 0;
end
--
local tInit, tValue;
function VUHDO_getShieldPerc(aUnit, aShield)
tInit = VUHDO_SHIELD_SIZE[aUnit][aShield] or 0;
if tInit > 0 then
tValue = ceil(100 * (VUHDO_SHIELD_LEFT[aUnit][aShield] or 0) / tInit);
return tValue > 100 and 100 or tValue;
else
return 0;
end
end
--
function VUHDO_getUnitOverallShieldRemain(aUnit)
return UnitGetTotalAbsorbs(aUnit) or 0;
end
--
local tUnit;
local VUHDO_DEBUFF_SHIELDS = { };
local tDelta, tShieldName;
function VUHDO_parseCombatLogShieldAbsorb(aMessage, aSrcGuid, aDstGuid, aShieldName, anAmount, aSpellId, anAbsorbAmount)
tUnit = VUHDO_RAID_GUIDS[aDstGuid];
if not tUnit then return; end
if sMissedEvents[aMessage] then
VUHDO_updateShields(tUnit);
return;
end
--VUHDO_Msg(aSpellId);
--[[if ("SPELL_AURA_APPLIED" == aMessage) then
VUHDO_xMsg(aShieldName, aSpellId);
end]]
if VUHDO_SHIELDS[aSpellId] then
if "SPELL_AURA_REFRESH" == aMessage then
VUHDO_updateShieldValue(tUnit, aShieldName, anAmount, VUHDO_SHIELDS[aSpellId]);
elseif "SPELL_AURA_APPLIED" == aMessage then
VUHDO_initShieldValue(tUnit, aShieldName, anAmount, VUHDO_SHIELDS[aSpellId]);
VUHDO_SHIELD_LAST_SOURCE_GUID[tUnit][aShieldName] = aSrcGuid;
elseif "SPELL_AURA_REMOVED" == aMessage
or "SPELL_AURA_BROKEN" == aMessage
or "SPELL_AURA_BROKEN_SPELL" == aMessage then
VUHDO_removeShield(tUnit, aShieldName);
end
elseif VUHDO_ABSORB_DEBUFFS[aSpellId] then
if "SPELL_AURA_REFRESH" == aMessage then
VUHDO_updateShieldValue(tUnit, aShieldName, VUHDO_ABSORB_DEBUFFS[aSpellId](tUnit));
elseif "SPELL_AURA_APPLIED" == aMessage then
VUHDO_initShieldValue(tUnit, aShieldName, VUHDO_ABSORB_DEBUFFS[aSpellId](tUnit));
VUHDO_DEBUFF_SHIELDS[tUnit] = aShieldName;
elseif "SPELL_AURA_REMOVED" == aMessage
or "SPELL_AURA_BROKEN" == aMessage
or "SPELL_AURA_BROKEN_SPELL" == aMessage then
VUHDO_removeShield(tUnit, aShieldName);
VUHDO_DEBUFF_SHIELDS[tUnit] = nil;
end
elseif ("SPELL_HEAL" == aMessage or "SPELL_PERIODIC_HEAL" == aMessage)
and VUHDO_DEBUFF_SHIELDS[tUnit]
and (tonumber(anAbsorbAmount) or 0) > 0 then
tShieldName = VUHDO_DEBUFF_SHIELDS[tUnit];
tDelta = VUHDO_getShieldLeftAmount(tUnit, tShieldName) - anAbsorbAmount;
VUHDO_updateShieldValue(tUnit, tShieldName, tDelta);
elseif "UNIT_DIED" == aMessage then
VUHDO_SHIELD_SIZE[tUnit] = nil;
VUHDO_SHIELD_LEFT[tUnit] = nil;
VUHDO_SHIELD_EXPIRY[tUnit] = nil;
VUHDO_DEBUFF_SHIELDS[tUnit] = nil;
VUHDO_SHIELD_LAST_SOURCE_GUID[tUnit] = nil;
elseif VUHDO_IMMEDIATE_HOTS[aShieldName] and VUHDO_ACTIVE_HOTS[aShieldName] and
("SPELL_AURA_APPLIED" == aMessage or "SPELL_AURA_REMOVED" == aMessage or
"SPELL_AURA_REFRESH" == aMessage or "SPELL_AURA_BROKEN" == aMessage or
"SPELL_AURA_BROKEN_SPELL" == aMessage) then
VUHDO_updateAllHoTs();
VUHDO_updateAllCyclicBouquets(true);
end
VUHDO_updateBouquetsForEvent(tUnit, 36); -- VUHDO_UPDATE_SHIELD
VUHDO_updateShieldBar(tUnit);
VUHDO_updateHealAbsorbBar(tUnit);
end