/trunk
## Interface: 30300 |
## Title: NightWatch |
## Notes: Sends chat alerts for certain spells. "/nw" for config. |
## Notes: Sends chat alerts for selected spells. "/nw" for config. |
## Author: Nightyniight @ Frostmourne - US |
## Version: 0.8.wowi:revision |
## Version: 0.8 |
## DefaultState: Enabled |
## LoadOnDemand: 0 |
## SavedVariables: NightWatchDB |
## OptionalDeps: Ace3, LibSink |
## X-Embeds: Ace3, LibSink |
## OptionalDeps: Ace3, LibSink-2.0 |
## X-Embeds: Ace3, LibSink-2.0 |
#@no-lib-strip@ |
Libs\LibStub\LibStub.lua |
local addon = LibStub("AceAddon-3.0"):NewAddon("NightWatch", "AceConsole-3.0", "AceEvent-3.0") |
local ACD = LibStub("AceConfigDialog-3.0") |
local sink1 = addon:NewModule("NightWatchSink1", "LibSink-2.0") |
local sink2 = addon:NewModule("NightWatchSink2", "LibSink-2.0") |
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded. |
-- Listed here for Mikk's FindGlobals script. |
-- GLOBALS: LibStub |
local GetNumPartyMembers = GetNumPartyMembers |
local InCombatLockdown = InCombatLockdown |
local version = GetAddOnMetadata("NightWatch", "Version") |
local version = GetAddOnMetadata("NightWatch", "Version") |
local playerName = UnitName("player") |
local firstEnable = true |
local db |
local clipboard = {} |
local sink = {} |
local i |
for i = 1, 4 do |
sink[i] = addon:NewModule("Sink" .. i , "LibSink-2.0") |
end |
local function Print(msg) |
print(format("|cffffff7fnw|r: %s",msg)) |
end |
function addon:defaultMsgFormat() |
return { |
chat = "<%C's> %s%t: %f", |
profile = { |
enabled = true, |
spells = {}, |
sinkStorage1 = { sink20OutputSink = "ChatFrame", }, |
sinkStorage2 = { sink20OutputSink = "None", }, |
sinkStorage = { |
[1] = { sink20OutputSink = "ChatFrame", }, |
[2] = { sink20OutputSink = "None", }, |
[3] = { sink20OutputSink = "None", }, |
[4] = { sink20OutputSink = "None", }, |
}, |
customMsgFormat = addon:defaultMsgFormat(), |
-- flagMap is used as a translation lookup and to help generate the default flag options for each watched spell. |
flagMap = { |
SPELL_CAST_START = "started", |
end |
return result |
end |
function addon:wsDefaults() |
return { |
watched = true, |
whisperTarget = false, |
output1 = true, |
output2 = false, |
output3 = false, |
output4 = false, |
combatOnly = false, |
anyFlag = true, |
flags = addon:flagDefaults(), |
} |
end |
local wantIconLinks = { |
["ChatFrame"] = true, |
["Default"] = true, |
["Blizzard Error Frame"] = true, |
["Raid Warning"] = true, |
} |
local icons = { |
star = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1:0|t", |
circle = "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2:0|t", |
order = 20, cmdHidden = true, |
type = "toggle", |
get = function(info) return db[info[#info]] end, |
set = function(info, value) |
if value then |
addon:Enable() |
else |
addon:Disable() |
set = function(info, value) |
if value then |
addon:Enable() |
else |
addon:Disable() |
end |
end, |
}, |
}, |
}, |
} |
opts.args.spell = { |
name = "Spell Options", |
order = 10, |
}, |
}, |
} |
opts.args.spell.args.general = { |
name = "General", |
order = 10, |
order = 60, |
type = "toggle", |
}, |
output1 = { |
name = "Output 1", |
desc = "Send output here.", |
order = 70, |
type = "toggle", |
}, |
output2 = { |
name = "Output 2", |
desc = "Send output here.", |
order = 80, |
type = "toggle", |
}, |
flags = { |
name = "Combatlog Flags", |
order = 90, |
}, |
} |
for i = 1,4 do |
opts.args.spell.args.general.args["output" .. i] = { |
name = "Output " .. i, |
desc = "Send output here.", |
order = 70 + 1, |
type = "toggle", |
} |
end |
opts.args.spell.args.msgFormat = { |
name = "Message Format", |
type = "group", |
desc = "If set, this will replace %t if there is a target.", |
order = 40, |
type = "input", |
}, |
}, |
whisperTest = { |
name = function() return addon:whisperTest() end, |
order = 60, |
order = 140, width = "half", |
type = "execute", |
func = function() addon:resetFmtToDefault(db.selSpell) end, |
}, |
}, |
formatHelp = { |
name = "\n** Format Syntax **\n" .. |
"%c = Caster\n" .. |
} |
opts.args.output = { |
name = "Output", |
name = "Outputs", |
desc = "Configure output options.", |
type = "group", |
order = 30, |
args = {} |
} |
local sink1 = sink1:GetSinkAce3OptionsDataTable() |
sink1.name = "Output 1" |
sink1.desc = "Where to send this addon's primary output." |
sink1.order = 10 |
-- sink1.cmdHidden = true |
sink1.inline = true |
local sinkOpts = {} |
for i = 1, #sink do |
sinkOpts[i] = sink[i]:GetSinkAce3OptionsDataTable() |
sinkOpts[i].name = "Output " .. i |
sinkOpts[i].desc = "Where to send this output." |
sinkOpts[i].order = 10 + i |
-- sinkOpts[i].inline = true |
opts.args.output.args["output" .. i] = sinkOpts[i] |
end |
local sink2 = sink2:GetSinkAce3OptionsDataTable() |
sink2.name = "Output 2" |
sink2.desc = "Where to send this addon's secondary output." |
sink2.order = 20 |
-- sink2.cmdHidden = true |
sink2.inline = true |
opts.args.output.args.output1 = sink1 |
opts.args.output.args.output2 = sink2 |
opts.args.flagOptions = { |
name = "Flag Options", |
desc = "Configure flag options.", |
order = 80, |
type = "input", |
get = function() return nil end, |
set = function(_, value) |
set = function(_, value) |
db.flagMap[value] = value |
LibStub("AceConfigRegistry-3.0"):NotifyChange("NightWatch") |
end, |
}, |
} |
opts.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(addon.db) |
opts.args.profile.order = -10 |
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("NightWatch", "NightWatch") |
addon:RegisterChatCommand("nw", "chatCommand") |
addon:RegisterChatCommand("nightwatch", "chatCommand") |
sink1:SetSinkStorage(db.sinkStorage1) |
sink2:SetSinkStorage(db.sinkStorage2) |
for i = 1, #sink do |
sink[i]:SetSinkStorage(db.sinkStorage[i]) |
end |
addon:upgrade() |
addon:resetSelected() |
end |
-- 0 1 2 3 4 5 6 7 8 9 10 11 12 |
-- _,timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellID, spellName, spellSchool, missType, ...) |
-- |
-- 0 1 2 3 4 5 6 7 8 9 10 |
-- 0 1 2 3 4 5 6 7 8 9 10 |
local msg |
local whisperTarget |
function addon:combatLogEvent(_, _, flag, _, source, _, _, target, _, _, spell, ...) |
if not db.spells[spell] then return end -- Spell not in database, quit |
local ws = db.spells[spell] |
if not ws.watched then return end -- Not being watched, quit |
if not (ws.anyFlag or ws.flags[flag]) then return end -- Doesn't match flags, quit |
if ws.selfOnly and not (source == playerName) then return end -- Check for self-cast only |
if ws.combatOnly and not InCombatLockdown() then return end -- Check for self in combat |
if ws.groupOnly and not (UnitInRaid(source) or UnitInParty(source)) then return end -- Check for source in raid/party |
if db.flagMap[flag] then -- Convert flag to more friendly version, if available. |
flag = db.flagMap[flag] |
end |
if target then |
if ws.whisperTarget then -- Whisper target |
if ws.msgFormat.whisperTarget then |
end |
msg = addon:formatMsg(source, spell, target, flag, ws.msgFormat.chat) |
if ws.output1 then -- Send to output |
if db.sinkStorage1.sink20OutputSink == "ChatFrame" then |
msg = addon:mkIconLinks(msg) |
for i = 1, #sink do |
if ws["output" .. i] then -- Send to output |
if wantIconLinks[db.sinkStorage[i].sink20OutputSink] then |
msg = addon:mkIconLinks(msg) |
end |
addon:pour(sink[i], msg) |
end |
addon:pour(sink1, msg) |
end |
if ws.output2 then |
if db.sinkStorage2.sink20OutputSink == "ChatFrame" then |
msg = addon:mkIconLinks(msg) |
end |
addon:pour(sink2, msg) |
end |
end |
------------------------------------------------------------------------------- |
ACD[ACD.OpenFrames.NightWatch and "Close" or "Open"](ACD,"NightWatch") |
end |
function addon:resetSettings() |
function addon:resetSettings() |
addon.db:ResetProfile() |
Print("All settings in this profile have been reset to default values.") |
end |
LibStub("AceConfigRegistry-3.0"):NotifyChange("NightWatch") |
end |
function addon:addSpell(info, value) |
function addon:addSpell(info, value) |
db.spells[value] = addon:wsDefaults() |
-- db.spells[value].watched = true |
db.spells[value].msgFormat = addon:deepcopy(db.customMsgFormat) |
function addon:chatTest() |
if not db.selSpell then return nil end |
return addon:testMsg( |
db.spells[db.selSpell].msgFormat.chat, |
db.spells[db.selSpell].msgFormat.chat, |
db.spells[db.selSpell].msgFormat.chatTarget |
) |
) |
end |
function addon:whisperTest() |
if not db.selSpell then return nil end |
return addon:testMsg( |
db.spells[db.selSpell].msgFormat.whisper, |
db.spells[db.selSpell].msgFormat.whisper, |
db.spells[db.selSpell].msgFormat.whisperTarget |
) |
) |
end |
function addon:testMsg(formatString, targetFormatString) |
local source, spell, target, flag = "Caster", db.selSpell or "Spell", "Target", "Flag" |
if not (targetFormatString == "" or targetFormatString == nil) then |
for k,_ in pairs(db.spells) do |
addon:pasteFmt(k) |
end |
end |
end |
function addon:resetFmtToDefault(value) |
if not value then return end |