WoWInterface SVN DisplacedEnergyNazi

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /trunk
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

DisplacedEnergyNazi/DisplacedEnergyNazi.toc
12,7 → 12,7
## Author: Acapela
## OptionalDeps: Ace3, LibStub
## X-Category: Interface Enhancements
## X-Embeds: Ace3, LibStub
## X-Embeds: Ace3, LibStub, LibSink-2.0
## SavedVariables: DisplacedEnergyNaziDB
## X-License: LGPL v2.1 or later
 
38,6 → 38,8
Libs\AceHook-3.0\AceHook-3.0.xml
Libs\AceTimer-3.0\AceTimer-3.0.xml
 
Libs\LibSink-2.0\lib.xml
 
##### Core DisplacedEnergyNazi
 
DisplacedEnergyNaziLocale.lua
45,4 → 47,6
 
Version.lua
 
DisplacedEnergyNaziOptions.lua
 
##
DisplacedEnergyNazi/Libs/LibSink-2.0/LibSink-2.0.lua New file
0,0 → 1,759
--[[
Name: Sink-2.0
Revision: $Rev: 97 $
Author(s): Funkydude, Rabbit
Description: Library that handles chat output.
Dependencies: LibStub, SharedMedia-3.0 (optional)
License: CC-BY-NC-SA 3.0
]]
 
--[[
Copyright (C) 2008-2013
For the attribution bit of the license, as long as you distribute the library unmodified,
no attribution is required.
If you derive from the library or change it in any way, you are required to contact the author(s).
]]
 
-----------------------------------------------------------------------
-- Sink-2.0
 
local SINK20 = "LibSink-2.0"
local SINK20_MINOR = 90000 + tonumber(("$Revision: 97 $"):match("(%d+)"))
 
local sink = LibStub:NewLibrary(SINK20, SINK20_MINOR)
if not sink then return end
 
-- Start upgrade
sink.storageForAddon = sink.storageForAddon or {}
sink.override = sink.override or {}
sink.msbt_registered_fonts = sink.msbt_registered_fonts or {}
sink.registeredScrollAreaFunctions = sink.registeredScrollAreaFunctions or {}
sink.handlers = sink.handlers or {}
 
sink.stickyAddons = sink.stickyAddons or {
Blizzard = true,
MikSBT = true,
SCT = true,
Parrot = true,
}
 
-- Upgrade complete
 
local format = string.format
 
local L_DEFAULT = "Default"
local L_DEFAULT_DESC = "Route output from this addon through the first available handler, preferring scrolling combat text addons if available."
local L_ROUTE = "Route output from this addon through %s."
local L_SCT = "Scrolling Combat Text"
local L_MSBT = "MikSBT"
local L_BIGWIGS = "BigWigs"
local L_UIERROR = "Blizzard Error Frame"
local L_CHAT = "Chat"
local L_BLIZZARD = "Blizzard FCT"
local L_RW = "Raid Warning"
local L_PARROT = "Parrot"
local L_CHANNEL = "Channel"
local L_OUTPUT = "Output"
local L_OUTPUT_DESC = "Where to route the output from this addon."
local L_SCROLL = "Sub section"
local L_SCROLL_DESC = "Set the sub section where messages should appear.\n\nOnly available for some output sinks."
local L_STICKY = "Sticky"
local L_STICKY_DESC = "Set messages from this addon to appear as sticky.\n\nOnly available for some output sinks."
local L_NONE = "None"
local L_NONE_DESC = "Hide all messages from this addon."
local L_NOTINCHANNEL = " (You tried sending this to the channel %s, but it appears you are not there.)"
 
local l = GetLocale()
if l == "koKR" then
L_DEFAULT = "기본"
L_DEFAULT_DESC = "처음으로 사용 가능한 트레이너를 통해 이 애드온으로부터 출력을 보냅니다."
L_ROUTE = "%s|1을;를; 통해 이 애드온의 메시지를 출력합니다."
L_SCT = "Scrolling Combat Text"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "블리자드 오류 창"
L_CHAT = "대화창"
L_BLIZZARD = "블리자드 FCT"
L_RW = "공격대 경보"
L_PARROT = "Parrot"
L_OUTPUT = "출력"
L_OUTPUT_DESC = "어디에 이 애드온의 메시지를 출력할지 선택합니다."
L_SCROLL = "스크롤 영역"
L_SCROLL_DESC = "메시지를 출력할 스크룰 영역을 설정합니다.\n\nParrot, SCT나 MikSBT만 사용 가능합니다."
L_STICKY = "점착"
L_STICKY_DESC = "달라붙는 것처럼 보일 이 애드온의 메시지를 설정합니다.\n\n블리자드 FCT, Parrot, SCT나 MikSBT만 사용 가능합니다."
L_NONE = "없음"
L_NONE_DESC = "이 애드온의 모든 메시지를 숨김니다."
elseif l == "frFR" then
L_DEFAULT = "Par défaut"
L_DEFAULT_DESC = "Transmet la sortie de cet addon via le premier handler disponible, de préférence les textes de combat défilants s'il y en a."
L_ROUTE = "Transmet la sortie de cet addon via %s."
L_SCT = "Scrolling Combat Text"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Cadre des erreurs"
L_CHAT = "Fenêtre de discussion"
L_BLIZZARD = "TCF de Blizzard"
L_RW = "Avertissement raid"
L_PARROT = "Parrot"
L_CHANNEL = "Canal"
L_OUTPUT = "Sortie"
L_OUTPUT_DESC = "Destination de la sortie de cet addon."
L_SCROLL = "Sous-section"
L_SCROLL_DESC = "Définit la sous-section où les messages doivent apparaitre.\n\nDisponible uniquement dans certains cas."
L_STICKY = "En évidence"
L_STICKY_DESC = "Fait en sortie que les messages de cet addon apparaissent en évidence.\n\nDisponible uniquement dans certains cas."
L_NONE = "Aucun"
L_NONE_DESC = "Masque tous les messages provenant de cet addon."
elseif l == "deDE" then
L_DEFAULT = "Voreinstellung"
L_DEFAULT_DESC = "Leitet die Ausgabe von diesem Addon zum ersten verfügbaren Ausgabeort, vorzugsweise Scrollende Kampf Text Addons wenn verfügbar."
L_ROUTE = "Schickt die Meldungen dieses Addons an %s."
L_SCT = "Scrolling Combat Text(SCT)"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Blizzard's Fehler Fenster"
L_CHAT = "Im Chat"
L_BLIZZARD = "Blizzard's schwebenden Kampftext"
L_RW = "Schlachtzug's Warnung"
L_PARROT = "Parrot"
L_OUTPUT = "Ausgabe"
L_OUTPUT_DESC = "Wohin die Meldungen des Addons gesendet werden soll."
L_SCROLL = "Scroll Bereich"
L_SCROLL_DESC = "Setzt die Scroll Bereich, wo die Meldungen erscheinen sollen.\n\nNur verfügbar für Parrot, SCT oder MikSBT."
L_STICKY = "Stehend"
L_STICKY_DESC = "Läßt Nachrichten von diesem Addon als stehende Nachrichten erscheinen.\n\nNur verfügbar für Blizzard FCT, Parrot, SCT oder MikSBT."
L_NONE = "Nirgends"
L_NONE_DESC = "Versteckt alle Meldungen von diesem Addon."
elseif l == "zhCN" then
L_DEFAULT = "默认"
L_DEFAULT_DESC = "插件的输出方式取决于第一个可用插件,例如有 SCT 插件,则优先使用。"
L_ROUTE = "经由%s显示信息。"
L_SCT = "SCT"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Blizzard 错误框体"
L_CHAT = "聊天框体"
L_BLIZZARD = "系统自带滚动战斗信息"
L_RW = "团队警告"
L_PARROT = "Parrot"
L_CHANNEL = "频道"
L_OUTPUT = "输出模式"
L_OUTPUT_DESC = "设置显示位置。"
L_SCROLL = "滚动区域"
L_SCROLL_DESC = "设置滚动信息显示位置。\n\n只有 Parrot、SCT 及 MikSBT 支持。"
L_STICKY = "固定"
L_STICKY_DESC = "设置信息固定显示位置。\n\n只有系统自带滚动战斗信息、Parrot、SCT 及 MikSBT 支持。"
L_NONE = "隐藏"
L_NONE_DESC = "隐藏所有来自插件的信息。"
L_NOTINCHANNEL = "(尝试发送到%s频道,但其并不存在。)"
elseif l == "zhTW" then
L_DEFAULT = "預設"
L_DEFAULT_DESC = "插件輸出經由第一個可使用的處理器顯示,如果有 SCT 的話,則優先使用。"
L_ROUTE = "插件輸出經由%s顯示。"
L_SCT = "SCT"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Blizzard 錯誤訊息框架"
L_CHAT = "聊天視窗"
L_BLIZZARD = "Blizzard 浮動戰鬥文字"
L_RW = "團隊警告"
L_PARROT = "Parrot"
L_CHANNEL = "頻道"
L_OUTPUT = "顯示模式"
L_OUTPUT_DESC = "插件輸出經由哪裡顯示。"
L_SCROLL = "滾動區域"
L_SCROLL_DESC = "設定滾動訊息出現位置。\n\n只有 Parrot,SCT 及 MikSBT 有支援。"
L_STICKY = "固定"
L_STICKY_DESC = "設定使用固定訊息。\n\n只有 Blizzard 浮動戰鬥文字,Parrot,SCT 及 MikSBT 有支援。"
L_NONE = "隱藏"
L_NONE_DESC = "隱藏所有插件輸出。"
L_NOTINCHANNEL = "(你嘗試發送訊息到頻道%s,但是此頻道不存在。)"
elseif l == "ruRU" then
L_DEFAULT = "По умолчанию"
L_DEFAULT_DESC = "Маршрут вывода сообщений данного аддона через первое доступное устройство, предпочитая доступные аддоны прокрутки текста боя."
L_ROUTE = "Маршрут вывода сообщений данного аддона через %s."
L_SCT = "SCT"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Фрейм ошибок Blizzard"
L_CHAT = "Чат"
L_BLIZZARD = "Blizzard FCT"
L_RW = "Объявление рейду"
L_PARROT = "Parrot"
L_CHANNEL = "Канал"
L_OUTPUT = "Вывод"
L_OUTPUT_DESC = "Куда выводить сообщения данного аддона."
L_SCROLL = "Область прокрутки"
L_SCROLL_DESC = "Назначить область прокрутки куда должны выводиться сообщения.\n\nДоступно только для Parrotа, SCT или MikSBT."
L_STICKY = "Клейкий"
L_STICKY_DESC = "Сделать сообщения данного аддона клейкими.\n\nДоступно только для Blizzard FCT, Parrot, SCT или MikSBT."
L_NONE = "Нету"
L_NONE_DESC = "Скрыть все сообщения данного аддона."
elseif l == "esES" or l == "esMX" then
L_DEFAULT = "Por defecto"
L_DEFAULT_DESC = "Envía los mensajes de este addon al primer canal disponible, preferiblemente a addons SCT si los hay."
L_ROUTE = "Envía los mensajes de este addon a %s."
L_SCT = "Scrolling Combat Text"
L_MSBT = "MikSBT"
L_BIGWIGS = "BigWigs"
L_UIERROR = "Marco de errores de Blizzard"
L_CHAT = "Chat"
L_BLIZZARD = "Texto flotante de Blizzard"
L_RW = "Aviso de la banda"
L_PARROT = "Parrot"
L_CHANNEL = "Canal específico"
L_OUTPUT = "Salida"
L_OUTPUT_DESC = "Dónde enviar los mensajes de este addon."
L_SCROLL = "Sub seción"
L_SCROLL_DESC = "Especifica dónde deberán mostrarse los mensajes.\n\nSólo disponible en algunas opciones de salida."
L_STICKY = "Destacar"
L_STICKY_DESC = "Especifica que los mensajes deberán mostrarse de forma destacada.\n\nSólo disponible en algunas opciones de salida."
L_NONE = "Ninguno"
L_NONE_DESC = "Oculta todos los mensajes de este addon."
elseif l == "ptBR" then
-- Missing
elseif l == "itIT" then
-- Missing
end
 
local SML = LibStub("LibSharedMedia-3.0", true)
 
local function getSticky(addon)
return sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20Sticky or nil
end
 
-- Thanks to Antiarc and his Soar-1.0 library for most of the 'meat' of the
-- sink-specific functions.
 
local function parrot(addon, text, r, g, b, font, size, outline, sticky, loc, icon)
local location = sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20ScrollArea or "Notification"
local s = getSticky(addon) or sticky
Parrot:ShowMessage(text, location, s, r, g, b, font, size, outline, icon)
end
 
local sct_color = {}
local function sct(addon, text, r, g, b, font, size, outline, sticky, _, icon)
sct_color.r, sct_color.g, sct_color.b = r, g, b
local loc = sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20ScrollArea or "Messages"
local location = (loc == "Outgoing" and SCT.FRAME1) or (loc == "Incoming" and SCT.FRAME2) or SCT.MSG
local s = getSticky(addon) or sticky
SCT:DisplayCustomEvent(text, sct_color, s, location, nil, icon)
end
 
local msbt_outlines = {["NORMAL"] = 1, ["OUTLINE"] = 2, ["THICKOUTLINE"] = 3}
local function msbt(addon, text, r, g, b, font, size, outline, sticky, _, icon)
if font and SML and not sink.msbt_registered_fonts[font] then
MikSBT.RegisterFont(font, SML:Fetch("font", font))
sink.msbt_registered_fonts[font] = true
end
local location = sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20ScrollArea or MikSBT.DISPLAYTYPE_NOTIFICATION
local s = getSticky(addon) or sticky
MikSBT.DisplayMessage(text, location, s, r * 255, g * 255, b * 255, size, font, msbt_outlines[outline], icon)
end
 
local function blizzard(addon, text, r, g, b, font, size, outline, sticky, _, icon)
if icon then text = "|T"..icon..":20:20:-5|t"..text end
if tostring(SHOW_COMBAT_TEXT) ~= "0" then
local s = getSticky(addon) or sticky
if type(CombatText_AddMessage) == "nil" then
UIParentLoadAddOn("Blizzard_CombatText")
end
CombatText_AddMessage(text, CombatText_StandardScroll, r, g, b, s and "crit" or nil, false)
else
UIErrorsFrame:AddMessage(text, r, g, b, 1.0)
end
end
 
sink.channelMapping = sink.channelMapping or {
[SAY] = "SAY",
[PARTY] = "PARTY",
[INSTANCE_CHAT] = "INSTANCE_CHAT",
[GUILD_CHAT] = "GUILD",
[OFFICER_CHAT] = "OFFICER",
[YELL] = "YELL",
[RAID] = "RAID",
[RAID_WARNING] = "RAID_WARNING",
[GROUP] = "GROUP",
}
sink.channelMappingIds = sink.channelMappingIds or {}
sink.frame = sink.frame or CreateFrame("Frame")
sink.frame:UnregisterAllEvents()
sink.frame:RegisterEvent("CHANNEL_UI_UPDATE")
sink.frame:RegisterEvent("PLAYER_ENTERING_WORLD")
do
local function loop(...)
wipe(sink.channelMappingIds)
for i = 1, select("#", ...), 2 do
local id, name = select(i, ...)
sink.channelMappingIds[name] = id
end
for k, v in next, sink.channelMapping do
if v == "CHANNEL" and not sink.channelMappingIds[k] then
sink.channelMapping[k] = nil
end
end
for k in next, sink.channelMappingIds do sink.channelMapping[k] = "CHANNEL" end
end
local function rescanChannels() loop(GetChannelList()) end
sink.frame:SetScript("OnEvent", rescanChannels)
rescanChannels()
end
 
local function color_strip(a, b, c)
if b:sub(1,2) == "|H" then
return a..b..c
else
return b
end
end
 
local function channel(addon, text)
-- Sanitize the text, remove all color codes.
text = text:gsub("(|c%x%x%x%x%x%x%x%x)(.-)(|r)", color_strip)
local loc = sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20ScrollArea or "SAY"
local chan = sink.channelMapping[loc]
if chan == "GROUP" then
chan = (IsInGroup(2) and "INSTANCE_CHAT") or (IsInRaid() and "RAID") or (IsInGroup() and "PARTY") or "SAY"
elseif chan == "CHANNEL" then
local id, name = GetChannelName(sink.channelMappingIds[loc])
if name then
SendChatMessage(text, "CHANNEL", nil, id)
else
print("LibSink:", text, L_NOTINCHANNEL:format(loc))
end
return
end
SendChatMessage(text, chan or "SAY")
end
 
local function chat(addon, text, r, g, b, _, _, _, _, _, icon)
if icon then text = "|T"..icon..":15|t"..text end
DEFAULT_CHAT_FRAME:AddMessage(text, r, g, b)
end
 
local function uierror(addon, text, r, g, b, _, _, _, _, _, icon)
if icon then text = "|T"..icon..":20:20:-5|t"..text end
UIErrorsFrame:AddMessage(text, r, g, b, 1.0)
end
 
local rw
do
local white = {r = 1, g = 1, b = 1}
function rw(addon, text, r, g, b, _, _, _, _, _, icon)
if r or g or b then
text = format("\124cff%02x%02x%02x%s\124r", (r or 0) * 255, (g or 0) * 255, (b or 0) * 255, text)
end
if icon then text = "\124T"..icon..":20:20:-5\124t"..text end
RaidNotice_AddMessage(RaidWarningFrame, text, white)
end
end
 
local function noop() --[[ noop! ]] end
 
local handlerPriority = { "Parrot", "SCT", "MikSBT" }
local customHandlersEnabled = {
Parrot = function()
if not _G.Parrot then return end
return _G.Parrot.IsEnabled and _G.Parrot:IsEnabled() or _G.Parrot:IsActive()
end,
SCT = function()
return _G.SCT and _G.SCT:IsEnabled()
end,
MikSBT = function()
return _G.MikSBT and not _G.MikSBT.IsModDisabled()
end,
}
 
local currentHandler = nil
local function getPrioritizedSink()
if currentHandler then
local check = customHandlersEnabled[currentHandler]
if check and check() then
return sink.handlers[currentHandler]
end
end
for i, v in next, handlerPriority do
local check = customHandlersEnabled[v]
if check and check() then
currentHandler = v
return sink.handlers[v]
end
end
if SHOW_COMBAT_TEXT and tostring(SHOW_COMBAT_TEXT) ~= "0" then
return blizzard
end
return chat
end
 
local function pour(addon, text, r, g, b, ...)
local func = sink.override and sink.handlers[sink.override] or nil
if not func and sink.storageForAddon[addon] and sink.storageForAddon[addon].sink20OutputSink then
local h = sink.storageForAddon[addon].sink20OutputSink
func = sink.handlers[h]
-- If this sink is not available now, find one manually.
if customHandlersEnabled[h] and not customHandlersEnabled[h]() then
func = nil
end
end
if not func then
func = getPrioritizedSink()
end
if not func then func = chat end
func(addon, text, r or 1, g or 1, b or 1, ...)
end
 
function sink:Pour(textOrAddon, ...)
local t = type(textOrAddon)
if t == "string" then
pour(self, textOrAddon, ...)
elseif t == "number" then
pour(self, tostring(textOrAddon), ...)
elseif t == "table" then
pour(textOrAddon, ...)
else
error("Invalid argument 2 to :Pour, must be either a string or a table.")
end
end
 
local sinks
do
-- Maybe we want to hide them instead of disable
local function shouldDisableSCT()
return not _G.SCT
end
local function shouldDisableMSBT()
return not _G.MikSBT
end
local function shouldDisableParrot()
return not _G.Parrot
end
local function shouldDisableFCT()
return not SHOW_COMBAT_TEXT or tostring(SHOW_COMBAT_TEXT) == "0"
end
 
local sctFrames = {"Incoming", "Outgoing", "Messages"}
local msbtFrames = nil
local tmp = {}
local function getScrollAreasForAddon(addon)
if type(addon) ~= "string" then return nil end
if addon == "Parrot" then
if Parrot.GetScrollAreasChoices then
return Parrot:GetScrollAreasChoices()
else
return Parrot:GetScrollAreasValidate()
end
elseif addon == "MikSBT" then
if not msbtFrames then
msbtFrames = {}
for key, name in MikSBT.IterateScrollAreas() do
msbtFrames[#msbtFrames+1] = name
end
end
return msbtFrames
elseif addon == "SCT" then
return sctFrames
elseif addon == "Channel" then
wipe(tmp)
for k in next, sink.channelMapping do
tmp[#tmp + 1] = k
end
return tmp
elseif sink.registeredScrollAreaFunctions[addon] then
return sink.registeredScrollAreaFunctions[addon]()
end
return nil
end
 
local emptyTable, args, options = {}, {}, {}
sinks = {
Default = {L_DEFAULT, L_DEFAULT_DESC},
SCT = {L_SCT, nil, shouldDisableSCT},
MikSBT = {L_MSBT, nil, shouldDisableMSBT},
Parrot = {L_PARROT, nil, shouldDisableParrot},
Blizzard = {L_BLIZZARD, nil, shouldDisableFCT},
RaidWarning = {L_RW},
ChatFrame = {L_CHAT},
Channel = {L_CHANNEL},
UIErrorsFrame = {L_UIERROR},
None = {L_NONE, L_NONE_DESC}
}
 
local function getAce2SinkOptions(key, opts)
local name, desc, hidden = unpack(opts)
args["Ace2"][key] = {
type = "toggle",
name = name,
desc = desc or format(L_ROUTE, name),
isRadio = true,
hidden = hidden
}
end
 
function sink.GetSinkAce2OptionsDataTable(addon)
options["Ace2"][addon] = options["Ace2"][addon] or {
output = {
type = "group",
name = L_OUTPUT,
desc = L_OUTPUT_DESC,
pass = true,
get = function(key)
if not sink.storageForAddon[addon] then
return "Default"
end
if tostring(key) == "nil" then
-- Means AceConsole wants to list the output option,
-- so we should show which sink is currently used.
return sink.storageForAddon[addon].sink20OutputSink or L_DEFAULT
end
if key == "ScrollArea" then
return sink.storageForAddon[addon].sink20ScrollArea
elseif key == "Sticky" then
return sink.storageForAddon[addon].sink20Sticky
else
if sink.storageForAddon[addon].sink20OutputSink == key then
local sa = getScrollAreasForAddon(key)
options["Ace2"][addon].output.args.ScrollArea.validate = sa or emptyTable
options["Ace2"][addon].output.args.ScrollArea.disabled = not sa
options["Ace2"][addon].output.args.Sticky.disabled = not sink.stickyAddons[key]
end
return sink.storageForAddon[addon].sink20OutputSink and sink.storageForAddon[addon].sink20OutputSink == key or nil
end
end,
set = function(key, value)
if not sink.storageForAddon[addon] then return end
if key == "ScrollArea" then
sink.storageForAddon[addon].sink20ScrollArea = value
elseif key == "Sticky" then
sink.storageForAddon[addon].sink20Sticky = value
elseif value then
local sa = getScrollAreasForAddon(key)
options["Ace2"][addon].output.args.ScrollArea.validate = sa or emptyTable
options["Ace2"][addon].output.args.ScrollArea.disabled = not sa
options["Ace2"][addon].output.args.Sticky.disabled = not sink.stickyAddons[key]
sink.storageForAddon[addon].sink20OutputSink = key
end
end,
args = args["Ace2"],
disabled = function()
return (type(addon.IsActive) == "function" and not addon:IsActive()) or nil
end
}
}
return options["Ace2"][addon]
end
 
-- Ace3 options data table format
local function getAce3SinkOptions(key, opts)
local name, desc, hidden = unpack(opts)
args["Ace3"][key] = {
type = "toggle",
name = name,
desc = desc or format(L_ROUTE, name),
hidden = hidden
}
end
 
function sink.GetSinkAce3OptionsDataTable(addon)
if not options["Ace3"][addon] then
options["Ace3"][addon] = {
type = "group",
name = L_OUTPUT,
desc = L_OUTPUT_DESC,
args = args["Ace3"],
get = function(info)
local key = info[#info]
if not sink.storageForAddon[addon] then
return "Default"
end
if tostring(key) == "nil" then
-- Means AceConsole wants to list the output option,
-- so we should show which sink is currently used.
return sink.storageForAddon[addon].sink20OutputSink or L_DEFAULT
end
if key == "ScrollArea" then
return sink.storageForAddon[addon].sink20ScrollArea
elseif key == "Sticky" then
return sink.storageForAddon[addon].sink20Sticky
else
if sink.storageForAddon[addon].sink20OutputSink == key then
local sa = getScrollAreasForAddon(key)
if sa then
for k,v in ipairs(sa) do
sa[k] = nil
sa[v] = v
end
end
options["Ace3"][addon].args.ScrollArea.values = sa or emptyTable
options["Ace3"][addon].args.ScrollArea.disabled = not sa
options["Ace3"][addon].args.Sticky.disabled = not sink.stickyAddons[key]
end
return sink.storageForAddon[addon].sink20OutputSink and sink.storageForAddon[addon].sink20OutputSink == key or nil
end
end,
set = function(info, v)
local key = info[#info]
if not sink.storageForAddon[addon] then return end
if key == "ScrollArea" then
sink.storageForAddon[addon].sink20ScrollArea = v
elseif key == "Sticky" then
sink.storageForAddon[addon].sink20Sticky = v
elseif v then
local sa = getScrollAreasForAddon(key)
if sa then
for k,v in ipairs(sa) do
sa[k] = nil
sa[v] = v
end
end
options["Ace3"][addon].args.ScrollArea.values = sa or emptyTable
options["Ace3"][addon].args.ScrollArea.disabled = not sa
options["Ace3"][addon].args.Sticky.disabled = not sink.stickyAddons[key]
sink.storageForAddon[addon].sink20OutputSink = key
end
end,
disabled = function()
return (type(addon.IsEnabled) == "function" and not addon:IsEnabled()) or nil
end,
}
end
return options["Ace3"][addon]
end
 
local sinkOptionGenerators = {
["Ace2"] = getAce2SinkOptions,
["Ace3"] = getAce3SinkOptions
}
for generatorName, generator in next, sinkOptionGenerators do
options[generatorName] = options[generatorName] or {}
args[generatorName] = args[generatorName] or {}
for name, opts in next, sinks do
generator(name, opts)
end
end
 
args["Ace2"].ScrollArea = {
type = "text",
name = L_SCROLL,
desc = L_SCROLL_DESC,
validate = emptyTable,
order = -1,
disabled = true
}
args["Ace2"].Sticky = {
type = "toggle",
name = L_STICKY,
desc = L_STICKY_DESC,
validate = emptyTable,
order = -2,
disabled = true
}
 
args["Ace3"].ScrollArea = {
type = "select",
name = L_SCROLL,
desc = L_SCROLL_DESC,
values = emptyTable,
order = -1,
disabled = true
}
args["Ace3"].Sticky = {
type = "toggle",
name = L_STICKY,
desc = L_STICKY_DESC,
order = -2,
disabled = true
}
 
function sink:RegisterSink(shortName, name, desc, func, scrollAreaFunc, hasSticky)
assert(type(shortName) == "string")
assert(type(name) == "string")
assert(type(desc) == "string" or desc == nil)
assert(type(func) == "function" or type(func) == "string")
assert(type(scrollAreaFunc) == "function" or scrollAreaFunc == nil)
assert(type(hasSticky) == "boolean" or hasSticky == nil)
 
if sinks[shortName] or sink.handlers[shortName] then
error("There's already a sink by the short name %q.", shortName)
end
sinks[shortName] = {name, desc}
-- Save it for library upgrades.
if not sink.registeredSinks then sink.registeredSinks = {} end
sink.registeredSinks[shortName] = sinks[shortName]
 
if type(func) == "function" then
sink.handlers[shortName] = func
else
sink.handlers[shortName] = function(...)
self[func](self, ...)
end
end
if type(scrollAreaFunc) == "function" then
sink.registeredScrollAreaFunctions[shortName] = scrollAreaFunc
elseif type(scrollAreaFunc) == "string" then
sink.registeredScrollAreaFunctions[shortName] = function(...)
return self[scrollAreaFunc](self, ...)
end
end
sink.stickyAddons[shortName] = hasSticky and true or nil
 
for k, v in next, sinkOptionGenerators do
v(shortName, sinks[shortName])
end
end
end
 
function sink.SetSinkStorage(addon, storage)
assert(type(addon) == "table")
assert(type(storage) == "table", "Storage must be a table")
sink.storageForAddon[addon] = storage
end
 
-- Sets a sink override for -all- addons, librarywide.
function sink:SetSinkOverride(override)
assert(type(override) == "string" or override == nil)
if override and not sink.handlers[override] then
error("There's no %q sink.", override)
end
sink.override = override
end
 
-- Put this at the bottom, because we need the local functions to exist first.
local handlers = {
Parrot = parrot,
SCT = sct,
MikSBT = msbt,
ChatFrame = chat,
Channel = channel,
UIErrorsFrame = uierror,
Blizzard = blizzard,
RaidWarning = rw,
None = noop,
}
-- Overwrite any handler functions from the old library
for k, v in next, handlers do
sink.handlers[k] = v
end
 
-----------------------------------------------------------------------
-- Embed handling
 
sink.embeds = sink.embeds or {}
 
local mixins = {
"Pour", "RegisterSink", "SetSinkStorage",
"GetSinkAce2OptionsDataTable", "GetSinkAce3OptionsDataTable"
}
 
function sink:Embed(target)
sink.embeds[target] = true
for _,v in next, mixins do
target[v] = sink[v]
end
return target
end
 
for addon in next, sink.embeds do
sink:Embed(addon)
end
 
DisplacedEnergyNazi/Libs/LibSink-2.0/lib.xml New file
0,0 → 1,7
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
 
<script file="LibSink-2.0.lua"/>
 
</Ui>
 
DisplacedEnergyNazi/DisplacedEnergyNaziOptions.lua New file
0,0 → 1,78
local DisplacedEnergyNazi = DisplacedEnergyNazi
if not DisplacedEnergyNazi then return end
local DisplacedEnergyNaziLocale = DisplacedEnergyNaziLocale
if not DisplacedEnergyNaziLocale then return end
 
-----------------------------------------------------------------------------
 
local L = DisplacedEnergyNaziLocale.DisplacedEnergyNazi
if not L then return end
 
local N = L["DisplacedEnergyNazi"] .. "-" .. DisplacedEnergyNazi.version
 
-----------------------------------------------------------------------------
 
DisplacedEnergyNazi.Options =
{
handler = DisplacedEnergyNazi,
type = 'group',
args =
{
enable =
{
type = 'toggle',
width = "full",
name = L["Enable"],
desc = L["Enable DisplacedEnergyNazi"],
get = function(i) return DisplacedEnergyNazi.db.profile.enable end,
set = function(i, v) DisplacedEnergyNazi.db.profile.enable = v DisplacedEnergyNazi:Update() end,
order = 1,
},
warnAfflict =
{
type = 'toggle',
width = "full",
name = L["Displaced Energy Affliction"],
desc = L["Warn about Displaced Energy debuff affliction"],
disabled = function(i) return not DisplacedEnergyNazi.db.profile.enable end,
get = function(i) return DisplacedEnergyNazi.db.profile.warnAfflict end,
set = function(i, v) DisplacedEnergyNazi.db.profile.warnAfflict = v end,
order = 10,
},
warnDamage =
{
type = 'toggle',
width = "full",
name = L["Displaced Energy Damage"],
desc = L["Warn about Displaced Energy debuff damage"],
disabled = function(i) return not DisplacedEnergyNazi.db.profile.enable end,
get = function(i) return DisplacedEnergyNazi.db.profile.warnDamage end,
set = function(i, v) DisplacedEnergyNazi.db.profile.warnDamage = v end,
order = 11,
},
warnDispel =
{
type = 'toggle',
width = "full",
name = L["Displaced Energy Dispels"],
desc = L["Warn about Displaced Energy debuff dispels too close to the raid"],
disabled = function(i) return not DisplacedEnergyNazi.db.profile.enable end,
get = function(i) return DisplacedEnergyNazi.db.profile.warnDispel end,
set = function(i, v) DisplacedEnergyNazi.db.profile.warnDispel = v end,
order = 12,
},
whisper =
{
type = 'toggle',
width = "full",
name = L["Whisper Offending Player"],
desc = L["Whisper offending player, in addition to normal output"],
disabled = function(i) return not DisplacedEnergyNazi.db.profile.enable end,
get = function(i) return DisplacedEnergyNazi.db.profile.whisper end,
set = function(i, v) DisplacedEnergyNazi.db.profile.whisper = v end,
order = 99,
},
},
}
 
-----------------------------------------------------------------------------
DisplacedEnergyNazi/DisplacedEnergyNazi.lua
10,14 → 10,43
if not L then return end
 
-- global on purpose
DisplacedEnergyNazi = LibStub("AceAddon-3.0"):NewAddon("DisplacedEnergyNazi", "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0")
DisplacedEnergyNazi = LibStub("AceAddon-3.0"):NewAddon("DisplacedEnergyNazi", "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0", "LibSink-2.0")
 
local isConfig = false
local AceConfig = LibStub("AceConfig-3.0")
 
local isDialog = false
local AceDialog = LibStub("AceConfigDialog-3.0")
 
local isDBOpt = false
local AceDBOptions = LibStub("AceDBOptions-3.0")
 
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")
 
-----------------------------------------------------------------------------
 
DisplacedEnergyNazi.namespace = "displacedEnergyNazi"
DisplacedEnergyNazi.defaults =
{
profile =
{
enable = true,
 
warnAfflict = true,
warnDamage = true,
warnDispel = true,
 
whisper = false,
},
}
 
-----------------------------------------------------------------------------
 
local N = nil
local DisplacedEnergyNazi = DisplacedEnergyNazi
 
-- Blizzard API upvalues rather than a global lookup
local SendChatMessage = SendChatMessage
local CheckInteractDistance = CheckInteractDistance
local UnitGUID = UnitGUID
local UnitName = UnitName
60,47 → 89,102
 
-----------------------------------------------------------------------------
 
local function DeliverMessage(message)
local function BroadcastMessage(message)
if message then
DEFAULT_CHAT_FRAME:AddMessage(MESSAGE_BOILER:format(message))
-- TODO: options for where to send the message?
self:Pour(message, 1, 0, 0) -- LibSink-2.0
end
end
 
local function WhisperMessage(unitName, message)
if unitName and message then
SendChatMessage(message, "WHISPER", nil, unitName)
end
SendChatMessage(message, "WHISPER", nil, "Ransaa")
end
 
-----------------------------------------------------------------------------
 
function DisplacedEnergyNazi:OnInitialize()
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnInitialize(): enter")
 
if not N then N = L["DisplacedEnergyNazi"] .. "-" .. DisplacedEnergyNazi.version end
 
 
DisplacedEnergyNazi.DisplacedEnergyNaziDB = LibStub("AceDB-3.0"):New("DisplacedEnergyNaziDB", nil, "Default")
if not self.db or self.db ~= DisplacedEnergyNazi.DisplacedEnergyNaziDB:GetNamespace(self.namespace, true) then self.db = DisplacedEnergyNazi.DisplacedEnergyNaziDB:RegisterNamespace(self.namespace, self.defaults) end
 
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnInitialize(): exit")
end
 
function DisplacedEnergyNazi:OnEnable()
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnEnable(): enter")
 
-- configure options
if (not isConfig) then
AceConfig:RegisterOptionsTable(N, DisplacedEnergyNazi.Options, "displacedEnergyNazi")
-- ChatFrame7:AddMessage("DisplacedEnergyNazi:OnEnable(): register options " .. "'" .. tostring(N) .. "'")
isConfig = true
end
 
if (not isDialog) then
self.optionsFrame = AceDialog:AddToBlizOptions(N, "DisplacedEnergyNazi")
isDialog = true
end
 
if (not isDBOpt) then
DisplacedEnergyNazi.Options.args.profiles = AceDBOptions:GetOptionsTable(DisplacedEnergyNazi.DisplacedEnergyNaziDB)
DisplacedEnergyNazi.Options.args.profiles.order = 800
isDBOpt = true
end
 
-- configure LibSink-2.0 options
self.Options.args.output = self:GetSinkAce3OptionsDataTable()
self.Options.args.output.disabled = function(i) return not self.db.profile.enable end
 
self:SetSinkStorage(self.db.profile)
-- TODO: add an option to whisper offending players
 
PLAYER_GUID = UnitGUID("player")
self:Connect()
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnEnable(): exit")
end
 
function DisplacedEnergyNazi:OnDisable()
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnDisable(): enter")
 
self:Disconnect()
 
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnDisable(): exit")
end
 
function DisplacedEnergyNazi:Update()
mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:Update(): enter")
 
if self.db.profile.enable then
self:Connect()
else
self:Disconnect()
end
 
mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:Update(): exit")
end
 
function DisplacedEnergyNazi:Connect()
-- register event
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", "OnCombatLogEvent") -- combat log event
self:RegisterEvent("GROUP_ROSTER_UPDATE", "OnGroupRosterUpdate") -- player added/moved/removed from group
 
self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnPlayerRegenDisabled") -- combat starts
self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnPlayerRegenEnabled") -- combat ends
 
-- configure initial unit GUID -> unitid map
self:ScanFullRoster()
 
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnEnable(): exit")
end
 
function DisplacedEnergyNazi:OnDisable()
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnDisable(): enter")
 
function DisplacedEnergyNazi:Disconnect()
self:UnregisterAllEvents()
self:UnregisterAllMessages()
self:CancelAllTimers()
 
-- mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:OnDisable(): exit")
end
 
-----------------------------------------------------------------------------
121,7 → 205,10
message = L["STOP IT"] .. ": " .. originName .. " " .. L["DISPELLED Displaced Energy TOO CLOSE TO OTHERS!!!"]
 
mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:SPELL_DISPEL(): " .. MESSAGE_BOILER:format(message))
DeliverMessage(message)
if DisplacedEnergyNazi.db.profile.whisper then
WhisperMessage(originName, message)
end
BroadcastMessage(message)
end
end
 
145,6 → 232,10
local n, r = UnitName(unitid)
local fn = n .. (r and ("-" .. r)) or ""
 
if DisplacedEnergyNazi.db.profile.whisper then
WhisperMessage(fn, L["GET AWAY"] .. ": " .. fn .. " " .. L["Displaced Energy is DAMAGING OTHERS!!!"])
end
 
names = (names and (names .. ", " .. fn)) or fn
end
end
155,7 → 246,7
local message = L["GET AWAY"] .. ": " .. names .. " " .. L["Displaced Energy is DAMAGING OTHERS!!!"]
 
mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:SPELL_AURA_APPLIED(): " .. MESSAGE_BOILER:format(message))
DeliverMessage(message)
BroadcastMessage(message)
end
end
end
177,7 → 268,10
local message = L["GET AWAY"] .. ": " .. targetName .. " " .. L["AFFLICTED with Displaced Energy!!!"]
mseq = mseq + 1; ChatFrame7:AddMessage(("%08d "):format(mseq) .. "DisplacedEnergyNazi:SPELL_AURA_APPLIED(): " .. MESSAGE_BOILER:format(message))
 
DeliverMessage(message)
if DisplacedEnergyNazi.db.profile.whisper then
WhisperMessage(targetName, message)
end
BroadcastMessage(message)
end
end
 
DisplacedEnergyNazi/DisplacedEnergyNaziLocale.lua
13,6 → 13,18
 
--[[ enUS ]] L["DisplacedEnergyNazi"] = "DisplacedEnergyNazi"
 
--[[ enUS ]] L["Enable"] = "Enable"
--[[ enUS ]] L["Enable DisplacedEnergyNazi"] = "Enable DisplacedEnergyNazi"
--[[ enUS ]] L["Displaced Energy Affliction"] = "Displaced Energy Affliction"
--[[ enUS ]] L["Warn about Displaced Energy debuff affliction"] = "Warn about Displaced Energy debuff affliction"
--[[ enUS ]] L["Displaced Energy Damage"] = "Displaced Energy Damage"
--[[ enUS ]] L["Warn about Displaced Energy debuff damage"] = "Warn about Displaced Energy debuff damage"
--[[ enUS ]] L["Displaced Energy Dispels"] = "Displaced Energy Dispels"
--[[ enUS ]] L["Warn about Displaced Energy debuff dispels too close to the raid"] = "Warn about Displaced Energy debuff dispels too close to the raid"
 
--[[ enUS ]] L["Whisper Offending Player"] = "Whisper Offending Player"
--[[ enUS ]] L["Whisper offending player, in addition to normal output"] = "Whisper offending player, in addition to normal output"
 
-- combat log name of the boss
--[[ enUS ]] L["Malkorok"] = "Malkorok"
 
DisplacedEnergyNazi/Version.lua
3,7 → 3,7
 
-----------------------------------------------------------------------------
 
local MAJOR_VERSION = "0.1.0"
local MAJOR_VERSION = "0.2.0"
local MINOR_VERSION = ("$Revision$"):match("%d+")
local locale = GetLocale()