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.

845 lines
25 KiB

---------------------------------------------------------------------------------
--
-- Prat - A framework for World of Warcraft chat modification
-- and a collection of modules which utilize the framework
--
-- Copyright (C) 2006-2020 Prat Development Team
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to:
--
-- Free Software Foundation, Inc.,
-- 51 Franklin Street, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--
-------------------------------------------------------------------------------
Prat = select(2, ...)
--[[ BEGIN STANDARD HEADER ]] --
-- Imports
local _G = _G
local LibStub = LibStub
local tonumber = tonumber
local tostring = tostring
local pairs = pairs
local ipairs = ipairs
local type = type
local select = select
local tinsert = tinsert
local Prat = Prat
local setmetatable, getmetatable = setmetatable, getmetatable
local strfind = strfind
local IsSecureCmd = IsSecureCmd
local wipe = table.wipe
local print = print
--[[ END STANDARD HEADER ]] --
--NEW_CHATFILTERS = select(4, _G.GetBuildInfo()) >= 30100
--CHAT_PLAYER_GUIDS = select(4, _G.GetBuildInfo()) >= 30200
--MOP = select(4, _G.GetBuildInfo()) >= 50000
Prat.BN_CHAT = true --(_G.GetBuildInfo() == "3.3.5") or (_G.GetBuildInfo() == "0.3.5")
-- Debug
--PrintMainChunkUse=true
--ChunkSizes = {}
--[==[@debug@
Prat.Version = "Prat |cff8080ff3.0|r (|cff8080ff" .. "DEBUG" .. "|r)"
--@end-debug@]==]
--@non-debug@
Prat.Version = "Prat |cff8080ff3.0|r (|cff8080ff".."3.9.55".."|r)"
--@end-non-debug@
local am = {}
local om = getmetatable(Prat)
if om then
for k, v in pairs(om) do am[k] = v end
end
am.__tostring = function() return "Prat |cff8080ff3.0|r" end
setmetatable(Prat, am)
Prat.Prat3 = true
Prat.IsClassic = (_G.WOW_PROJECT_ID ~= _G.WOW_PROJECT_MAINLINE)
Prat.IsRetail = (_G.WOW_PROJECT_ID == _G.WOW_PROJECT_MAINLINE)
local function dbg(...) end
--[==[@debug@
local function dbg(...) Prat:PrintLiteral(...) end
--@end-debug@]==]
Prat.Localizations = Prat.GetLocalizer({})
local L = Prat.Localizations
Prat.Frames = {
["ChatFrame1"] = _G.ChatFrame1,
["ChatFrame2"] = _G.ChatFrame2,
["ChatFrame3"] = _G.ChatFrame3,
["ChatFrame4"] = _G.ChatFrame4,
["ChatFrame5"] = _G.ChatFrame5,
["ChatFrame6"] = _G.ChatFrame6,
["ChatFrame7"] = _G.ChatFrame7,
["ChatFrame8"] = _G.ChatFrame8,
["ChatFrame9"] = _G.ChatFrame9,
["ChatFrame10"] = _G.ChatFrame10
}
Prat.HookedFrames = {}
Prat.ExternalFrames = {}
local builtinSounds = {
["Bell"] = "Interface\\AddOns\\Prat-3.0\\sounds\\Bell.ogg",
["Chime"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Chime.ogg",
["Heart"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Heart.ogg",
["IM"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\IM.ogg",
["Info"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Info.ogg",
["Kachink"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Kachink.ogg",
["popup"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Link.ogg",
["Text1"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Text1.ogg",
["Text2"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Text2.ogg",
["Xylo"] = "Interface\\AddOns\\Prat-3.0\\Sounds\\Xylo.ogg",
}
-- Symbolic names for all the events which Prat uses
Prat.Events = {
MODULE_ENABLED = "Prat_ModuleCreated",
DISABLED = "Prat_Disabled",
ENABLING = "Prat_Starting",
ENABLED = "Prat_Ready",
STARTUP = "Prat_Initialized",
DEBUG_UPDATE = "Prat_DebugModeChanged",
PRE_OUTBOUND = "Prat_PreOutboundChat",
OUTBOUND = "Prat_OutboundChat",
PRE_ADDMESSAGE = "Prat_PreAddMessage",
POST_ADDMESSAGE = "Prat_PostAddMessage",
POST_ADDMESSAGE_BLOCKED = "Prat_PostAddMessageBlocked",
FRAME_MESSAGE = "Prat_FrameMessage",
SECTIONS_UPDATED = "Prat_ChatSectionsUpdated",
FRAMES_UPDATED = "Prat_FramesUpdated",
FRAMES_REMOVED = "Prat_FramesRemoved",
}
Prat.EnableTasks = {}
local addon = LibStub("AceAddon-3.0"):NewAddon("Prat", "AceConsole-3.0", "AceTimer-3.0", "AceHook-3.0")
Prat.Addon = addon
--local callbacks
--[[ 1 = no load, 2 = disabled, 3 = enabled (this is temporary, a better format will be forthcoming, 4 is setdisabled, and 5 is setenabled]]
-- What I need to do is return the module's own value if the option isn't 1
-- but one problem is if the module was "no-load", and then is set to "enabled" but it thinks it should be "disabled"
local defaults = {
profile = {
modules = {
["Clear"] = 1,
["AddonMsgs"] = 1,
["CustomFilters"] = 1,
["EventNames"] = 1,
["Substitutions"] = 1,
["Experimental"] = 1,
["Filtering"] = 1,
["KeyBindings"] = 3,
["OriginalEditbox"] = 1,
["ChatTabs"] = 1,
["*"] = 3
}
},
realm = {
PlayerNameBlackList = {
["you"] = true
}
}
}
local SOUND
function addon:OnInitialize()
local IsAddOnLoaded = _G.C_AddOns.IsAddOnLoaded or _G.IsAddOnLoaded
if IsAddOnLoaded("Prat") == 1 then
Prat:Print(("Prat 2.0 was detected, and disabled. Please %s your UI."):format(GetReloadUILink()))
end
Prat.db = LibStub("AceDB-3.0"):New("Prat3DB", defaults, "Default")
_G.Prat3CharDB = _G.Prat3CharDB or {}
Prat.PlayerNameBlackList = Prat.db.realm.PlayerNameBlackList or {}
Prat.callbacks = LibStub("CallbackHandler-1.0"):New(Prat, "RegisterChatEvent", "UnregisterChatEvent", "UnregisterAllChatEvents")
Prat.Options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(Prat.db)
Prat.Options.args.profiles.order = tonumber(-1)
Prat.Media = LibStub("LibSharedMedia-3.0")
SOUND = Prat.Media.MediaType.SOUND
for k, v in pairs(builtinSounds) do
Prat.Media:Register(SOUND, k, v)
end
Prat.AddonName = self.baseName
Prat.builtinSounds = nil
-- Build the list of frames which we should hook addmessage on
-- IsCombatLog is not correct yet it appears, so we resort to checking
-- for chatframe2
for _, v in pairs(Prat.Frames) do
if (not _G.IsCombatLog(v)) and v ~= _G.ChatFrame2 then
Prat.HookedFrames[v:GetName()] = v
end
end
Prat.db.RegisterCallback(self, "OnProfileChanged", "UpdateProfile")
Prat.db.RegisterCallback(self, "OnProfileCopied", "UpdateProfile")
Prat.db.RegisterCallback(self, "OnProfileReset", "UpdateProfile")
-- _G.collectgarbage('collect')
-- Print("Pre-Module-Load Memory Use: "..MemoryUse())
Prat.LoadModules()
-- _G.collectgarbage('collect')
-- Print("Post-Module-Load Memory Use: "..MemoryUse())
self.OnInitalize = nil
end
local DEF_INFO = {
r = 1,
g = 1,
b = 1,
id = 1
}
-- Used for Prat/WIM integration
function Prat.Format(smf, event, color, ...)
local PRE_ADDMESSAGE = "Prat_PreAddMessage"
local POST_ADDMESSAGE = "Prat_PostAddMessage"
local FRAME_MESSAGE = "Prat_FrameMessage"
local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15 = ...;
local this = smf
local formattedText = ""
local m, info = Prat.SplitChatMessage(smf, event, ...)
if type(m) == "boolean" and m == true then
return ""
end
Prat.CurrentMessage = m
m.DONOTPROCESS = nil
local process = Prat.EventProcessingType.Full
Prat.callbacks:Fire(FRAME_MESSAGE, m, this, event)
if not m.DONOTPROCESS then
color = color or info
local r, g, b, id = color.r or 1, color.g or 1, color.b or 1, 1
-- Remove all the pattern matches ahead of time
m.MESSAGE = Prat.MatchPatterns(m)
Prat.callbacks:Fire(PRE_ADDMESSAGE, m, this, event, Prat.BuildChatText(m), r, g, b, id)
-- Pattern Matches Put Back IN
m.MESSAGE = Prat.ReplaceMatches(m)
if process == Prat.EventProcessingType.Full then
-- We are about to send the message
m.OUTPUT = Prat.BuildChatText(m) -- Combine all the chat sections
elseif process == Prat.EventProcessingType.PatternsOnly then
m.OUTPUT = (m.PRE or "") .. m.MESSAGE .. (m.POST or "")
else
if type(m.OUTPUT) == "string" then
-- Now we have the chatstring that the client was planning to output
-- For now just do it. (Tack on POST too)
m.OUTPUT = (m.PRE or "") .. m.OUTPUT .. (m.POST or "")
end
end
-- Allow for message blocking during the patern match phase
if not m.DONOTPROCESS then
formattedText = m.OUTPUT
end
-- We have called addmessage by now, or we have skipped it
-- regardless, we call postaddmessage. This was changed to allow
-- for more flexibility in the customfilters module, speficially
-- it allows for replacements to occur in blocked messages
Prat.callbacks:Fire(POST_ADDMESSAGE, m, this, event, m.OUTPUT, r, g, b, id)
end
m.CAPTUREOUTPUT = nil
m.OUTPUT = nil
m.INFO = nil
Prat.CurrentMessage = nil
return formattedText
end
function addon:OnEnable()
for i, v in ipairs(Prat.EnableTasks) do
v(self)
end
Prat.EnableTasks = nil
Prat.RegisterLinkType({
linkid = "rldui",
linkfunc = function(...) _G.ReloadUI() return false end
}, "Prat")
self:PostEnable()
end
function addon:UpdateProfile()
self:ScheduleTimer("UpdateProfileDelayed", 0)
end
function addon:UpdateProfileDelayed()
for k, v in self:IterateModules() do
if v.db.profile.on then
if v:IsEnabled() then
v:Disable()
v:Enable()
else
v:Enable()
end
else
v:Disable()
end
end
Prat.UpdateOptions()
end
function Prat.GetReloadUILink(Requestor)
return "Reload"
end
local module = {}
do
local org_GetChannelName = _G.GetChannelName
local chanTable
Prat.EnableTasks[#Prat.EnableTasks + 1] = function() chanTable = Prat.GetChannelTable() end
function Prat.GetChannelName(n)
local a, b, c = org_GetChannelName(n)
--dbg("GetChannelName: "..tostring(n), a,b,c)
if b == nil and chanTable then
n = chanTable[n]
if n ~= nil then
a, b, c = org_GetChannelName(n)
--dbg("GetChannelName: "..n, a,b,c)
end
end
return a, b, c
end
-- Orignial GetChannelName
--Prat 3.0 (244): >> print(GetChannelName(1))
--Prat 3.0 (244): 1, "General - The Storm Peaks", 0
--Prat 3.0 (244): >> print(GetChannelName("General"))
--Prat 3.0 (244): 0, nil, 0
-- Replace the global version with one which sucks a bit less
--_G.GetChannelName = GetChannelName
-- Improved GetChannelName
--Prat 3.0 (244): >> print(GetChannelName(1))
--Prat 3.0 (244): 1, "General - The Storm Peaks", 0
--Prat 3.0 (244): >> print(GetChannelName("General"))
--Prat 3.0 (244): 1, "General - The Storm Peaks", 0
end
function addon:FCF_SetTemporaryWindowType(chatFrame, chatType, chatTarget)
local name = chatFrame:GetName()
Prat.Frames[name] = chatFrame
Prat.HookedFrames[name] = chatFrame
Prat.callbacks:Fire(Prat.Events.FRAMES_UPDATED, name, chatFrame, chatType, chatTarget)
end
function addon:FCF_Close(frame, fallback)
local name = frame:GetName()
Prat.Frames[name] = nil
Prat.HookedFrames[name] = nil
Prat.callbacks:Fire(Prat.Events.FRAMES_REMOVED, name, frame)
end
function addon:FCF_CopyChatSettings(chatFrame)
if not chatFrame.isTemporary then
local name = chatFrame:GetName()
Prat.Frames[name] = chatFrame
if not _G.IsCombatLog(chatFrame) then
Prat.HookedFrames[name] = chatFrame
end
Prat.callbacks:Fire(Prat.Events.FRAMES_UPDATED, name, chatFrame)
end
end
function addon:PostEnable()
--[==[@debug@
Prat:Print(Prat.Version)
--@end-debug@]==]
Prat.AddPrintMethods()
if Prat.PrintSlashCommand then
self:RegisterChatCommand("print", Prat.PrintSlashCommand)
end
-- 2.4 Changes
-- self:RegisterEvent("CVAR_UPDATE")
-- Inbound Hooking
self:RawHook("ChatFrame_MessageEventHandler", true)
-- Outbound hooking
self:SecureHook("ChatEdit_ParseText")
-- Display Hooking
Prat.DummyFrame = _G.CreateFrame("ScrollingMessageFrame")
self:RawHook(Prat.DummyFrame, "AddMessage", true)
-- ItemRef Hooking
self:RawHook(_G.ItemRefTooltip, "SetHyperlink", true)
self:SecureHook("FCF_SetTemporaryWindowType")
self:SecureHook("FCF_Close")
self:SecureHook("FCF_CopyChatSettings")
-- -- This event fires after Prat's hooks are installed
-- -- Prat's core wont operate until after this event
Prat.callbacks:Fire(Prat.Events.SECTIONS_UPDATED)
Prat.callbacks:Fire(Prat.Events.ENABLED)
--[==[@debug@
-- if ChunkSizes then
-- local last = 0
-- for i, v in ipairs(ChunkSizes) do
-- self:Print("Chunk #"..tostring(i)..":"..("|cff80ffff%.0f|r KB"):format(v-last))
-- last = v
-- end
-- self:Print("Total Size: "..("|cff80ffff%.0f|r KB"):format(ChunkSizes[#ChunkSizes]))
-- ChunkSizes = nil
-- end
if Prat.Modules then
local total, loaded, enabled = 0, 0, 0
for k, v in pairs(Prat.Modules) do
total = total + 1
if v ~= "EXISTS" then
loaded = loaded + 1
end
if v == "ENABLED" then
enabled = enabled + 1
end
end
Prat:Print(("Module Count: |cff80ffff%d|r total |cff80ffff%d|r loaded, |cff80ffff%d|r enabled"):format(total, loaded, enabled))
end
if Prat.MemoryUse then
_G.collectgarbage("collect")
Prat:Print("Memory Use: " .. Prat.MemoryUse())
end
--@end-debug@]==]
if Prat.EnableGlobalCompletions then
Prat.EnableGlobalCompletions(Prat, "Prat-Global-Autocomplete")
end
end
function addon:SetHyperlink(frame, ...)
return Prat.SetHyperlinkHook(self.hooks[frame], frame, ...)
end
function addon:ChatEdit_ParseText(editBox, send)
local command = editBox:GetText()
-- this is what blizzard does
local cmd = command:match("^(#%s*[Ss][Hh][Oo][Ww]:*)%s[^%s]") or
command:match("^(#%s*[Ss][Hh][Oo][Ww][Tt][Oo][Oo][Ll][Tt][Ii][Pp]:*)%s[^%s]") or
command:match("^(/[^%s]+)");
-- Hack from blizzard's code
if (cmd and strfind(cmd, "^#")) then
-- This is a hack, but the "USE" code below handles bags and slots
cmd = SLASH_USE1;
end
if cmd and IsSecureCmd(cmd) then
return
end
local m = Prat.SplitMessageOut
wipe(m)
CurrentMessage = m
m.MESSAGE = command:gsub("^%s*(.-)%s*$", "%1") -- trim whitespace
m.CTYPE = editBox:GetAttribute("chatType")
m.TARGET = editBox:GetAttribute("tellTarget")
m.CHANNEL = editBox:GetAttribute("channelTarget")
m.LANGUAGE = editBox.language
m.SEND = send
if send ~= 1 then
return
end
self:ProcessUserEnteredChat(m)
editBox:SetAttribute("chatType", m.CTYPE)
editBox:SetAttribute("tellTarget", m.TARGET)
editBox:SetAttribute("channelTarget", m.CHANNEL)
editBox.languague = m.LANGUAGE
if m.DONOTPROCESS then
editBox:SetText("")
else
editBox:SetText(m.MESSAGE)
end
Prat.CurrentMessage = nil
end
function addon:ProcessUserEnteredChat(m)
if (m.MESSAGE:len() <= 0) then
return
end
Prat.callbacks:Fire(Prat.Events.PRE_OUTBOUND, m)
-- Remove all the pattern matches ahead of time
m.MESSAGE = Prat.MatchPatterns(m, "OUTBOUND")
Prat.callbacks:Fire(Prat.Events.OUTBOUND, m)
-- Pattern Matches Put Back IN
m.MESSAGE = Prat.ReplaceMatches(m, "OUTBOUND")
end
local fieldBlacklist = {
historyBuffer = true,
isLayoutDirty = true,
isDisplayDirty = true,
onDisplayRefreshedCallback = true,
onScrollChangedCallback = true,
onTextCopiedCallback = true,
scrollOffset = true,
visibleLines = true,
highlightTexturePool = true,
fontStringPool = true,
}
local savedFrame = {}
function Prat.CreateProxy(frame)
for k, v in pairs(frame) do
if type(v) ~= "function" and not fieldBlacklist[k] then
savedFrame[k] = Prat.DummyFrame[k]
Prat.DummyFrame[k] = v
end
end
Prat.DummyFrame.IsShown = function() return true end
return Prat.DummyFrame
end
function Prat.RestoreProxy()
for k, v in pairs(savedFrame) do
Prat.DummyFrame[k] = v
end
for k, v in pairs(Prat.DummyFrame) do
if type(v) ~= "function" and not fieldBlacklist[k] then
if savedFrame[k] == nil then
Prat.DummyFrame[k] = nil
end
end
end
end
function addon:ChatFrame_MessageEventHandler(this, event, ...)
local PRE_ADDMESSAGE = "Prat_PreAddMessage"
local POST_ADDMESSAGE = "Prat_PostAddMessage"
local FRAME_MESSAGE = "Prat_FrameMessage"
local POST_ADDMESSAGE_BLOCKED = "Prat_PostAddMessageBlocked"
local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15 = ...
loading = nil -- clear any batch message loading that may be happening
if not Prat.HookedFrames[this:GetName()] then
return self.hooks["ChatFrame_MessageEventHandler"](this, event, ...)
end
local message, info
local process = Prat.EventIsProcessed(event)
local CMEResult
if type(arg1) == "string" and (arg1):find("\r") then -- Stupid exploit. Protect our users.
arg1 = arg1:gsub("\r", " ")
end
-- Create a message table. This table contains the chat message in a non-concatenated form
-- so that it can be modified easily without lots of complex gsub's
message, info = Prat.SplitChatMessage(this, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
-- Handle Default-UI filtering: Since the default UI now provides filtering functions
-- similar to the way Prat's pattern registry works, we need to be sure not to call the
-- filtering functions twice by calling back into the hook chain - otherwise you could
-- have side effects of the handler functions being called more than once for a given event.
-- I don't see any way around this.
if type(message) == "boolean" and message == true then
return true
end
if not info then
return self.hooks["ChatFrame_MessageEventHandler"](this, event, ...)
else
local m = message --SplitMessage
-- Prat_FrameMessage is fired for every message going to the
-- chatframe which is displayable (has a chat infotype)
-- It may not be displayed, in which case no Pre/Post Addmessage
-- events will fire
-- Any addons which hook things will operate following this event
-- but before Prat_PreAddMessage, OUTPUT will contain the chat line
-- it may be modified by other addons.
--
-- Right now, prat will discard the chat line for chat types that
-- it is handling
--
m.OUTPUT = nil
m.DONOTPROCESS = nil
-- DUMP_OUTPUT_EX(this, "Prat_FrameMessage", nil, nil, m.CAPTUREOUTPUT, m.OUTPUT)
Prat.callbacks:Fire(FRAME_MESSAGE, message, this, message.EVENT)
-- A return value of true means that the message was processed
-- normally this would result in the OnEvent returning
-- for that chatframe
local proxy = Prat.CreateProxy(this)
m.CAPTUREOUTPUT = proxy
CMEResult = self.hooks["ChatFrame_MessageEventHandler"](proxy, event, ...) -- This specifically does not use message.EVENT
this.tellTimer = proxy.tellTimer
Prat.RestoreProxy()
m.CAPTUREOUTPUT = false
-- DBG_OUTPUT("CMEResult", CMEResult)
if type(m.OUTPUT) == "string" and not m.DONOTPROCESS then
Prat.CurrentMessage = m
local r, g, b, id = m.INFO.r, m.INFO.g, m.INFO.b, m.INFO.id
if process == Prat.EventProcessingType.Full or process == Prat.EventProcessingType.PatternsOnly then
-- Remove all the pattern matches ahead of time
m.MESSAGE = Prat.MatchPatterns(m, "FRAME")
end
Prat.callbacks:Fire(PRE_ADDMESSAGE, message, this, message.EVENT, Prat.BuildChatText(message), r, g, b, id)
if process == Prat.EventProcessingType.Full or process == Prat.EventProcessingType.PatternsOnly then
-- Pattern Matches Put Back IN
m.MESSAGE = Prat.ReplaceMatches(m, "FRAME")
end
if process == Prat.EventProcessingType.Full then
-- We are about to send the message
m.OUTPUT = Prat.BuildChatText(message) -- Combine all the chat sections
elseif process == Prat.EventProcessingType.PatternsOnly then
m.OUTPUT = (m.PRE or "") .. m.MESSAGE .. (m.POST or "")
else
-- Now we have the chatstring that the client was planning to output
-- For now just do it. (Tack on POST too)
m.OUTPUT = (m.PRE or "") .. m.OUTPUT .. (m.POST or "")
end
-- Allow for message blocking during the patern match phase
if m.DONOTPROCESS then
Prat.callbacks:Fire(POST_ADDMESSAGE_BLOCKED, m, this, message.EVENT, m.OUTPUT, r, g, b, id)
elseif m.OUTPUT:len() > 0 then
-- Hack to get the censored message display working with Prat
local isChatLineCensored = arg11 and C_ChatInfo.IsChatLineCensored(arg11);
local msg = isChatLineCensored and arg1 or m.OUTPUT
if isChatLineCensored then
local eventLabel = event
local eventArgs = SafePack(...);
this:AddMessage(msg, r, g, b, id, m.ACCESSID, m.TYPEID, eventLabel, eventArgs, function(text) return text end);
else
this:AddMessage(msg, r, g, b, id, m.ACCESSID, m.TYPEID);
end
-- We have called addmessage by now, or we have skipped it
-- regardless, we call postaddmessage. This was changed to allow
-- for more flexibility in the customfilters module, speficially
-- it allows for replacements to occur in blocked messages
Prat.callbacks:Fire(POST_ADDMESSAGE, m, this, message.EVENT, m.OUTPUT, r, g, b, id, m.ACCESSID, m.TYPEID)
if (not this:IsShown()) then
if ((this == _G.DEFAULT_CHAT_FRAME and m.INFO.flashTabOnGeneral) or (this ~= _G.DEFAULT_CHAT_FRAME and m.INFO.flashTab)) then
if (not _G.CHAT_OPTIONS.HIDE_FRAME_ALERTS or m.CHATTYPE == "WHISPER" or m.CHATTYPE == "BN_WHISPER") then --BN_WHISPER FIXME
if (not _G.FCFManager_ShouldSuppressMessageFlash(this, m.CHATGROUP, m.CHATTARGET)) then
_G.FCF_StartAlertFlash(this);
end
end
end
end
Prat.LastMessage = m
end
end
m.CAPTUREOUTPUT = nil
Prat.CurrentMessage = nil
end
return CMEResult
end
function addon:AddMessage(frame, text, r, g, b, id, ...)
local s = Prat.SplitMessage
if s.OUTPUT == nil and s.CAPTUREOUTPUT == frame --[[ and Prat.dumping == false]] then
-- s.INFO.r, s.INFO.g, s.INFO.b, s.INFO.id = r, g, b, id
s.ORG.OUTPUT = text
else
self.hooks[frame].AddMessage(frame, text, r, g, b, id, ...)
end
end
local wowsounds = {
["TellMessage"] = _G.SOUNDKIT.TELL_MESSAGE,
}
function Prat.PlaySound(self, sound)
if not sound then return end
if wowsounds[sound] then
_G.PlaySound(wowsounds[sound], "Master")
else
local play
if play == nil then
play = Prat.Media:Fetch(SOUND, sound)
end
if play == nil then return end
_G.PlaySoundFile(play, "Master")
end
end
function Prat.CanSendChatMessage(type)
if type == "SAY" or type == "YELL" then
return _G.IsInInstance("player")
elseif type == "RAID" or type == "GUILD" or type == "WHISPER" then
return true
end
return false
end
function Prat.RegisterChatCommand(cmd, func)
addon:RegisterChatCommand(cmd, func)
end
Prat.RegisterChatCommand("pratblacklist",
function(name)
if name and #name > 0 then
Prat:Print("Blacklisting: '" .. tostring(name) .. "' to activate " .. Prat.GetReloadUILink())
db.realm.PlayerNameBlackList[tostring(name):lower()] = true
end
end)
Prat.RegisterChatCommand("pratunblacklist",
function(name)
if name and #name > 0 then
Prat:Print("Un-Blacklisting: '" .. tostring(name) .. "' to activate " .. Prat.GetReloadUILink())
db.realm.PlayerNameBlackList[tostring(name):lower()] = nil
end
end)
Prat.RegisterChatCommand("pratdebugmsg",
function(name)
Prat:PrintLiteral(LastMessage, Prat.LastMessage.ORG)
local cc = addon:GetModule("CopyChat", true)
if cc then cc:ScrapeFullChatFrame(printFrame or _G.DEFAULT_CHAT_FRAME, true) end
end)
Prat.RegisterChatCommand("pratdebug", function(name)
local dm = addon:GetModule("DebugModules", true)
if dm then
dm:ShowCopyDialog()
end
end)