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