-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathQoL.lua
More file actions
385 lines (357 loc) · 16.4 KB
/
QoL.lua
File metadata and controls
385 lines (357 loc) · 16.4 KB
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
377
378
379
380
381
382
383
384
385
local _, NSI = ... -- Internal namespace
local f = CreateFrame("Frame")
f:SetScript("OnEvent", function(self, e, ...)
NSI:QoLEvents(e, ...)
end)
local GatewayIcon = "\124T"..C_Spell.GetSpellTexture(111771)..":12:12:0:0:64:64:4:60:4:60\124t"
local ResetBossIcon = "\124T"..C_Spell.GetSpellTexture(57724)..":12:12:0:0:64:64:4:60:4:60\124t"
local CrestIcon = "\124T"..C_CurrencyInfo.GetCurrencyInfo(3347).iconFileID..":12:12:0:0:64:64:4:60:4:60\124t"
local FeastIcon = "\124T"..C_Spell.GetSpellTexture(19705)..":12:12:0:0:64:64:4:60:4:60\124t"
local CauldronIcon = "\124T"..C_Spell.GetSpellTexture(448001)..":12:12:0:0:64:64:4:60:4:60\124t"
local SoulwellIcon = "\124T"..C_Spell.GetSpellTexture(6262)..":12:12:0:0:64:64:4:60:4:60\124t"
local RepairIcon = "\124T"..C_Spell.GetSpellTexture(126462)..":12:12:0:0:64:64:4:60:4:60\124t"
local TextDisplays = {
Gateway = GatewayIcon.."Gateway Useable"..GatewayIcon,
ResetBoss = ResetBossIcon.."Reset Boss"..ResetBossIcon,
LootBoss = CrestIcon.."Loot Boss"..CrestIcon,
SoulwellDropped = SoulwellIcon.."%s Dropped a Soulwell"..SoulwellIcon,
FeastDropped = FeastIcon.."%s Dropped a Feast"..FeastIcon,
RepairDropped = RepairIcon.."%s Dropped a Repair"..RepairIcon,
CauldronDropped = CauldronIcon.."%s Dropped a Cauldron"..CauldronIcon,
}
local ConsumableSpells = {
[1259657] = "FEAST", -- Quel'dorei Medley
[1278915] = "FEAST", -- Hearty Quel'dorei Medley
[1259658] = "FEAST", -- Harandar Celebration
[1278929] = "FEAST", -- Hearty Harandar Celebration
[1237104] = "FEAST", -- Blooming Feast
[1278909] = "FEAST", -- Hearty Blooming Feast
[1259659] = "FEAST", -- Silvermoon Parade
[1278895] = "FEAST", -- Hearty Silvermoon Parade
[1240267] = "CAULDRON", -- Voidlight Potion Cauldron
[1240195] = "CAULDRON", -- Voidlight of Sin'dorei Flasks
[29893] = "SOULWELL",
[199109] = "REPAIR", -- Auto-Hammer
[67826] = "REPAIR", -- Jeeves
}
local LustDebuffs = {
57723, -- Exhaustion
57724, -- Sated
80354, -- Time Warp
264689, -- Fatigued
390435, -- Exhaustion
}
function NSI:QoLEvents(e, ...)
if self.IsBuilding then return end
if e == "ACTIONBAR_UPDATE_USABLE" then -- only thing needed for Gateway
if NSRT.QoL.GatewayUseableDisplay and C_Item.IsUsableItem(188152) then
self.QoLTextDisplays.Gateway = {SettingsName = "GatewayUseableDisplay", text = TextDisplays.Gateway}
else
self.QoLTextDisplays.Gateway = nil
end
self:UpdateQoLTextDisplay()
elseif e == "ADDON_RESTRICTION_STATE_CHANGED" then
if C_ChatInfo.InChatMessagingLockdown() then
self:ToggleQoLEvent("UNIT_SPELLCAST_SUCCEEDED", false)
else
self:ToggleQoLEvent("UNIT_SPELLCAST_SUCCEEDED", true, "player")
end
if not NSRT.QoL.ResetBossDisplay then -- shouldn't be possible but another safety check
self.QoLTextDisplays.ResetBoss = nil
self:UpdateQoLTextDisplay()
self:ToggleQoLEvent("UNIT_AURA", false)
return
elseif self:Restricted() then
self.QoLTextDisplays.ResetBoss = nil
self:ToggleQoLEvent("UNIT_AURA", false)
else
local inRaid = self:DifficultyCheck(14)
if not inRaid then return end
self:ToggleQoLEvent("UNIT_AURA", inRaid, "player")
local debuffed = self:HasLustDebuff()
if debuffed then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
else
self.QoLTextDisplays.ResetBoss = nil
end
end
self:UpdateQoLTextDisplay()
elseif e == "PLAYER_REGEN_DISABLED" and NSRT.QoLResetBossDisplay then
self.QoLTextDisplays.ResetBoss = nil
self:UpdateQoLTextDisplay()
elseif e == "PLAYER_REGEN_ENABLED" and NSRT.QoLResetBossDisplay then
if self:HasLustDebuff() then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
else
self.QoLTextDisplays.ResetBoss = nil
end
self:UpdateQoLTextDisplay()
elseif e == "UNIT_AURA" then
if self:Restricted() then return end -- shouldn't happen because we unregister but just a safety check
local unit, updateInfo = ...
if NSRT.QoL.ResetBossDisplay and unit == "player" then
if updateInfo.isFullUpdate then
local debuff = self:HasLustDebuff()
if debuff then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
else
self.QoLTextDisplays.ResetBoss = nil
end
self:UpdateQoLTextDisplay()
elseif updateInfo.addedAuras then
for _, auraData in ipairs(updateInfo.addedAuras) do
for _, spellID in ipairs(LustDebuffs) do
-- idk how this can ever be secret because I'm checking that at the very start but it can
if (not issecretvalue(auraData.spellId)) and auraData.spellId == spellID then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
self:UpdateQoLTextDisplay()
return
end
end
end
elseif updateInfo.removedAuraInstanceIDs and self.QoLTextDisplays.ResetBoss then
if self:HasLustDebuff() then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
else
self.QoLTextDisplays.ResetBoss = nil
end
self:UpdateQoLTextDisplay()
end
end
elseif e == "PLAYER_ENTERING_WORLD" then
C_Timer.After(0.01, function()
if self:DifficultyCheck(14) and NSRT.QoL.ResetBossDisplay and not self:Restricted() then
if self:HasLustDebuff() then
self.QoLTextDisplays.ResetBoss = {SettingsName = "ResetBossDisplay", text = TextDisplays.ResetBoss}
self:UpdateQoLTextDisplay()
end
end
self:QoLOnZoneSwap()
end)
elseif e == "ENCOUNTER_END" and self:DifficultyCheck(14) then
if NSRT.QoL.LootBossReminder then
local success = select(5, ...)
if success == 1 then
self.QoLTextDisplays.LootBoss = {SettingsName = "LootBossReminder", text = TextDisplays.LootBoss}
self:UpdateQoLTextDisplay()
self.LootReminderTimer = C_Timer.NewTimer(40, function() -- backup hide in case something goes wrong
if self.QoLTextDisplays.LootBoss then
self.QoLTextDisplays.LootBoss = nil
self:UpdateQoLTextDisplay()
end
end)
end
end
elseif e == "ENCOUNTER_START" and self:DifficultyCheck(14) then
self.QoLTextDisplays = {}
self:UpdateQoLTextDisplay()
elseif self:DifficultyCheck(14) and (e == "LOOT_OPENED" or e == "CHAT_MSG_MONEY" or e == "ENCOUNTER_START") then
if NSRT.QoL.LootBossReminder and self.QoLTextDisplays.LootBoss then
self.QoLTextDisplays.LootBoss = nil
self:UpdateQoLTextDisplay()
end
elseif e == "MERCHANT_SHOW" and NSRT.QoL.AutoRepair then
RepairAllItems(CanGuildBankRepair())
elseif (e == "CHAT_MSG_WHISPER" or e == "CHAT_MSG_BN_WHISPER") and NSRT.QoL.AutoInvite then
local msg, playerName = ...
if issecretvalue(msg) or issecretvalue(playerName) then return end
if msg == "inv" or msg == "invite" then
if e == "CHAT_MSG_BN_WHISPER" then
local bnSenderID = select(13, ...)
for i = 1, BNGetNumFriends() do
local accountInfo = C_BattleNet.GetFriendAccountInfo(i)
if bnSenderID == accountInfo.bnetAccountID then
for j = 1, C_BattleNet.GetFriendNumGameAccounts(i) do
local gameInfo = C_BattleNet.GetFriendGameAccountInfo(i, j)
if gameInfo then
local char = gameInfo.characterName
local realm = gameInfo.realmName
if char and realm then
playerName = char.."-"..realm
break
end
end
end
break
end
end
end
-- unfortunately have to check guild roster because C_GuildInfo.MemberExistsByName is a security risk as it can't check the realm
for i=1, GetNumGuildMembers() do
local name = GetGuildRosterInfo(i)
if name == playerName then
C_PartyInfo.InviteUnit(playerName)
return
end
end
end
elseif e == "UNIT_SPELLCAST_SUCCEEDED" then
-- registered only for 'player' so we don't need a unitTarget check or a secret check
local spellId = select(3, ...)
if IsInGroup() and ConsumableSpells[spellId] then
self:Broadcast("QoL_Comms", "RAID", ConsumableSpells[spellId])
end
elseif e == "QoL_Comms" then
self:HandleQoLComm(...)
end
end
function NSI:InitQoL()
self.QoLTextDisplays = {}
-- stuff in here is ALWAYS enabled.
self:ToggleQoLEvent("PLAYER_ENTERING_WORLD", true)
self:ToggleQoLEvent("ENCOUNTER_START", true)
if NSRT.QoL.AutoRepair then self:ToggleQoLEvent("MERCHANT_SHOW", true) end
if NSRT.QoL.AutoInvite then
self:ToggleQoLEvent("CHAT_MSG_WHISPER", true)
self:ToggleQoLEvent("CHAT_MSG_BN_WHISPER", true)
end
end
function NSI:ToggleQoLEvent(event, enable, unit)
if self.IsBuilding then return end
if enable then
f:RegisterUnitEvent(event, unit)
else
f:UnregisterEvent(event)
end
end
function NSI:QoLOnZoneSwap() -- only register events while player is in raid
local InRaid = self:DifficultyCheck(14)
local InInstance = select(2, GetInstanceInfo()) == "party"
if NSRT.QoL.ResetBossDisplay then
self:ToggleQoLEvent("PLAYER_REGEN_ENABLED", true)
self:ToggleQoLEvent("PLAYER_REGEN_DISABLED", true)
if InRaid and not self:Restricted() then
self:ToggleQoLEvent("UNIT_AURA", true, "player")
else
self:ToggleQoLEvent("UNIT_AURA", false)
end
end
if NSRT.QoL.LootBossReminder then -- Loot Reminder is active in raid and any non-m+ dungeon
self:ToggleQoLEvent("ENCOUNTER_END", InRaid)
self:ToggleQoLEvent("LOOT_OPENED", InRaid)
self:ToggleQoLEvent("CHAT_MSG_MONEY", InRaid)
self:ToggleQoLEvent("ENCOUNTER_START", InRaid)
end
if NSRT.QoL.GatewayUseableDisplay then self:ToggleQoLEvent("ACTIONBAR_UPDATE_USABLE", InRaid or InInstance) end
-- always keeping these enabled when in a raid or instance as they are required for addon comms to work and addon restriction is used for multiple checks.
self:ToggleQoLEvent("UNIT_SPELLCAST_SUCCEEDED", InRaid or InInstance, "player")
self:ToggleQoLEvent("ADDON_RESTRICTION_STATE_CHANGED", InRaid or InInstance)
if (not InRaid) and (not InInstance) then -- if zoning outside of raid&dungeon -> remove all displays
self.QoLTextDisplays = {}
self:UpdateQoLTextDisplay()
end
end
function NSI:HasLustDebuff()
for _, spellID in ipairs(LustDebuffs) do
local debuff = self:UnitAura("player", spellID)
if (not issecretvalue(debuff)) and debuff then
return true
end
end
return false
end
local VantusIds = {
}
function NSI:VantusRuneCheck()
if self:Restricted() then print("Auras are currently secret so this is unvailable.") return end
if not UnitInRaid("player") then return end
local name = C_Spell.GetSpellInfo(1276691).name
local prefix = name:match("^([^:]+)") -- get localized name of vantus runes
if issecretvalue(prefix) then return end
local maxgroup = self:DifficultyCheck(16) and 4 or 6 -- if outside raidlead checks this always goes to 6 but guess that'S fine
local text = ""
for i=1, 40 do
local name, _, subgroup = GetRaidRosterInfo(i)
if name and subgroup and subgroup <= maxgroup then
local index = UnitInRaid(name)
local unitid = index and "raid"..index
if unitid then
local found = false
for j=1, 100 do
local buff = C_UnitAuras.GetAuraDataByIndex(unitid, j, "HELPFUL")
if not buff then break end
if (not issecretvalue(buff.name)) and buff.name:find(prefix) then
found = true
break
end
end
if not found then
if text == "" then text = name else text = text..", "..name end
end
end
end
end
if text ~= "" then
text = "Missing Vantus Runes: "..text
print(text)
else
print("Everyone has a Vantus Rune!")
end
end
function NSI:HandleQoLComm(unitName, type)
-- We can get addon comms from anywhere, but only show notifs from players we can actually see.
if C_InstanceEncounter.IsEncounterInProgress() then return end -- don't popup anything while in boss combat
if not UnitIsVisible(unitName) then
return
end
if UnitIsUnit(unitName, "player") then
return
end
local displayTimerSeconds = NSRT.QoL.ConsumableNotificationDurationSeconds or 5
local displayName = NSAPI:Shorten(unitName, 8, false, "GlobalNickNames")
if type == "FEAST" then
-- can't check buff duration/presence in combat
if self:Restricted() then
return
end
local wellFedBuff = self:UnitAura("player", "Well Fed")
local okayBuffDurationSeconds = 10 * 60
if wellFedBuff and wellFedBuff.expirationTime and (wellFedBuff.expirationTime - GetTime() > okayBuffDurationSeconds) then
return
end
self.QoLTextDisplays.FeastDropped = {SettingsName = "FeastDropped", text = string.format(TextDisplays.FeastDropped, displayName)}
self:UpdateQoLTextDisplay()
C_Timer.After(displayTimerSeconds, function()
self.QoLTextDisplays.FeastDropped = nil
self:UpdateQoLTextDisplay()
end)
elseif type == "CAULDRON" then
-- TODO: check flask buff duration and number of potions in inventory?
self.QoLTextDisplays.CauldronDropped = {SettingsName = "CauldronDropped", text = string.format(TextDisplays.CauldronDropped, displayName)}
self:UpdateQoLTextDisplay()
C_Timer.After(displayTimerSeconds, function()
self.QoLTextDisplays.CauldronDropped = nil
self:UpdateQoLTextDisplay()
end)
elseif type == "SOULWELL" then
local healthstoneCharges = C_Item.GetItemCount(5512, false, true)
if healthstoneCharges == 3 then
return
end
self.QoLTextDisplays.SoulwellDropped = {SettingsName = "SoulwellDropped", text = string.format(TextDisplays.SoulwellDropped, displayName)}
self:UpdateQoLTextDisplay()
C_Timer.After(displayTimerSeconds, function()
self.QoLTextDisplays.SoulwellDropped = nil
self:UpdateQoLTextDisplay()
end)
elseif type == "REPAIR" then
-- no repair notifications above this threshold
local durabilityCutoff = 0.9
local minDurability = 1
for i=1, 18 do
local currentDurability, maxDurability = GetInventoryItemDurability(i)
if currentDurability ~= nil then
minDurability = min(minDurability, currentDurability / maxDurability)
end
end
if minDurability >= durabilityCutoff then
return
end
self.QoLTextDisplays.RepairDropped = {SettingsName = "RepairDropped", text = string.format(TextDisplays.RepairDropped, displayName)}
self:UpdateQoLTextDisplay()
C_Timer.After(displayTimerSeconds, function()
self.QoLTextDisplays.RepairDropped = nil
self:UpdateQoLTextDisplay()
end)
end
end