View difference between Paste ID: D4u8a8WB and 1HbNqCtX
SHOW: | | - or go back to the newest paste.
1
local ADDON, private = ...
2
local f = CreateFrame("Frame", ADDON, InterfaceOptionsFramePanelContainer)
3
4
local db = { -- default values
5
	[2825]   = "RAID", -- Bloodlust
6
	[32182]  = "RAID", -- Heroism
7
	[80353]  = "RAID", -- Time Warp
8
	[13159]  = "RAID", -- Aspect of Fail
9
	[41450]  = "RAID", -- Blessing of Piss me off
10
	[73325]  = "RAID", -- Leap of Fail
11
	[34477]  = "RAID", -- MD
12
	[20736]  = "RAID", -- Distracting Shot
13
	[62124]  = "RAID", -- Reckoning * paladin
14
	[56222]  = "RAID", -- Dark Command
15
	[49576]  = "RAID", -- Death Grip
16
	[2649]   = "RAID", -- Generic hunter growl
17
	[39270]  = "RAID", -- main target growl
18
	[103128] = "RAID", -- suffering
19
}
20
21
local L = {
22
	ANNOUNCE_MESSAGE = "%1$s used %2$s!",
23
	SOMEONES_PET = "%s's pet",
24
25
	ADD_SPELL = "Add Spell",
26
	ADD_SPELL_DESC = "Use this dialog to add a new spell to be announced.",
27
	ADD_SPELL_HELP = "Enter the numeric ID of the spell you want to add. If you don't know the ID, look up the spell on Wowhead.com and copy the number out of the spell page URL.",
28
	ADD_SPELL_INVALID = "That is not a valid spell ID!",
29
	DELETE_SPELL = "Delete Spell",
30
	DELETE_SPELL_DESC = "Permanently remove this spell from this list. If you only want to disable it temporarily, change the channel to NONE instead.",
31
}
32
33
local ChannelNames = {
34
	NONE = NONE,
35
	SELF = PLAYER,
36
	SAY = CHAT_MSG_SAY,
37
	PARTY = CHAT_MSG_PARTY,
38
	RAID = CHAT_MSG_RAID,
39
}
40
41
local orderedChannels = { "NONE", "SELF", "SAY", "PARTY", "RAID" }
42
43
-------------------------------------------------------------------------
44
--	Event handling
45
46
f:RegisterEvent("PLAYER_LOGIN")
47
f:SetScript("OnEvent", function(self, event)
48
	NoTrollDB = NoTrollDB or db
49
	db = NoTrollDB
50
51
	for id in pairs(db) do
52
		if not GetSpellInfo(id) then
53
			print("Invalid spell in db:", id)
54
		end
55
	end
56
57
	self:UnregisterEvent("PLAYER_LOGIN")
58
	self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
59
60
	self:SetScript("OnEvent", function(self, event, unit, _, _, _, spellID)
61
		local channel = db[spellID]
62
		if channel and strmatch(unit, "%d") then -- ignore player, target, focus, etc.
63
			self:Announce(channel, spellID, unit)
64
		end
65
	end)
66
end)
67
68
-------------------------------------------------------------------------
69
--	Announce logic
70
71-
local lastText, lastTime = "", 0
71+
local last = {}
72
73
function f:Announce(channel, spellID, caster, target, isPet)
74
	if channel == "NONE" then return end
75
76-
		unit = gsub(unit, "pet", "player")
76+
77
		caster = gsub(caster, "pet", "player")
78
	end
79
80
	local guid, now = UnitGUID(caster), GetTime()
81
	if last[guid] and last[guid] < 1 then return end
82
	last[guid] = now
83
84
	local spellLink = GetSpellLink(spellID)
85
	local playerName = GetUnitName(unit, true)
86
87
	if channel == "SELF" then
88
		-- Clickable player links in self messages
89
		local playerLink = "|Hplayer:"..playerName.."|h["..playerName.."]|h"
90
		if isPet then
91
			playerLink = format(L.SOMEONES_PET, playerLink)
92
		end
93
		print("|cffffff9a[NoTroll]|r", format(L.ANNOUNCE_MESSAGE, playerLink, spellLink))
94-
		local now, message = GetTime(), format(L.ANNOUNCE_MESSAGE, playerName, spellLink)
94+
95-
		if message ~= lastText or now - lastTime > 5 then
95+
96-
			lastText, lastTime = message, now
96+
97-
			SendChatMessage(message, channel)
97+
98
		end
99
		SendChatMessage(format(L.ANNOUNCE_MESSAGE, playerName, spellLink), channel)
100
	end
101
end
102
103-
-- Make player names in channel messages from the addon clickable LOCALLY ONLY
103+
104
-- Make player names in channel messages from the addon
105
-- clickable in your local chat frame.
106
107-
function f:AddLocalMessageLinks(_, message, ...)
107+
108-
	local name = strmatch(message, ANNOUNCE_PATTERN)
108+
109-
	if name then
109+
function f.AddLocalMessageLinks(frame, event, message, ...)
110-
		local char = strmatch(playerName, "^[^%s%-]+")
110+
	local playerName = strmatch(message, ANNOUNCE_PATTERN)
111-
		local class = UnitClass(char)
111+
	if playerName then
112-
		local link = "|Hplayer:"..char.."|h["..name.."]|h"
112+
113-
		message = gsub(message, name, link)
113+
		message = gsub(message, playerName, playerLink)
114
		return false, message, ...
115
	end
116
end
117
118
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", f.AddLocalMessageLinks)
119
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID", f.AddLocalMessageLinks)
120
ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", f.AddLocalMessageLinks)
121
122
-------------------------------------------------------------------------
123
-- Options panel
124
125
f:Hide()
126
f:SetScript("OnShow", function(self)
127
	local RefreshOptions
128
129
	local title = self:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
130
	title:SetPoint("TOPLEFT", 16, -16)
131
	title:SetPoint("TOPRIGHT", -32, -16)
132
	title:SetJustifyH("LEFT")
133
	title:SetText(self.name)
134
	self.Title = Title
135
136
	local notes = self:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
137
	notes:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
138
	notes:SetPoint("TOPRIGHT", title, "BOTTOMRIGHT", 0, -8)
139
	notes:SetHeight(32)
140
	notes:SetJustifyH("LEFT")
141
	notes:SetJustifyV("TOP")
142
	notes:SetText(GetAddOnMetadata(ADDON, "Notes"))
143
	self.Notes = Notes
144
145
	local scrollFrame = CreateFrame("ScrollFrame", "$parentScrollFrame", self, "UIPanelScrollFrameTemplate")
146
	scrollFrame:SetPoint("TOPLEFT", notes, "BOTTOMLEFT", 0, -16)
147
	scrollFrame:SetPoint("BOTTOMRIGHT", -38, 16)
148
	self.ScrollFrame = scrollFrame
149
150
	scrollFrame.ScrollBar:EnableMouseWheel(true)
151
	scrollFrame.ScrollBar:SetScript("OnMouseWheel", function(self, delta)
152
		ScrollFrameTemplate_OnMouseWheel(scrollFrame, delta)
153
	end)
154
155
	local barBG = scrollFrame:CreateTexture(nil, "BACKGROUND", nil, -6)
156
	barBG:SetPoint("TOP")
157
	barBG:SetPoint("RIGHT", 25, 0)
158
	barBG:SetPoint("BOTTOM")
159
	barBG:SetWidth(26)
160
	barBG:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar")
161
	barBG:SetTexCoord(0, 0.45, 0.1640625, 1)
162
	barBG:SetAlpha(0.5)
163
	scrollFrame.ScrollBar.bg = barBG
164
165
	local scrollChild = CreateFrame("Frame", nil, scrollFrame)
166
	scrollChild:SetSize(scrollFrame:GetWidth(), 100)
167
	scrollFrame.ScrollChild = scrollChild
168
169
	scrollFrame:SetScrollChild(scrollChild)
170
	scrollFrame:SetScript("OnSizeChanged", function(self)
171
		scrollChild:SetWidth(self:GetWidth())
172
	end)
173
174
	--------------------------------------------------------------------
175
176
	local dialog = CreateFrame("Frame", nil, self)
177
	dialog:SetPoint("TOPLEFT", notes, "BOTTOMLEFT", 0, -16)
178
	dialog:SetPoint("BOTTOMRIGHT", -16, 16)
179
	dialog:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16 })
180
	dialog:SetBackdropBorderColor(1, 0.82, 0, 0.8)
181
	self.Dialog = dialog
182
183
	dialog.bg = dialog:CreateTexture(nil, "BACKGROUND")
184
	dialog.bg:SetPoint("BOTTOMLEFT", 3, 3)
185
	dialog.bg:SetPoint("TOPRIGHT", -3, -3)
186
	dialog.bg:SetTexture("Interface\\FrameGeneral\\UI-Background-Rock", true, true)
187
	dialog.bg:SetHorizTile(true)
188
	dialog.bg:SetVertTile(true)
189
	dialog.bg:SetVertexColor(0.4, 0.4, 0.4, 0.8)
190
191
	dialog:Hide()
192
	dialog:SetScript("OnShow", function(self)
193
		self:GetParent().ScrollFrame:Hide()
194
		self.EditBox:SetText("")
195
		self.Text:SetText("")
196
		self.EditBox:SetFocus()
197
	end)
198
	dialog:SetScript("OnHide", function(self)
199
		self:GetParent().ScrollFrame:Show()
200-
		self:GetParent().refresh()
200+
201
		self.Text:SetText("")
202
		RefreshOptions()
203
	end)
204
205
	local dialogTitle = dialog:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
206
	dialogTitle:SetPoint("TOPLEFT", 16, -16)
207
	dialogTitle:SetText(L.ADD_SPELL)
208
	dialog.Title = dialogTitle
209
210
	local dialogNotes = dialog:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
211
	dialogNotes:SetPoint("TOPLEFT", dialogTitle, "BOTTOMLEFT", 0, -8)
212
	dialogNotes:SetPoint("RIGHT", -32, 0)
213
	dialogNotes:SetHeight(16)
214
	dialogNotes:SetJustifyH("LEFT")
215
	dialogNotes:SetJustifyV("TOP")
216
	dialogNotes:SetText(L.ADD_SPELL_DESC)
217
218
	local dialogBox = CreateFrame("EditBox", "$parentEditBox", dialog, "InputBoxTemplate")
219
	dialogBox:SetPoint("TOPLEFT", dialogNotes, "BOTTOMLEFT", 6, -12)
220
	dialogBox:SetSize(160, 24)
221
	dialogBox:SetAltArrowKeyMode(false)
222
	dialogBox:SetAutoFocus(false)
223
	dialogBox:SetMaxLetters(6)
224
	dialogBox:SetNumeric(true)
225
	dialog.EditBox = dialogBox
226
227
	dialogBox:SetScript("OnTextChanged", function(self, userInput)
228
		if not userInput then return end
229
230
		local spell = self:GetNumber()
231
		if spell == 0 then
232
			dialog.Text:SetText("")
233
			dialog.Button:SetEnabled(false)
234
			return
235
		end
236
237
		local name, _, icon = GetSpellInfo(spell)
238
		if name and icon then
239
			dialog.Text:SetFormattedText("|T%s:0|t %s", icon, name)
240
			dialog.Button:SetEnabled(true)
241
		else
242
			dialog.Text:SetText(RED_FONT_COLOR_CODE .. L.ADD_SPELL_INVALID .. "|r")
243
			dialog.Button:Disable()
244
		end
245
	end)
246
247
	dialogBox:SetScript("OnEnterPressed", function(self)
248
		if not dialog.Button:IsEnabled() then return end
249
		local id = self:GetNumber()
250
		if id and id > 0 and GetSpellInfo(id) then
251
			db[id] = "RAID"
252
			dialog:Hide()
253
		end
254
	end)
255
256
	local dialogButton = CreateFrame("Button", "$parentAddButton", dialog, "UIPanelButtonTemplate")
257
	dialogButton:SetPoint("LEFT", dialogBox, "RIGHT", 12, 0)
258
	dialogButton:SetWidth(80)
259
	dialogButton:SetText(OKAY)
260
	dialogButton:SetScript("OnClick", function()
261
		dialogBox:GetScript("OnEnterPressed")(dialogBox)
262
	end)
263
	dialog.Button = dialogButton
264
265
	local dialogText = dialog:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
266
	dialogText:SetPoint("LEFT", dialogButton, "RIGHT", 12, 0)
267
	dialogText:SetPoint("RIGHT", dialog, -16, 0)
268
	dialogText:SetJustifyH("LEFT")
269
	dialogText:SetJustifyV("TOP")
270
	dialogText:SetText("")
271
	dialog.Text = dialogText
272
273
	local dialogHelp = dialog:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
274
	dialogHelp:SetPoint("TOPLEFT", dialogBox, "BOTTOMLEFT", -6, -16)
275
	dialogHelp:SetPoint("RIGHT", dialog, -16, 0)
276
	dialogHelp:SetHeight(32)
277
	dialogHelp:SetJustifyH("LEFT")
278
	dialogHelp:SetJustifyV("TOP")
279
	dialogHelp:SetNonSpaceWrap(true)
280
	dialogHelp:SetText(L.ADD_SPELL_HELP)
281
	dialog.HelpText = dialogHelp
282
283
	--------------------------------------------------------------------
284
285
	local add = CreateFrame("Button", "$parentPanelButton", self, "UIPanelButtonTemplate")
286
	add:SetPoint("TOPRIGHT", title, "BOTTOMRIGHT", 0, -8)
287
	add:SetSize(160, 32)
288
	add:SetText("|TInterface\\LFGFRAME\\LFGROLE_BW:0:0:0:0:64:16:48:64:0:16:255:255:153|t " .. L.ADD_SPELL)
289
	self.AddButton = add
290
291
	notes:SetPoint("TOPRIGHT", add, "TOPLEFT", -24, 0)
292
293
	add:SetScript("OnClick", function(self)
294
		if dialog:IsShown() then
295
			dialog:Hide()
296
			self:SetText("|TInterface\\LFGFRAME\\LFGROLE_BW:0:0:0:0:64:16:48:64:0:16:255:255:153|t " .. L.ADD_SPELL)
297
		else
298
			dialog:Show()
299
			self:SetText(CANCEL)
300
		end
301
	end)
302
303
	--------------------------------------------------------------------
304
305
	local function Row_OnEnter(self)
306
		self.name:SetTextColor(1, 1, 1)
307
		self.highlight:Show()
308
		GameTooltip:SetOwner(self, "ANCHOR_NONE")
309
		GameTooltip:SetPoint("TOPRIGHT", self, "TOPLEFT")
310
		GameTooltip:SetSpellByID(self.id)
311
		GameTooltip:Show()
312
	end
313
	local function Row_OnLeave(self)
314
		self.name:SetTextColor(1, 0.82, 0)
315
		self.highlight:Hide()
316
		GameTooltip:Hide()
317
	end
318
	local function Row_OnHide(self)
319
		self.id = 0
320
		self.icon:SetTexture(nil)
321
		self.name:SetText("")
322
		self.channel.valueText:SetText("")
323
	end
324
325
	-- Delete button functions:
326
	local function Delete_OnClick(self)
327
		if GameTooltip:IsOwned(self) then
328
			GameTooltip:Hide()
329
		end
330-
		self.refresh()
330+
331
		db[id] = nil
332
		RefreshOptions()
333
	end
334
	local function Delete_OnEnter(self)
335
		GameTooltip:SetOwner(self, "ANCHOR_LEFT")
336
		GameTooltip:SetText(L.DELETE_SPELL)
337
		GameTooltip:AddLine(L.DELETE_SPELL_DESC, 1, 1, 1, true)
338
		GameTooltip:Show()
339
	end
340
341
	-- Filter dropdown functions:
342
	local CURRENT_SPELL, CURRENT_DROPDOWN
343
	local function Dropdown_ClickFunc(info)
344
		db[CURRENT_SPELL] = info.value
345
		CURRENT_DROPDOWN:SetValue(info.value, ChannelNames[info.value])
346
	end
347
	local function Dropdown_Initialize(self, level) -- self is the dropdown menu
348
		if not level then return end
349
		CURRENT_DROPDOWN = self:GetParent()
350
		CURRENT_SPELL = CURRENT_DROPDOWN:GetParent().id
351
		local selected = db[CURRENT_SPELL]
352
		local info = UIDropDownMenu_CreateInfo()
353
		for i = 1, #orderedChannels do
354
			local k = orderedChannels[i]
355
			info.text = ChannelNames[k]
356
			info.value = k
357
			info.checked = k == selected
358
			info.func = Dropdown_ClickFunc
359
			UIDropDownMenu_AddButton(info, level)
360
		end
361
	end
362
	local function Dropdown_OnEnter(self)
363
		Row_OnEnter(self:GetParent())
364
	end
365
	local function Dropdown_OnLeave(self)
366
		Row_OnLeave(self:GetParent())
367
	end
368
369
	-- Rows:
370
	local rows = setmetatable({}, { __index = function(t, i)
371
		local row = CreateFrame("Frame", nil, scrollChild)
372
		row:SetHeight(40)
373
		row:SetPoint("LEFT")
374
		row:SetPoint("RIGHT")
375
		if i > 1 then
376
			row:SetPoint("TOP", t[i-1], "BOTTOM", 0, -4)
377
		else
378
			row:SetPoint("TOP")
379
		end
380
381
		row:EnableMouse(true)
382
		row:SetScript("OnEnter", Row_OnEnter)
383
		row:SetScript("OnLeave", Row_OnLeave)
384
385
		row:EnableMouseWheel(true)
386
		row:SetScript("OnMouseWheel", function(self, delta)
387
			ScrollFrameTemplate_OnMouseWheel(scrollFrame, delta)
388
		end)
389
390
		local highlight = row:CreateTexture(nil, "BACKGROUND")
391
		highlight:SetAllPoints(true)
392
		highlight:SetBlendMode("ADD")
393
		highlight:SetTexture([[Interface\QuestFrame\UI-QuestLogTitleHighlight]])
394
		highlight:SetVertexColor(0.2, 0.4, 0.8)
395
		highlight:Hide()
396
		row.highlight = highlight
397
398
		local delete = CreateFrame("Button", "$parentDelete"..i, row, "UIPanelCloseButton")
399
		delete:SetPoint("LEFT", -2, -1)
400
		delete:SetSize(32, 32)
401
		delete:SetScript("OnClick", Delete_OnClick)
402
		delete:SetScript("OnEnter", Delete_OnEnter)
403
		delete:SetScript("OnLeave", GameTooltip_Hide)
404
		row.delete = delete
405
406
		local icon = row:CreateTexture(nil, "ARTWORK")
407
		icon:SetPoint("LEFT", delete, "RIGHT", 2, 0)
408
		icon:SetSize(32, 32)
409
		icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
410
		row.icon = icon
411
412
		local name = row:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
413
		name:SetPoint("LEFT", icon, "RIGHT", 8, 0)
414
		row.name = name
415
416
		local channel = LibStub("PhanxConfig-Dropdown"):New(row, nil, nil, Dropdown_Initialize)
417
		channel:SetPoint("RIGHT", 0, 5)
418
		channel:SetWidth(200)
419
		channel.OnEnter = Dropdown_OnEnter
420
		channel.OnLeave = Dropdown_OnLeave
421
		row.channel = channel
422
423
		t[i] = row
424
		return row
425
	end })
426
	self.rows = rows
427
428
	--------------------------------------------------------------------
429
430
	-- OnShow for self:
431
	local pool = {}
432
	local sortedSpells = {}
433
	local sortFunc = function(a, b)
434-
	self.refresh = function()
434+
435
	end
436
437
	function RefreshOptions()
438
		for i = #sortedSpells, 1, -1 do
439
			pool[tremove(sortedSpells, i)] = true
440
		end
441
442
		for id, channel in pairs(db) do
443
			local name, _, icon = GetSpellInfo(id)
444
			if name and icon then
445
				local spell = next(pool) or {}
446
				pool[spell] = nil
447
				spell.name = name
448
				spell.icon = icon
449
				spell.id = id
450
				spell.channel = channel
451
				tinsert(sortedSpells, spell)
452
			end
453
		end
454
		sort(sortedSpells, sortFunc)
455
456
		if #sortedSpells > 0 then
457
			local height = 0
458
			for i = 1, #sortedSpells do
459
				local spell = sortedSpells[i]
460
				local row = rows[i]
461
				row.id = spell.id
462
				row.name:SetText(spell.name)
463
				row.icon:SetTexture(spell.icon)
464
				row.channel:SetValue(spell.channel, ChannelNames[spell.channel])
465
				row:Show()
466
				height = height + 4 + row:GetHeight()
467
			end
468
			for i = #sortedSpells + 1, #rows do
469
				rows[i]:Hide()
470
			end
471
			scrollChild:SetHeight(height)
472
			add:Show()
473
		else
474
			for i = 1, #rows do
475
				rows[i]:Hide()
476
			end
477
			scrollChild:SetHeight(100)
478
			dialog:Show()
479
			add:Hide()
480
		end
481-
	self.refresh()
481+
482
483
	self:SetScript("OnShow", nil)
484
	self.refresh = RefreshOptions
485
	RefreshOptions()
486
end)
487
488
f.name = GetAddOnMetadata(ADDON, "Title")
489
InterfaceOptions_AddCategory(f)
490
491
_G["SLASH_"..ADDON.."1"] = "/notroll"
492
SlashCmdList[ADDON] = function()
493
	InterfaceOptionsFrame_OpenToCategory(f)
494
	InterfaceOptionsFrame_OpenToCategory(f)
495
end