This commit is contained in:
Bunny67
2017-12-11 20:27:02 +03:00
commit de8c95c8f0
295 changed files with 57024 additions and 0 deletions
@@ -0,0 +1,7 @@
## Interface: 11200
## Title: !Compatibility
## Notes: Compatibility functions for Vanilla
## Version: 1.0
api\api.xml
debugTools.lua
+4
View File
@@ -0,0 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="wowLua.lua"/>
<Script file="wowAPI.lua"/>
</Ui>
+103
View File
@@ -0,0 +1,103 @@
--Cache global variables
local _G = getfenv()
local assert = assert
local error = error
local type = type
local unpack = unpack
local date = date
local gsub = string.gsub
function hooksecurefunc(arg1, arg2, arg3)
if type(arg1) == "string" then
arg1, arg2, arg3 = _G, arg1, arg2
end
local orig = arg1[arg2]
if type(orig) ~= "function" then
error("The function "..arg2.." does not exist", 2)
end
arg1[arg2] = function(...)
local tmp = {orig(unpack(arg))}
arg3(unpack(arg))
return unpack(tmp)
end
end
local function noop() end
function HookScript(frame, method, func)
assert(frame, "HookScript: frame argument missing")
local orig = frame:GetScript(method) or noop
frame:SetScript(method, function(...)
local tmp = {orig(unpack(arg))}
func(unpack(arg))
return unpack(tmp)
end)
end
function BetterDate(formatString, timeVal)
local dateTable = date("*t", timeVal)
local amString = (dateTable.hour >= 12) and "PM" or "AM"
--First, we'll replace %p with the appropriate AM or PM.
formatString = gsub(formatString, "^%%p", amString) --Replaces %p at the beginning of the string with the am/pm token
formatString = gsub(formatString, "([^%%])%%p", "%1"..amString) -- Replaces %p anywhere else in the string, but doesn't replace %%p (since the first % escapes the second)
return date(formatString, timeVal)
end
RAID_CLASS_COLORS = {
["HUNTER"] = {r = 0.67, g = 0.83, b = 0.45},
["WARLOCK"] = {r = 0.58, g = 0.51, b = 0.79},
["PRIEST"] = {r = 1.0, g = 1.0, b = 1.0},
["PALADIN"] = {r = 0.96, g = 0.55, b = 0.73},
["MAGE"] = {r = 0.41, g = 0.8, b = 0.94},
["ROGUE"] = {r = 1.0, g = 0.96, b = 0.41},
["DRUID"] = {r = 1.0, g = 0.49, b = 0.04},
["WARRIOR"] = {r = 0.78, g = 0.61, b = 0.43},
};
QuestDifficultyColors = {
["impossible"] = {r = 1.00, g = 0.10, b = 0.10};
["verydifficult"] = {r = 1.00, g = 0.50, b = 0.25};
["difficult"] = {r = 1.00, g = 1.00, b = 0.00};
["standard"] = {r = 0.25, g = 0.75, b = 0.25};
["trivial"] = {r = 0.50, g = 0.50, b = 0.50};
["header"] = {r = 0.70, g = 0.70, b = 0.70};
};
function GetQuestDifficultyColor(level)
local levelDiff = level - UnitLevel("player")
local color
if levelDiff >= 5 then
return QuestDifficultyColors["impossible"]
elseif levelDiff >= 3 then
return QuestDifficultyColors["verydifficult"]
elseif levelDiff >= -2 then
return QuestDifficultyColors["difficult"]
elseif -levelDiff <= GetQuestGreenRange() then
return QuestDifficultyColors["standard"]
else
return QuestDifficultyColors["trivial"]
end
end
function EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay)
if displayMode == "MENU" then
menuFrame.displayMode = displayMode
end
UIDropDownMenu_Initialize(menuFrame, EasyMenu_Initialize, displayMode)
ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList)
end
function EasyMenu_Initialize()
print(level, info)
for index = 1, getn(menuList) do
local value = menuList[index]
if value.text then
value.index = index;
UIDropDownMenu_AddButton(value, level)
end
end
end
+142
View File
@@ -0,0 +1,142 @@
--Cache global variables
local assert = assert
local error = error
local geterrorhandler = geterrorhandler
local pairs = pairs
local pcall = pcall
local tostring = tostring
local type = type
local unpack = unpack
local ceil, floor = math.ceil, math.floor
local format, gsub = string.format, string.gsub
local getn, insert = table.getn, table.insert
function select(n, ...)
assert(type(n) == "number" or type(n) == "string", "bad argument #1 to 'select' (number expected, got no value)")
if type(n) == "string" and n == "#" then
if type(arg) == "table" then
return getn(arg)
else
return 1
end
end
local temp = {}
for i = n, getn(arg) do
insert(temp, arg[i])
end
return unpack(temp)
end
function math.modf(i)
assert(type(i) == "number", "bad argument #1 to 'modf' (number expected, got no value)")
local int = i >= 0 and floor(i) or ceil(i)
return int, i - int
end
function string.join(delimiter, ...)
-- assert(type(delimiter) == "number", "bad argument #1 to 'join' (string expected, got no value)")
local size = getn(arg)
if size == 0 then
return ""
end
local text = arg[1]
for i = 2, size do
text = text..delimiter..arg[i]
end
return text
end
strjoin = string.join
function string.split(delimiter, subject)
assert(type(delimiter) == "string", "bad argument #1 to 'split' (string expected, got no value)")
local delimiter, fields = delimiter or ":", {}
local pattern = format("([^%s]+)", delimiter)
gsub(subject, pattern, function(c) fields[getn(fields) + 1] = c end)
return unpack(fields)
end
strsplit = string.split
function table.wipe(t)
assert(type(t) == "table", "bad argument #1 to 'wipe' (table expected, got no value)")
for k in pairs(t) do
t[k] = nil
end
return t
end
wipe = table.wipe
local LOCAL_ToStringAllTemp = {}
function tostringall(...)
local n = getn(arg)
-- Simple versions for common argument counts
if (n == 1) then
return tostring(arg[1])
elseif (n == 2) then
return tostring(arg[1]), tostring(arg[2])
elseif (n == 3) then
return tostring(arg[1]), tostring(arg[2]), tostring(arg[3])
elseif (n == 0) then
return
end
local needfix
for i = 1, n do
local v = arg[i]
if (type(v) ~= "string") then
needfix = i
break
end
end
if (not needfix) then return unpack(arg) end
wipe(LOCAL_ToStringAllTemp)
for i = 1, needfix - 1 do
LOCAL_ToStringAllTemp[i] = arg[i]
end
for i = needfix, n do
LOCAL_ToStringAllTemp[i] = tostring(arg[i])
end
return unpack(LOCAL_ToStringAllTemp)
end
local LOCAL_PrintHandler = function(...)
DEFAULT_CHAT_FRAME:AddMessage(strjoin(" ", tostringall(unpack(arg))))
end
function setprinthandler(func)
if (type(func) ~= "function") then
error("Invalid print handler")
else
LOCAL_PrintHandler = func
end
end
function getprinthandler() return LOCAL_PrintHandler end
local function print_inner(...)
local ok, err = pcall(LOCAL_PrintHandler, unpack(arg))
if (not ok) then
local func = geterrorhandler()
func(err)
end
end
function print(...)
pcall(print_inner, unpack(arg))
end
SLASH_PRINT1 = "/print"
SlashCmdList["PRINT"] = print
+69
View File
@@ -0,0 +1,69 @@
--Cache global variables
local strmatch = strmatch
--WoW API
local GetCVar = GetCVar
local IsAddOnLoaded = IsAddOnLoaded
local LoadAddOn = LoadAddOn
local UIParentLoadAddOn = UIParentLoadAddOn
local _ERROR_COUNT = 0
local _ERROR_LIMIT = 1000
function _ERRORMESSAGE_NEW(message)
debuginfo()
LoadAddOn("!DebugTools")
local loaded = IsAddOnLoaded("!DebugTools")
-- if (GetCVar("scriptErrors") == 1) then
if (not loaded or DEBUG_DEBUGTOOLS) then
ScriptErrors_Message:SetText(message)
ScriptErrors:Show()
if (DEBUG_DEBUGTOOLS) then
ScriptErrorsFrame_OnError(message)
end
else
ScriptErrorsFrame_OnError(message)
end
-- elseif (loaded) then
-- ScriptErrorsFrame_OnError(message, true)
-- end
_ERROR_COUNT = _ERROR_COUNT + 1
if (_ERROR_COUNT == _ERROR_LIMIT) then
StaticPopup_Show("TOO_MANY_LUA_ERRORS")
end
return message
end
seterrorhandler(_ERRORMESSAGE_NEW)
function message(text)
if (not ScriptErrors:IsShown()) then
ScriptErrors_Message:SetText(text)
ScriptErrors:Show()
end
end
SLASH_FRAMESTACK1 = "/framestack"
SLASH_FRAMESTACK2 = "/fstack"
SlashCmdList["FRAMESTACK"] = function(msg)
UIParentLoadAddOn("!DebugTools")
FrameStackTooltip_Toggle(showHidden)
end
SLASH_EVENTTRACE1 = "/eventtrace"
SLASH_EVENTTRACE2 = "/etrace"
SlashCmdList["EVENTTRACE"] = function(msg)
UIParentLoadAddOn("!DebugTools")
EventTraceFrame_HandleSlashCmd(msg)
end
SLASH_DUMP1 = "/dump"
SlashCmdList["DUMP"] = function(msg)
UIParentLoadAddOn("!DebugTools")
DevTools_DumpCommand(msg)
end
+12
View File
@@ -0,0 +1,12 @@
## Interface: 20400
## Title: !DebugTools
## Notes: Tools for developing addons (Blizzard UI Debug Tools)
## Author: Blizzard Entertainment
## Special Thanks: Iriel, Kirov, Esamynn
## Version: 1.0
## Dependencies: !Compatibility
Compatibility.lua
Dump.lua
Blizzard_DebugTools.lua
Blizzard_DebugTools.xml
@@ -0,0 +1,729 @@
local _G = getfenv()
EVENT_TRACE_EVENT_HEIGHT = 16;
EVENT_TRACE_MAX_ENTRIES = 1000;
DEBUGLOCALS_LEVEL = 4;
local _normalFontColor = {1, .82, 0, 1};
EVENT_TRACE_SYSTEM_TIMES = {};
EVENT_TRACE_SYSTEM_TIMES["System"] = true;
EVENT_TRACE_SYSTEM_TIMES["Elapsed"] = true;
EVENT_TRACE_EVENT_COLORS = {};
EVENT_TRACE_EVENT_COLORS["System"] = _normalFontColor;
EVENT_TRACE_EVENT_COLORS["Elapsed"] = {.6, .6, .6, 1};
local _EventTraceFrame;
local _framesSinceLast = 0;
local _timeSinceLast = 0;
local _timer = CreateFrame("FRAME");
_timer:SetScript("OnUpdate", function () _framesSinceLast = _framesSinceLast + 1; _timeSinceLast = _timeSinceLast + arg1; end);
function EventTraceFrame_OnLoad(self)
local frameName = self:GetName()
_G[frameName.."Scroll"].thumb = _G[frameName.."ScrollThumb"]
_G[frameName.."DialogBG"]:SetVertexColor(0, 0, 0)
_G[frameName.."DialogBG"]:SetAlpha(0.75)
self.buttons = {};
self.events = {};
self.times = {};
self.rawtimes = {};
self.eventids = {};
self.eventtimes = {};
self.numhandlers = {};
self.slowesthandlers = {};
self.slowesthandlertimes = {}
self.timeSinceLast = {};
self.framesSinceLast = {};
self.args = {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
self.ignoredEvents = {};
self.lastIndex = 0;
self.visibleButtons = 0;
_EventTraceFrame = self;
self:SetScript("OnSizeChanged", function() EventTraceFrame_OnSizeChanged(this, arg1, arg2) end);
EventTraceFrame_OnSizeChanged(self, self:GetWidth(), self:GetHeight());
self:EnableMouse(true);
self:EnableMouseWheel(true);
self:SetScript("OnMouseWheel", function() EventTraceFrame_OnMouseWheel(tris, arg1) end);
end
local _workTable = {};
function EventTraceFrame_OnEvent (self, event, ...)
if (not self.ignoredEvents[event]) then
if (_framesSinceLast ~= 0 and event ~= "On Update") then
EventTraceFrame_OnEvent(self, "On Update");
end
local nextIndex = self.lastIndex + 1;
if (nextIndex > EVENT_TRACE_MAX_ENTRIES) then
local staleIndex = nextIndex - EVENT_TRACE_MAX_ENTRIES;
self.events[staleIndex] = nil;
self.times[staleIndex] = nil;
self.rawtimes[staleIndex] = nil;
self.timeSinceLast[staleIndex] = nil;
self.framesSinceLast[staleIndex] = nil;
self.eventids[staleIndex] = nil;
self.eventtimes[staleIndex] = nil;
self.numhandlers[staleIndex] = nil;
self.slowesthandlers[staleIndex] = nil;
self.slowesthandlertimes[staleIndex] = nil;
for k, v in next, self.args do
self.args[k][staleIndex] = nil;
end
end
if (event == "Begin Capture" or event == "End Capture") then
self.times[nextIndex] = "System";
if (self.eventsToCapture) then
self.events[nextIndex] = string.format("%s (%s events)", event, tostring(self.eventsToCapture));
else
self.events[nextIndex] = event;
end
self.timeSinceLast[nextIndex] = 0;
self.framesSinceLast[nextIndex] = 0;
elseif (event == "On Update") then
self.times[nextIndex] = "Elapsed";
self.events[nextIndex] = string.format("%.3f sec - %d frame(s)", _timeSinceLast, _framesSinceLast);
self.timeSinceLast[nextIndex] = _timeSinceLast;
self.framesSinceLast[nextIndex] = _framesSinceLast;
_timeSinceLast = 0;
_framesSinceLast = 0;
else
self.events[nextIndex] = event;
local seconds = GetTime();
local minutes = math.floor(math.floor(seconds) / 60);
local hours = math.floor(minutes / 60);
seconds = seconds - 60 * minutes;
minutes = minutes - 60 * hours;
hours = math.mod(hours, 1000);
self.times[nextIndex] = string.format("%.2d:%.2d:%06.3f", hours, minutes, seconds);
self.timeSinceLast[nextIndex] = 0;
self.framesSinceLast[nextIndex] = 0;
self.eventids[nextIndex] = GetCurrentEventID();
local numArgs = select("#", unpack(arg));
for i=1, numArgs do
if (not self.args[i]) then
self.args[i] = {};
end
self.args[i][nextIndex] = select(i, unpack(arg));
end
if (self.eventsToCapture) then
self.eventsToCapture = self.eventsToCapture - 1;
end
end
self.rawtimes[nextIndex] = GetTime();
self.lastIndex = nextIndex;
if (self.eventsToCapture and self.eventsToCapture <= 0) then
self.eventsToCapture = nil;
EventTraceFrame_StopEventCapture();
end
end
end
function EventTraceFrame_OnShow()
wipe(this.ignoredEvents);
local scrollBar = _G["EventTraceFrameScroll"];
local minValue, maxValue = scrollBar:GetMinMaxValues();
scrollBar:SetValue(maxValue);
end
function EventTraceFrame_OnUpdate ()
EventTraceFrame_Update();
end
function EventTraceFrame_OnSizeChanged (self, width, height)
local numButtonsToDisplay = math.floor((height - 36)/EVENT_TRACE_EVENT_HEIGHT);
local numButtonsCreated = getn(self.buttons)
if (numButtonsCreated < numButtonsToDisplay) then
for i = numButtonsCreated + 1, numButtonsToDisplay do
local button = CreateFrame("BUTTON", "EventTraceFrameButton" .. i, self, "EventTraceEventTemplate");
button:SetPoint("BOTTOMLEFT", 12, (16 * (i - 1)) + 12);
button:SetPoint("RIGHT", -28, 0);
tinsert(self.buttons, button);
end
for i = self.visibleButtons + 1, numButtonsToDisplay do
self.buttons[i]:Show();
end
self.visibleButtons = numButtonsToDisplay;
EventTraceFrame_Update();
elseif (self.visibleButtons < numButtonsToDisplay) then
for i = self.visibleButtons + 1, numButtonsToDisplay do
self.buttons[i]:Show();
end
self.visibleButtons = numButtonsToDisplay;
EventTraceFrame_Update();
elseif (numButtonsToDisplay < self.visibleButtons) then
for i = numButtonsToDisplay + 1, self.visibleButtons do
-- self.buttons[i]:Hide();
end
self.visibleButtons = numButtonsToDisplay;
end
end
function EventTraceFrame_Update ()
local offset = 0;
local scrollBar = _G["EventTraceFrameScroll"];
local scrollBarValue = scrollBar:GetValue();
local minValue, maxValue = scrollBar:GetMinMaxValues();
local firstID = max(1, _EventTraceFrame.lastIndex - EVENT_TRACE_MAX_ENTRIES + 1);
local lastID = _EventTraceFrame.lastIndex or 1;
if (firstID >= lastID) then
scrollBar:SetMinMaxValues(firstID-1, lastID);
else
scrollBar:SetMinMaxValues(firstID, lastID);
end
if (scrollBarValue < firstID) then
scrollBar:SetValue(firstID);
scrollBarValue = firstID;
end
if (scrollBarValue < 1) then
scrollBarValue = 1;
elseif (not _EventTraceFrame.selectedEvent) then
if (scrollBarValue == maxValue) then
scrollBar:SetValue(_EventTraceFrame.lastIndex);
end
end
for i = 1, _EventTraceFrame.visibleButtons do
local button = _EventTraceFrame.buttons[i];
if (button) then
local index = scrollBarValue - (i - 1);
local event = _EventTraceFrame.events[index];
if (event) then
local timeString = _EventTraceFrame.times[index]
button.index = index;
button.time:SetText(timeString);
button.event:SetText(event);
if (_EventTraceFrame.eventids[index] and not _EventTraceFrame.eventtimes[index]) then
local eventTime, numHandlers, slowestHandler, slowestHandlerTime = GetEventTime(_EventTraceFrame.eventids[index]);
_EventTraceFrame.eventtimes[index] = eventTime;
_EventTraceFrame.numhandlers[index] = numHandlers;
_EventTraceFrame.slowesthandlers[index] = slowestHandler;
_EventTraceFrame.slowesthandlertimes[index] = slowestHandlerTime;
end
local color = EVENT_TRACE_EVENT_COLORS[event] or EVENT_TRACE_EVENT_COLORS[timeString];
if (color) then
button.time:SetTextColor(unpack(color));
button.event:SetTextColor(unpack(color));
else
local eventTime = _EventTraceFrame.eventtimes[index];
if (eventTime and eventTime > 50.0) then
button.time:SetTextColor(1, 0, 0, 1);
button.event:SetTextColor(1, 0, 0, 1);
elseif (eventTime and eventTime > 20.0) then
button.time:SetTextColor(1, .5, 0, 1);
button.event:SetTextColor(1, .5, 0, 1);
elseif (eventTime and eventTime > 10.0) then
button.time:SetTextColor(1, .8, 0, 1);
button.event:SetTextColor(1, .8, 0, 1);
elseif (eventTime and eventTime > 5.0) then
button.time:SetTextColor(1, 1, .6, 1);
button.event:SetTextColor(1, 1, .6, 1);
else
button.time:SetTextColor(1, 1, 1, 1);
button.event:SetTextColor(1, 1, 1, 1);
end
end
button:Show();
if (_EventTraceFrame.selectedEvent) then
if (index == _EventTraceFrame.selectedEvent) then
EventTraceFrameEvent_DisplayTooltip(button);
button:GetHighlightTexture():SetVertexColor(.15, .25, 1, .35);
button:LockHighlight(true);
button.wasSelected = true;
elseif (button.wasSelected) then
button.wasSelected = nil;
button:GetHighlightTexture():SetVertexColor(.8, .8, 1, .15);
button:UnlockHighlight();
end
else
if (button.wasSelected) then
button.wasSelected = nil;
button:GetHighlightTexture():SetVertexColor(.8, .8, 1, .15);
button:UnlockHighlight();
end
end
if (button == GetMouseFocus()) then
EventTraceFrameEvent_OnEnter(button);
else
button.HideButton:Hide();
end
else
button.index = index;
button:Hide();
end
end
end
EventTraceFrame_UpdateKeyboardStatus();
end
function EventTraceFrame_StartEventCapture()
if (_EventTraceFrame.started) then
return;
end
EventHandler_Enable()
_EventTraceFrame.started = true;
_framesSinceLast = 0;
_timeSinceLast = 0;
_EventTraceFrame:RegisterAllEvents();
EventTraceFrame_OnEvent(_EventTraceFrame, "Begin Capture");
end
function EventTraceFrame_StopEventCapture()
if (not _EventTraceFrame.started) then
return;
end
EventHandler_Disable()
_EventTraceFrame.started = false;
_framesSinceLast = 0;
_timeSinceLast = 0;
_EventTraceFrame:UnregisterAllEvents();
EventTraceFrame_OnEvent(_EventTraceFrame, "End Capture");
end
function EventTraceFrame_HandleSlashCmd(msg)
msg = strlower(msg);
if (msg == "start") then
EventTraceFrame_StartEventCapture();
elseif (msg == "stop") then
EventTraceFrame_StopEventCapture();
elseif (tonumber(msg) and tonumber(msg) > 0) then
if (not _EventTraceFrame.started) then
_EventTraceFrame.eventsToCapture = tonumber(msg);
EventTraceFrame_StartEventCapture();
end
elseif (msg == "") then
if (not _EventTraceFrame:IsShown()) then
_EventTraceFrame:Show();
if (_EventTraceFrame.started == nil) then
EventTraceFrame_StartEventCapture();
end
else
_EventTraceFrame:Hide();
end
end
end
function EventTraceFrame_OnMouseWheel(self, delta)
local scrollBar = _G["EventTraceFrameScroll"];
local minVal, maxVal = scrollBar:GetMinMaxValues();
local currentValue = scrollBar:GetValue();
local newValue = currentValue - (delta * 3);
newValue = max(newValue, minVal);
newValue = min(newValue, maxVal);
if (newValue ~= currentValue) then
scrollBar:SetValue(newValue);
end
end
function EventTraceFrame_UpdateKeyboardStatus()
if (_EventTraceFrame.selectedEvent) then
local focus = GetMouseFocus();
if (focus == _EventTraceFrame or (focus and focus:GetParent() == _EventTraceFrame)) then
_EventTraceFrame:EnableKeyboard(true);
return;
end
end
_EventTraceFrame:EnableKeyboard(false);
end
function EventTraceFrame_OnKeyUp(self, key)
if (key == "ESCAPE") then
self.selectedEvent = nil;
EventTraceTooltip:Hide();
EventTraceFrame_Update();
end
end
function EventTraceFrame_RemoveEvent(i)
if (i >= 1 and i <= EventTraceFrame.lastIndex) then
tremove(EventTraceFrame.events, i);
tremove(EventTraceFrame.times, i);
tremove(EventTraceFrame.rawtimes, i);
tremove(EventTraceFrame.timeSinceLast, i);
tremove(EventTraceFrame.framesSinceLast, i);
tremove(EventTraceFrame.eventtimes, i);
tremove(EventTraceFrame.eventids, i);
tremove(EventTraceFrame.numhandlers, i);
tremove(EventTraceFrame.slowesthandlers, i);
tremove(EventTraceFrame.slowesthandlertimes, i);
for k, v in next, EventTraceFrame.args do
for j = i, EventTraceFrame.lastIndex do
EventTraceFrame.args[k][j] = EventTraceFrame.args[k][j+1];
end
end
EventTraceFrame.lastIndex = EventTraceFrame.lastIndex-1;
end
end
local TIME_LABEL = "Time:";
local DETAILS_LABEL = "Details:";
local SLOWEST_LABEL = "Slowest:";
local ARGUMENT_LABEL_FORMAT = "arg %d:";
local NUM_HANDLERS_FORMAT = "(%d handlers)";
local EVENT_TIME_FORMAT = "%.2fms";
local function EventTrace_FormatArgValue (val)
if (type(val) == "string") then
return string.format('"%s"', val);
elseif (type(val) == "number") then
return tostring(val);
elseif (type(val) == "boolean") then
return string.format('|cffaaaaff%s|r', tostring(val));
elseif (type(val) == "table" or type(val) == "bool") then
return string.format('|cffffaaaa%s|r', tostring(val));
end
end
function EventTraceFrameEvent_DisplayTooltip (eventButton)
local index = eventButton.index;
if (not index) then
return;
end
local tooltip = _G["EventTraceTooltip"];
tooltip:SetOwner(eventButton, "ANCHOR_NONE");
tooltip:SetPoint("TOPLEFT", eventButton, "TOPRIGHT", 24, 2);
local timeString = _EventTraceFrame.times[index]
if (EVENT_TRACE_SYSTEM_TIMES[timeString]) then
tooltip:AddLine(timeString, 1, 1, 1);
tooltip:AddDoubleLine(TIME_LABEL, _EventTraceFrame.rawtimes[index], 1, .82, 0, 1, 1, 1);
tooltip:AddDoubleLine(DETAILS_LABEL, _EventTraceFrame.events[index], 1, .82, 0, 1, 1, 1);
else
tooltip:AddLine(_EventTraceFrame.events[index], 1, 1, 1);
local eventTime = _EventTraceFrame.eventtimes[index];
if (eventTime) then
if (eventTime < 0) then
eventTime = "?";
else
eventTime = format(EVENT_TIME_FORMAT, eventTime);
end
tooltip:AddDoubleLine(TIME_LABEL, eventTime .. " " .. format(NUM_HANDLERS_FORMAT, _EventTraceFrame.numhandlers[index] or 0), 1, .82, 0, 1, 1, 1);
else
tooltip:AddDoubleLine(TIME_LABEL, _EventTraceFrame.rawtimes[index], 1, .82, 0, 1, 1, 1);
end
if (_EventTraceFrame.slowesthandlers[index]) then
tooltip:AddDoubleLine(SLOWEST_LABEL, format("%s (%.2fms)", _EventTraceFrame.slowesthandlers[index], _EventTraceFrame.slowesthandlertimes[index]), 1, .82, 0, 1, 1, 1);
end
for k, v in ipairs(EventTraceFrame.args) do
if (v[index]) then
tooltip:AddDoubleLine(format(ARGUMENT_LABEL_FORMAT, k), EventTrace_FormatArgValue(v[index]), 1, .82, 0, 1, 1, 1);
end
end
end
tooltip:Show();
end
function EventTraceFrameEvent_OnEnter (self)
if (not EVENT_TRACE_SYSTEM_TIMES[EventTraceFrame.times[self.index]]) then
self.HideButton:Show();
else
self.HideButton:Hide();
end
if (_EventTraceFrame.selectedEvent) then
return;
else
EventTraceFrameEvent_DisplayTooltip(self);
end
end
function EventTraceFrameEvent_OnLeave (self)
if (not self.HideButton == GetMouseFocus()) then
self.HideButton:Hide();
end
if (not _EventTraceFrame.selectedEvent) then
EventTraceTooltip:Hide();
end
end
function EventTraceFrameEvent_OnClick (self)
if (_EventTraceFrame.selectedEvent == self.index) then
_EventTraceFrame.selectedEvent = nil;
else
_EventTraceFrame.selectedEvent = self.index;
end
EventTraceFrame_Update();
end
function EventTraceFrameEventHideButton_OnClick (button)
local eventName = button:GetParent().event:GetText();
EventTraceFrame.ignoredEvents[eventName] = 1;
EventTraceFrame.selectedEvent = nil;
for i = EventTraceFrame.lastIndex, 1, -1 do
if (EventTraceFrame.events[i] == eventName) then
EventTraceFrame_RemoveEvent(i);
end
end
local lastWasElapsed = false;
for i = EventTraceFrame.lastIndex, 1, -1 do
if (EventTraceFrame.times[i] == "Elapsed") then
if (lastWasElapsed) then
EventTraceFrame.timeSinceLast[i] = EventTraceFrame.timeSinceLast[i] + EventTraceFrame.timeSinceLast[i+1];
EventTraceFrame.framesSinceLast[i] = EventTraceFrame.framesSinceLast[i] + EventTraceFrame.framesSinceLast[i+1];
EventTraceFrame.events[i] = string.format(string.format("%.3f sec", EventTraceFrame.timeSinceLast[i]) .. " - %d frame(s)", EventTraceFrame.framesSinceLast[i]);
EventTraceFrame_RemoveEvent(i+1);
end
lastWasElapsed = true;
else
lastWasElapsed = false;
end
end
EventTraceFrame_Update();
end
local ERROR_FORMAT = "|cffffd200Message:|r|cffffffff %s|r\n|cffffd200Time:|r|cffffffff %s|r\n|cffffd200Count:|r|cffffffff %s|r\n|cffffd200Stack:|r|cffffffff %s|r";
local WARNING_AS_ERROR_FORMAT = "|cffffd200Message:|r|cffffffff %s|r\n|cffffd200Time:|r|cffffffff %s|r\n|cffffd200Count:|r|cffffffff %s|r";
local WARNING_FORMAT = "Lua Warning:\n"..WARNING_AS_ERROR_FORMAT;
local INDEX_ORDER_FORMAT = "%d / %d"
local _ScriptErrorsFrame;
function ScriptErrorsFrame_OnLoad (self)
local frameName = self:GetName()
self.title = _G[frameName.."Title"]
self.indexLabel = _G[frameName.."IndexLabel"]
self.reload = _G[frameName.."Reload"]
self.previous = _G[frameName.."Previous"]
self.next = _G[frameName.."Next"]
self.close = _G[frameName.."CloseButton"]
self.title:SetText(LUA_ERROR);
self:RegisterForDrag("LeftButton");
self.seen = {};
self.order = {};
self.count = {};
self.messages = {};
self.times = {};
_ScriptErrorsFrame = self;
end
function ScriptErrorsFrame_OnShow (self)
ScriptErrorsFrame_Update();
end
function ScriptErrorsFrame_OnError (message, keepHidden)
local stack = debugstack(DEBUGLOCALS_LEVEL);
local messageStack = message..stack;
if (_ScriptErrorsFrame) then
local index = _ScriptErrorsFrame.seen[messageStack];
if (index) then
_ScriptErrorsFrame.count[index] = _ScriptErrorsFrame.count[index] + 1;
_ScriptErrorsFrame.messages[index] = message;
_ScriptErrorsFrame.times[index] = date();
else
tinsert(_ScriptErrorsFrame.order, stack);
index = getn(_ScriptErrorsFrame.order);
_ScriptErrorsFrame.count[index] = 1;
_ScriptErrorsFrame.messages[index] = message;
_ScriptErrorsFrame.times[index] = date();
_ScriptErrorsFrame.seen[messageStack] = index;
end
if (not _ScriptErrorsFrame:IsShown() and not keepHidden) then
_ScriptErrorsFrame.index = index;
_ScriptErrorsFrame:Show();
else
ScriptErrorsFrame_Update();
end
end
end
function ScriptErrorsFrame_Update ()
local editBox = ScriptErrorsFrameScrollFrameText;
local index = _ScriptErrorsFrame.index;
if (not index or not _ScriptErrorsFrame.order[index]) then
index = getn(_ScriptErrorsFrame.order);
_ScriptErrorsFrame.index = index;
end
if (index == 0) then
editBox:SetText("");
ScriptErrorsFrame_UpdateButtons();
return;
end
local text = string.format(
ERROR_FORMAT,
_ScriptErrorsFrame.messages[index],
_ScriptErrorsFrame.times[index],
_ScriptErrorsFrame.count[index],
_ScriptErrorsFrame.order[index]
);
local parent = editBox:GetParent();
local prevText = editBox.text;
editBox.text = text;
if (prevText ~= text) then
editBox:SetText(text);
editBox:HighlightText(0);
--editBox:SetCursorPosition(0);
else
ScriptErrorsFrameScrollFrame:UpdateScrollChildRect();
end
parent:SetVerticalScroll(0);
ScriptErrorsFrame_UpdateButtons();
end
function ScriptErrorsFrame_UpdateButtons ()
local index = _ScriptErrorsFrame.index;
local numErrors = getn(_ScriptErrorsFrame.order);
if (index == 0) then
_ScriptErrorsFrame.next:Disable();
_ScriptErrorsFrame.previous:Disable();
else
if (numErrors == 1) then
_ScriptErrorsFrame.next:Disable();
_ScriptErrorsFrame.previous:Disable();
elseif (index == 1) then
_ScriptErrorsFrame.next:Enable();
_ScriptErrorsFrame.previous:Disable();
elseif (index == numErrors) then
_ScriptErrorsFrame.next:Disable();
_ScriptErrorsFrame.previous:Enable();
else
_ScriptErrorsFrame.next:Enable();
_ScriptErrorsFrame.previous:Enable();
end
end
_ScriptErrorsFrame.indexLabel:SetText(string.format(INDEX_ORDER_FORMAT, index, numErrors));
end
function ScriptErrorsFrame_DeleteError (index)
if (_ScriptErrorsFrame.order[index]) then
_ScriptErrorsFrame.seen[_ScriptErrorsFrame.messages[index] .. _ScriptErrorsFrame.order[index]] = nil;
tremove(_ScriptErrorsFrame.order, index);
tremove(_ScriptErrorsFrame.messages, index);
tremove(_ScriptErrorsFrame.times, index);
tremove(_ScriptErrorsFrame.count, index);
end
end
function ScriptErrorsFrameButton_OnClick (self)
local id = self:GetID();
if (id == 1) then
_ScriptErrorsFrame.index = _ScriptErrorsFrame.index + 1;
else
_ScriptErrorsFrame.index = _ScriptErrorsFrame.index - 1;
end
ScriptErrorsFrame_Update();
end
function DebugTooltip_OnLoad(self)
self:SetFrameLevel(self:GetFrameLevel() + 2)
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
self.statusBar2 = getglobal(self:GetName().."StatusBar2")
self.statusBar2Text = getglobal(self:GetName().."StatusBar2Text")
end
function FrameStackTooltip_OnDisplaySizeChanged(self)
local height = GetScreenHeight()
if (height > 768) then
self:SetScale(768 / height)
else
self:SetScale(1)
end
end
function FrameStackTooltip_OnLoad(self)
DebugTooltip_OnLoad(self)
FrameStackTooltip_OnDisplaySizeChanged(self)
self:RegisterEvent("DISPLAY_SIZE_CHANGED")
end
function FrameStackTooltip_OnEvent(self, event, ...)
if (event == "DISPLAY_SIZE_CHANGED") then
FrameStackTooltip_OnDisplaySizeChanged(self)
end
end
function FrameStackTooltip_Toggle(showHidden)
local tooltip = _G["FrameStackTooltip"]
if (tooltip:IsVisible()) then
tooltip:Hide()
FrameStackHighlight:Hide()
else
tooltip:SetOwner(UIParent, "ANCHOR_NONE")
tooltip:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -CONTAINER_OFFSET_X - 13, CONTAINER_OFFSET_Y)
tooltip.default = 1
tooltip.showHidden = showHidden
UpdateFrameStack(tooltip, showHidden)
end
end
FRAMESTACK_UPDATE_TIME = .1
local _timeSinceLast = 0
function FrameStackTooltip_OnUpdate(self, elapsed)
_timeSinceLast = _timeSinceLast - elapsed
if (_timeSinceLast <= 0) then
_timeSinceLast = FRAMESTACK_UPDATE_TIME
local highlightFrame = UpdateFrameStack(self, self.showHidden)
FrameStackHighlight:ClearAllPoints();
if (highlightFrame) then
FrameStackHighlight:SetPoint("BOTTOMLEFT", highlightFrame);
FrameStackHighlight:SetPoint("TOPRIGHT", highlightFrame);
FrameStackHighlight:Show();
else
FrameStackHighlight:Hide();
end
end
end
function FrameStackTooltip_OnShow(self)
local parent = self:GetParent() or UIParent
local ps = parent:GetEffectiveScale()
local px, py = parent:GetCenter()
px, py = px * ps, py * ps
local x, y = GetCursorPosition()
self:ClearAllPoints()
if (x > px) then
if (y > py) then
self:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 20, 20)
else
self:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -20)
end
else
if (y > py) then
self:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -20, 20)
else
self:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -20, -20)
end
end
end
FrameStackTooltip_OnEnter = FrameStackTooltip_OnShow
@@ -0,0 +1,568 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Font name="GameFontHighlightSmall" inherits="GameFontNormalSmall" virtual="true">
<Color r="1.0" g="1.0" b="1.0"/>
</Font>
<Font name="GameFontHighlightSmallLeft" inherits="GameFontHighlightSmall" justifyH="LEFT" virtual="true"/>
<Font name="GameFontNormalCenter" inherits="GameFontNormal" justifyH="CENTER" virtual="true"/>
<FontString name="EventTraceTimeFont" font="fonts\arialn.ttf" justifyH="RIGHT" virtual="true">
<FontHeight val="10"/>
<Color r="1" g="1" b="1" a="1"/>
</FontString>
<Button name="EventTraceEventTemplate" virtual="true">
<Size x="0" y="16"/>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentTime" inherits="EventTraceTimeFont">
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="TOPRIGHT" relativePoint="TOPLEFT">
<Offset x="72" y="0"/>
</Anchor>
<Anchor point="BOTTOM"/>
</Anchors>
</FontString>
<FontString name="$parentEvent" inherits="GameFontHighlightSmallLeft">
<Anchors>
<Anchor point="TOPRIGHT"/>
<Anchor point="TOPLEFT">
<Offset x="80" y="0"/>
</Anchor>
<Anchor point="BOTTOM"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Button name="$parentHideButton" hidden="true">
<Size x="16" y="8"/>
<Anchors>
<Anchor point="LEFT"/>
</Anchors>
<Scripts>
<OnClick>
EventTraceFrameEventHideButton_OnClick(this);
</OnClick>
<OnLeave>
EventTraceFrameEvent_OnLeave(this:GetParent());
</OnLeave>
</Scripts>
<ButtonText text="X" inherits="GameFontRedSmall">
<Anchors>
<Anchor point="LEFT"/>
</Anchors>
</ButtonText>
</Button>
</Frames>
<Scripts>
<OnLoad>
local frameName = this:GetName();
this.time = getglobal(frameName.."Time");
this.event = getglobal(frameName.."Event");
this.HideButton = getglobal(frameName.."HideButton");
this:GetHighlightTexture():SetAlpha(.15);
</OnLoad>
<OnEnter>
EventTraceFrameEvent_OnEnter(this);
</OnEnter>
<OnLeave>
EventTraceFrameEvent_OnLeave(this);
</OnLeave>
<OnClick>
EventTraceFrameEvent_OnClick(this);
</OnClick>
</Scripts>
<HighlightTexture setAllPoints="true" alphaMode="ADD">
<Color r=".8" g=".8" b="1" a="1"/>
</HighlightTexture>
</Button>
<Frame name="UIPanelDialogTemplate" virtual="true">
<Layers>
<Layer level="OVERLAY">
<Texture name="$parentTopLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="TOPLEFT"/>
</Anchors>
<TexCoords left="0.501953125" right="0.625" top="0" bottom="1"/>
</Texture>
<Texture name="$parentTopRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="TOPRIGHT"/>
</Anchors>
<TexCoords left="0.625" right="0.75" top="0" bottom="1"/>
</Texture>
<Texture name="$parentTop" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="0" y="64"/>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTopLeft" relativePoint="TOPRIGHT"/>
<Anchor point="TOPRIGHT" relativeTo="$parentTopRight" relativePoint="TOPLEFT"/>
</Anchors>
<TexCoords left="0.25" right="0.369140625" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottomLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="BOTTOMLEFT"/>
</Anchors>
<TexCoords left="0.751953125" right="0.875" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottomRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
<TexCoords left="0.875" right="1" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottom" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="0" y="64"/>
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBottomLeft" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottomRight" relativePoint="BOTTOMLEFT"/>
</Anchors>
<TexCoords left="0.376953125" right="0.498046875" top="0" bottom="1"/>
</Texture>
<Texture name="$parentLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="0"/>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTopLeft" relativePoint="BOTTOMLEFT"/>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBottomLeft" relativePoint="TOPLEFT"/>
</Anchors>
<TexCoords left="0.001953125" right="0.125" top="0" bottom="1"/>
</Texture>
<Texture name="$parentRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="0"/>
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parentTopRight" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottomRight" relativePoint="TOPRIGHT"/>
</Anchors>
<TexCoords left="0.1171875" right="0.2421875" top="0" bottom="1"/>
</Texture>
</Layer>
<Layer level="BACKGROUND">
<Texture name="$parentTitleBG" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Title-Background">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="8" y="-7"/>
</Anchor>
<Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT">
<Offset x="-8" y="-24"/>
</Anchor>
</Anchors>
</Texture>
<Texture name="$parentDialogBG" file="Interface\PaperDollInfoFrame\UI-Character-CharacterTab-L1">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="8" y="-24"/>
</Anchor>
<Anchor point="BOTTOMRIGHT">
<Offset x="-6" y="8"/>
</Anchor>
</Anchors>
<TexCoords left="0.255" right="1" top="0.29" bottom="1"/>
</Texture>
</Layer>
<Layer level="OVERLAY">
<FontString name="$parentTitle" inherits="GameFontNormal">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="12" y="-8"/>
</Anchor>
<Anchor point="TOPRIGHT">
<Offset x="-32" y="-24"/>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Button name="$parentClose" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT">
<Offset x="2" y="1"/>
</Anchor>
</Anchors>
</Button>
</Frames>
</Frame>
<Frame name="EventTraceFrame" parent="UIParent" movable="true" enableMouse="true" clampedToScreen="true" hidden="true" frameStrata="MEDIUM" toplevel="true">
<Size x="326" y="505"/>
<Anchors>
<Anchor point="LEFT">
<Offset x="64" y="0"/>
</Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentTitleBG" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Title-Background">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="9" y="-6"/>
</Anchor>
<Anchor point="BOTTOMRIGHT" relativePoint="TOPRIGHT">
<Offset x="-28" y="-24"/>
</Anchor>
</Anchors>
</Texture>
<Texture name="$parentDialogBG" file="Interface\Tooltips\UI-Tooltip-Background">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="8" y="-24"/>
</Anchor>
<Anchor point="BOTTOMRIGHT">
<Offset x="-6" y="8"/>
</Anchor>
</Anchors>
<Color r="0" g="0" b="0" a=".75"/>
</Texture>
</Layer>
<Layer level="BORDER">
<Texture name="$parentTopLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="TOPLEFT"/>
</Anchors>
<TexCoords left="0.501953125" right="0.625" top="0" bottom="1"/>
</Texture>
<Texture name="$parentTopRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="TOPRIGHT"/>
</Anchors>
<TexCoords left="0.625" right="0.75" top="0" bottom="1"/>
</Texture>
<Texture name="$parentTop" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="0" y="64"/>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTopLeft" relativePoint="TOPRIGHT"/>
<Anchor point="TOPRIGHT" relativeTo="$parentTopRight" relativePoint="TOPLEFT"/>
</Anchors>
<TexCoords left="0.25" right="0.369140625" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottomLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="BOTTOMLEFT"/>
</Anchors>
<TexCoords left="0.751953125" right="0.875" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottomRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="64"/>
<Anchors>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
<TexCoords left="0.875" right="1" top="0" bottom="1"/>
</Texture>
<Texture name="$parentBottom" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="0" y="64"/>
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBottomLeft" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottomRight" relativePoint="BOTTOMLEFT"/>
</Anchors>
<TexCoords left="0.376953125" right="0.498046875" top="0" bottom="1"/>
</Texture>
<Texture name="$parentLeft" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="0"/>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTopLeft" relativePoint="BOTTOMLEFT"/>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBottomLeft" relativePoint="TOPLEFT"/>
</Anchors>
<TexCoords left="0.001953125" right="0.125" top="0" bottom="1"/>
</Texture>
<Texture name="$parentRight" file="Interface\AddOns\!DebugTools\media\UI-GearManager-Border">
<Size x="64" y="0"/>
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parentTopRight" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottomRight" relativePoint="TOPRIGHT"/>
</Anchors>
<TexCoords left="0.1171875" right="0.2421875" top="0" bottom="1"/>
</Texture>
</Layer>
<Layer level="OVERLAY">
<FontString name="$parentTitle" inherits="GameFontNormal" text="EVENTS_LABEL">
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="12" y="-8"/>
</Anchor>
<Anchor point="TOPRIGHT">
<Offset x="-32" y="-8"/>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Button name="$parentCloseButton" inherits="UIPanelCloseButton">
<Size>
<AbsDimension x="32" y="32"/>
</Size>
<Anchors>
<Anchor point="TOPRIGHT">
<Offset x="2" y="1"/>
</Anchor>
</Anchors>
</Button>
<Frame name="$parentTitleButton">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTitleBG"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentTitleBG"/>
</Anchors>
<Frames>
<Frame name="$parentHighlight" setAllPoints="true" hidden="true">
<Layers>
<Layer level="OVERLAY">
<Texture file="Interface\Buttons\UI-ListBox-Highlight" setAllPoints="true">
<Color r="1" g="1" b="1" a="0.4"/>
</Texture>
</Layer>
</Layers>
</Frame>
</Frames>
<Scripts>
<OnLoad>
this:RegisterForDrag("LeftButton");
</OnLoad>
<OnDragStart>
local eventTraceFrame = getglobal("EventTraceFrame");
eventTraceFrame.moving = true;
eventTraceFrame:StartMoving();
</OnDragStart>
<OnDragStop>
local eventTraceFrame = getglobal("EventTraceFrame");
eventTraceFrame.moving = nil;
eventTraceFrame:StopMovingOrSizing();
</OnDragStop>
</Scripts>
</Frame>
<Slider name="$parentScroll">
<Size x="16" y="0"/>
<Anchors>
<Anchor point="TOPRIGHT">
<Offset x="-7" y="-28"/>
</Anchor>
<Anchor point="BOTTOMRIGHT">
<Offset x="-7" y="10"/>
</Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentBG" setAllPoints="true">
<Color r=".8" g=".8" b="1" a="0.1"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnLoad>
this:SetFrameLevel(this:GetFrameLevel() + 1);
this:SetValue(0);
this:SetValueStep(1);
</OnLoad>
</Scripts>
<ThumbTexture name="$parentThumb" file="Interface\Buttons\UI-ScrollBar-Knob">
<Size x="16" y="16"/>
<TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/>
</ThumbTexture>
</Slider>
</Frames>
<Scripts>
<OnLoad>
EventTraceFrame_OnLoad(this);
</OnLoad>
<OnShow>
EventTraceFrame_OnShow(this);
</OnShow>
<OnEvent>
EventTraceFrame_OnEvent(this, unpack(arg));
</OnEvent>
<OnUpdate>
EventTraceFrame_OnUpdate(this, arg1);
</OnUpdate>
<OnKeyUp>
EventTraceFrame_OnKeyUp(this, arg1);
</OnKeyUp>
</Scripts>
</Frame>
<Frame name="ScriptErrorsFrame" inherits="UIPanelDialogTemplate" frameStrata="TOOLTIP" movable="true" enableMouse="true" clampedToScreen="true" hidden="true" toplevel="true">
<Size x="384" y="260"/>
<Anchors>
<Anchor point="CENTER"/>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentIndexLabel" font="GameFontNormalCenter">
<Size x="70" y="16"/>
<Anchors>
<Anchor point="BOTTOM">
<Offset x="0" y="16"/>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Frame name="$parentTitleButton">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTitleBG"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentTitleBG"/>
</Anchors>
<Scripts>
<OnLoad>
this:RegisterForDrag("LeftButton");
</OnLoad>
<OnDragStart>
local frame = getglobal("ScriptErrorsFrame");
frame.moving = true;
frame:StartMoving();
</OnDragStart>
<OnDragStop>
local frame = getglobal("ScriptErrorsFrame");
frame.moving = nil;
frame:StopMovingOrSizing();
</OnDragStop>
</Scripts>
</Frame>
<ScrollFrame name="$parentScrollFrame" inherits="UIPanelScrollFrameTemplate">
<Size x="343" y="194"/>
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="12" y="-30"/>
</Anchor>
</Anchors>
<ScrollChild>
<EditBox name="$parentText" multiLine="true" letters="4000" autoFocus="false">
<Size x="343" y="194"/>
<Scripts>
<OnCursorChanged>
ScrollingEdit_OnCursorChanged(this);
</OnCursorChanged>
<OnUpdate>
ScrollingEdit_OnUpdate(this, arg1, this:GetParent());
</OnUpdate>
<OnEditFocusGained>
this:HighlightText(0);
</OnEditFocusGained>
<OnEscapePressed>
this:ClearFocus();
</OnEscapePressed>
</Scripts>
<FontString inherits="GameFontHighlightSmall"/>
</EditBox>
</ScrollChild>
</ScrollFrame>
<Button name="$parentReload" inherits="UIPanelButtonTemplate" text="RELOADUI">
<Size x="96" y="24"/>
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parent">
<Offset x="10" y="12" />
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ReloadUI();
</OnClick>
</Scripts>
</Button>
<Button name="$parentPrevious" id="2">
<Size x="32" y="32"/>
<Anchors>
<Anchor point="BOTTOM">
<Offset x="-50" y="8"/>
</Anchor>
</Anchors>
<NormalTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Up"/>
<PushedTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Down"/>
<DisabledTexture file="Interface\Buttons\UI-SpellbookIcon-PrevPage-Disabled"/>
<HighlightTexture file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD"/>
<Scripts>
<OnClick>
ScriptErrorsFrameButton_OnClick(this);
</OnClick>
</Scripts>
</Button>
<Button name="$parentNext" id="1">
<Size x="32" y="32" />
<Anchors>
<Anchor point="BOTTOM">
<Offset x="50" y="8"/>
</Anchor>
</Anchors>
<NormalTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Up"/>
<PushedTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Down"/>
<DisabledTexture file="Interface\Buttons\UI-SpellbookIcon-NextPage-Disabled"/>
<HighlightTexture file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD"/>
<Scripts>
<OnClick>
ScriptErrorsFrameButton_OnClick(this);
</OnClick>
</Scripts>
</Button>
<Button name="$parentCloseButton" inherits="UIPanelButtonTemplate" text="CLOSE">
<Size x="96" y="24"/>
<Anchors>
<Anchor point="BOTTOMRIGHT">
<Offset x="-8" y="12"/>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
HideUIPanel(this:GetParent());
</OnClick>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnLoad>
ScriptErrorsFrame_OnLoad(this);
</OnLoad>
<OnShow>
ScriptErrorsFrame_OnShow(this);
</OnShow>
</Scripts>
</Frame>
<GameTooltip name="FrameStackTooltip" frameStrata="TOOLTIP" hidden="true" inherits="GameTooltipTemplate">
<Scripts>
<OnLoad>
FrameStackTooltip_OnLoad(this);
</OnLoad>
<OnShow>
FrameStackTooltip_OnShow(this);
</OnShow>
<OnEnter>
FrameStackTooltip_OnEnter(this);
</OnEnter>
<OnUpdate>
FrameStackTooltip_OnUpdate(this, arg1);
</OnUpdate>
<OnEvent>
FrameStackTooltip_OnEvent(this, unpack(arg));
</OnEvent>
</Scripts>
</GameTooltip>
<GameTooltip name="EventTraceTooltip" frameStrata="TOOLTIP" hidden="true" parent="EventTraceFrame" inherits="GameTooltipTemplate">
<Scripts>
<OnLoad>
DebugTooltip_OnLoad(this)
</OnLoad>
</Scripts>
</GameTooltip>
<Frame name="FrameStackHighlight" frameStrata="TOOLTIP">
<Layers>
<Layer level="ARTWORK">
<Texture name="$parentTexture">
<Color r="0.0" g="0.8" b="0.0" a=".4"/>
</Texture>
</Layer>
</Layers>
</Frame>
</Ui>
+197
View File
@@ -0,0 +1,197 @@
--Cache global variables
local _G = getfenv()
local format, match = string.format, string.match
local tinsert, tsort, twipe = table.insert, table.sort, table.wipe
local mod = math.mod
local pairs = pairs
local tostring = tostring
--WoW API
local GetTime = GetTime
DEBUG_FRAMESTACK = "Frame Stack"
EVENTS_LABEL = "Events"
RELOADUI = "Reload UI"
local eventList = {}
local function EventHandler_OnEvent()
tinsert(eventList, GetTime())
end
local eventHandler = CreateFrame("Frame", "EventHandler", UIParent)
eventHandler:SetScript("OnEvent", EventHandler_OnEvent)
function GetCurrentEventID()
return getn(eventList)
end
function GetEventTime(eventID)
return eventList[eventID]
end
function EventHandler_Enable()
eventHandler:RegisterAllEvents()
end
function EventHandler_Disable()
eventHandler:UnregisterAllEvents()
twipe(eventList)
end
local strataLevels = {
["UNKNOWN"] = 1,
["BACKGROUND"] = 2,
["LOW"] = 3,
["MEDIUM"] = 4,
["HIGH"] = 5,
["DIALOG"] = 6,
["FULLSCREEN"] = 7,
["FULLSCREEN_DIALOG"] = 8,
["TOOLTIP"] = 9,
}
local colorSpecs = {
"|cff6699ff",
"|cff88dddd"
}
local activeColorSpecs = {
"|cffff9966",
"|cffdddd88"
}
local hiddenColorSpecs = {
"|cff666666",
"|cff888888"
}
local frameStackStrata = {}
local frameStackLevels = {}
local frameStackActive = {}
local frameStackList = {}
local function FrameStackSort(b, a)
local sa = strataLevels[frameStackStrata[a]] or -1
local sb = strataLevels[frameStackStrata[b]] or -1
if sa < sb then
return true
elseif sa > sb then
return
end
local sa = frameStackLevels[a] or -1
local sb = frameStackLevels[b] or -1
if sa < sb then
return true
elseif sa > sb then
return
end
return a < b
end
function UpdateFrameStack(tooltip, showHidden)
local x, y = GetCursorPosition()
for i = 1, getn(frameStackList) do
frameStackList[i] = nil
end
for k in pairs(frameStackLevels) do
frameStackLevels[k] = nil
frameStackStrata[k] = nil
frameStackActive[k] = nil
end
local f
local nf = EnumerateFrames()
while nf do
f, nf = nf, EnumerateFrames(nf)
local es = f:GetEffectiveScale() or 1
local Fl, Fb, Fr, Ft = f:GetLeft(), f:GetBottom(), f:GetRight(), f:GetTop()
Fl = Fl or -1
Fb = Fb or -1
Fr = Fl + (Fr or -1)
Ft = Fb + (Ft or -1)
if (x >= Fl * es) and (x <= Fr * es) and (y >= Fb * es) and (y <= Ft * es) then
local n = f:GetName()
if n and _G[n] == f then
-- Name is ok
elseif n then
n = tostring(f) .. " (" .. n .. ")"
else
n = tostring(f)
end
local s = f:GetFrameStrata() or "nil"
local l = f:GetFrameLevel() or -1
local a
if f:IsVisible() then
if f:IsMouseEnabled() then
a = activeColorSpecs
else
a = colorSpecs
end
elseif showHidden then
a = hiddenColorSpecs
else
a = nil
end
if a then
frameStackLevels[n] = l
frameStackStrata[n] = s
frameStackActive[n] = a
tinsert(frameStackList, n)
end
end
end
frameStackList[getn(frameStackList) + 1] = nil
--tsort(frameStackList, FrameStackSort)
tooltip:ClearLines()
tooltip:AddDoubleLine(DEBUG_FRAMESTACK, format("(%.2f,%.2f)", x, y), 1, 1, 1, 1, .82, 0)
local cs, os, ol = 1, nil, nil
local cn = getn(colorSpecs)
local highlighted
local highlightFrame = GetMouseFocus()
for _, n in ipairs(frameStackList) do
local s, l, a = frameStackStrata[n], frameStackLevels[n], frameStackActive[n]
if os ~= s then
tooltip:AddLine(s, 1, 1, 1)
os = s
ol = nil
cs = 1
end
if l ~= ol then
cs = mod(cs, cn) + 1 or 0
ol = l
end
if not highlighted then
local frameName = _G[n] --[[or match(n, "%((.+)%)$")]] or n
if frameName and frameName == highlightFrame then
tooltip:AddLine("-->" .. (a[cs] or "|cff444444") .. "<" .. l .. "> " .. n .. "|r")
highlighted = true
else
tooltip:AddLine(" " .. (a[cs] or "|cff444444") .. "<" .. l .. "> " .. n .. "|r")
end
else
tooltip:AddLine(" " .. (a[cs] or "|cff444444") .. "<" .. l .. "> " .. n .. "|r")
end
end
tooltip:Show()
return highlightFrame
end
+387
View File
@@ -0,0 +1,387 @@
------------------------------------------------------------------------------
-- Dump.lua
--
-- Contributed by Iriel, Esamynn and Kirov from DevTools v1.11
-- /dump Implementation
--
-- Globals: DevTools, SLASH_DEVTOOLSDUMP1, DevTools_Dump, DevTools_RunDump
-- Globals: DEVTOOLS_MAX_ENTRY_CUTOFF, DEVTOOLS_LONG_STRING_CUTOFF
-- Globals: DEVTOOLS_DEPTH_CUTOFF, DEVTOOLS_INDENT
-- Globals: DEVTOOLS_USE_TABLE_CACHE, DEVTOOLS_USE_FUNCTION_CACHE
-- Globals: DEVTOOLS_USE_USERDATA_CACHE
---------------------------------------------------------------------------
local DT = {};
DEVTOOLS_MAX_ENTRY_CUTOFF = 30; -- Maximum table entries shown
DEVTOOLS_LONG_STRING_CUTOFF = 200; -- Maximum string size shown
DEVTOOLS_DEPTH_CUTOFF = 10; -- Maximum table depth
DEVTOOLS_USE_TABLE_CACHE = true; -- Look up table names
DEVTOOLS_USE_FUNCTION_CACHE = true; -- Look up function names
DEVTOOLS_USE_USERDATA_CACHE = true; -- Look up userdata names
DEVTOOLS_INDENT=' '; -- Indentation string
local DEVTOOLS_TYPE_COLOR="|cff88ff88";
local DEVTOOLS_TABLEREF_COLOR="|cffffcc00";
local DEVTOOLS_CUTOFF_COLOR="|cffff0000";
local DEVTOOLS_TABLEKEY_COLOR="|cff88ccff";
local FORMATS = {};
-- prefix type suffix
FORMATS["opaqueTypeVal"] = "%s" .. DEVTOOLS_TYPE_COLOR .. "<%s>|r%s";
-- prefix type name suffix
FORMATS["opaqueTypeValName"] = "%s" .. DEVTOOLS_TYPE_COLOR .. "<%s %s>|r%s";
-- type
FORMATS["opaqueTypeKey"] = "<%s>";
-- type name
FORMATS["opaqueTypeKeyName"] = "<%s %s>";
-- value
FORMATS["bracketTableKey"] = "[%s]";
-- prefix value
FORMATS["tableKeyAssignPrefix"] = DEVTOOLS_TABLEKEY_COLOR .. "%s%s|r=";
-- prefix cutoff
FORMATS["tableEntriesSkipped"] = "%s" .. DEVTOOLS_CUTOFF_COLOR .. "<skipped %s>|r";
-- prefix suffix
FORMATS["tableTooDeep"] = "%s" .. DEVTOOLS_CUTOFF_COLOR .. "<table (too deep)>|r%s";
-- prefix value suffix
FORMATS["simpleValue"] = "%s%s%s";
-- prefix tablename suffix
FORMATS["tableReference"] = "%s" .. DEVTOOLS_TABLEREF_COLOR .. "%s|r%s";
-- Grab a copy various oft-used functions
local rawget = rawget;
local type = type;
local string_len = string.len;
local string_sub = string.sub;
local string_gsub = string.gsub;
local string_format = string.format;
local string_match = string.match;
local function WriteMessage(msg)
DEFAULT_CHAT_FRAME:AddMessage(msg);
end
local function prepSimple(val, context)
local valType = type(val);
if (valType == "nil") then
return "nil";
elseif (valType == "number") then
return val;
elseif (valType == "boolean") then
if (val) then
return "true";
else
return "false";
end
elseif (valType == "string") then
local l = string_len(val);
if ((l > DEVTOOLS_LONG_STRING_CUTOFF) and
(DEVTOOLS_LONG_STRING_CUTOFF > 0)) then
local more = l - DEVTOOLS_LONG_STRING_CUTOFF;
val = string_sub(val, 1, DEVTOOLS_LONG_STRING_CUTOFF);
return string_gsub(string_format("%q...+%s",val,more),"[|]", "||");
else
return string_gsub(string_format("%q",val),"[|]", "||");
end
elseif (valType == "function") then
local fName = context:GetFunctionName(val);
if (fName) then
return string_format(FORMATS.opaqueTypeKeyName, valType, fName);
else
return string_format(FORMATS.opaqueTypeKey, valType);
end
return string_format(FORMATS.opaqueTypeKey, valType);
elseif (valType == "userdata") then
local uName = context:GetUserdataName(val);
if (uName) then
return string_format(FORMATS.opaqueTypeKeyName, valType, uName);
else
return string_format(FORMATS.opaqueTypeKey, valType);
end
elseif (valType == 'table') then
local tName = context:GetTableName(val);
if (tName) then
return string_format(FORMATS.opaqueTypeKeyName, valType, tName);
else
return string_format(FORMATS.opaqueTypeKey, valType);
end
end
error("Bad type '" .. valType .. "' to prepSimple");
end
local function prepSimpleKey(val, context)
local valType = type(val);
if (valType == "string") then
local l = string_len(val);
if ((l <= DEVTOOLS_LONG_STRING_CUTOFF) or
(DEVTOOLS_LONG_STRING_CUTOFF <= 0)) then
if (string_match(val, "^[a-zA-Z_][a-zA-Z0-9_]*$")) then
return val;
end
end
end
return string_format(FORMATS.bracketTableKey, prepSimple(val, context));
end
local function DevTools_InitFunctionCache(context)
local ret = {};
for _,k in ipairs(DT.functionSymbols) do
local v = getglobal(k);
if (type(v) == 'function') then
ret[v] = '[' .. k .. ']';
end
end
for k,v in pairs(getfenv(0)) do
if (type(v) == 'function') then
if (not ret[v]) then
ret[v] = '[' .. k .. ']';
end
end
end
return ret;
end
local function DevTools_InitUserdataCache(context)
local ret = {};
for _,k in ipairs(DT.userdataSymbols) do
local v = getglobal(k);
if (type(v) == 'table') then
local u = rawget(v,0);
if (type(u) == 'userdata') then
ret[u] = k .. '[0]';
end
end
end
for k,v in pairs(getfenv(0)) do
if (type(v) == 'table') then
local u = rawget(v, 0);
if (type(u) == 'userdata') then
if (not ret[u]) then
ret[u] = k .. '[0]';
end
end
end
end
return ret;
end
local function DevTools_Cache_Nil(self, value, newName)
return nil;
end
local function DevTools_Cache_Function(self, value, newName)
if (not self.fCache) then
self.fCache = DevTools_InitFunctionCache(self);
end
local name = self.fCache[value];
if ((not name) and newName) then
self.fCache[value] = newName;
end
return name;
end
local function DevTools_Cache_Userdata(self, value, newName)
if (not self.uCache) then
self.uCache = DevTools_InitUserdataCache(self);
end
local name = self.uCache[value];
if ((not name) and newName) then
self.uCache[value] = newName;
end
return name;
end
local function DevTools_Cache_Table(self, value, newName)
if (not self.tCache) then
self.tCache = {};
end
local name = self.tCache[value];
if ((not name) and newName) then
self.tCache[value] = newName;
end
return name;
end
local function DevTools_Write(self, msg)
DEFAULT_CHAT_FRAME:AddMessage(msg);
end
local DevTools_DumpValue;
local function DevTools_DumpTableContents(val, prefix, firstPrefix, context)
local showCount = 0;
local oldDepth = context.depth;
local oldKey = context.key;
-- Use this to set the cache name
context:GetTableName(val, oldKey or 'value');
local iter = pairs(val);
local nextK, nextV = iter(val, nil);
while (nextK) do
local k,v = nextK, nextV;
nextK, nextV = iter(val, k);
showCount = showCount + 1;
if ((showCount <= DEVTOOLS_MAX_ENTRY_CUTOFF) or (DEVTOOLS_MAX_ENTRY_CUTOFF <= 0)) then
local prepKey = prepSimpleKey(k, context);
if (oldKey == nil) then
context.key = prepKey;
elseif (string_sub(prepKey, 1, 1) == "[") then
context.key = oldKey .. prepKey
else
context.key = oldKey .. "." .. prepKey
end
context.depth = oldDepth + 1;
local rp = string_format(FORMATS.tableKeyAssignPrefix, firstPrefix, prepKey);
firstPrefix = prefix;
DevTools_DumpValue(v, prefix, rp, (nextK and ",") or '', context);
end
end
local cutoff = showCount - DEVTOOLS_MAX_ENTRY_CUTOFF;
if ((cutoff > 0) and (DEVTOOLS_MAX_ENTRY_CUTOFF > 0)) then
context:Write(string_format(FORMATS.tableEntriesSkipped,firstPrefix, cutoff));
end
context.key = oldKey;
context.depth = oldDepth;
return (showCount > 0)
end
-- Return the specified value
function DevTools_DumpValue(val, prefix, firstPrefix, suffix, context)
local valType = type(val);
if (valType == "userdata") then
local uName = context:GetUserdataName(val, 'value');
if (uName) then
context:Write(string_format(FORMATS.opaqueTypeValName, firstPrefix, valType, uName, suffix));
else
context:Write(string_format(FORMATS.opaqueTypeVal, firstPrefix, valType, suffix));
end
return;
elseif (valType == "function") then
local fName = context:GetFunctionName(val, 'value');
if (fName) then
context:Write(string_format(FORMATS.opaqueTypeValName, firstPrefix, valType, fName, suffix));
else
context:Write(string_format(FORMATS.opaqueTypeVal, firstPrefix, valType, suffix));
end
return;
elseif (valType ~= "table") then
context:Write(string_format(FORMATS.simpleValue, firstPrefix,prepSimple(val, context), suffix));
return;
end
local cacheName = context:GetTableName(val);
if (cacheName) then
context:Write(string_format(FORMATS.tableReference, firstPrefix, cacheName, suffix));
return;
end
if ((context.depth >= DEVTOOLS_DEPTH_CUTOFF) and (DEVTOOLS_DEPTH_CUTOFF > 0)) then
context:Write(string_format(FORMATS.tableTooDeep, firstPrefix, suffix));
return;
end
firstPrefix = firstPrefix .. "{";
local oldPrefix = prefix;
prefix = prefix .. DEVTOOLS_INDENT;
context:Write(firstPrefix);
firstPrefix = prefix;
local anyContents = DevTools_DumpTableContents(val, prefix, firstPrefix, context);
context:Write(oldPrefix .. "}" .. suffix);
end
local function Pick_Cache_Function(func, setting)
if (setting) then
return func;
else
return DevTools_Cache_Nil;
end
end
function DevTools_RunDump(value, context)
local prefix = "";
local firstPrefix = prefix;
local valType = type(value);
if (type(value) == 'table') then
local any =
DevTools_DumpTableContents(value, prefix, firstPrefix, context);
if (context.Result) then
return context:Result();
end
if (not any) then
context:Write("empty result");
end
return;
end
DevTools_DumpValue(value, '', '', '', context);
if (context.Result) then
return context:Result();
end
end
-- Dump the specified list of value
function DevTools_Dump(value, startKey)
local context = {
depth = 0,
key = startKey,
};
context.GetTableName = Pick_Cache_Function(DevTools_Cache_Table, DEVTOOLS_USE_TABLE_CACHE);
context.GetFunctionName = Pick_Cache_Function(DevTools_Cache_Function, DEVTOOLS_USE_FUNCTION_CACHE);
context.GetUserdataName = Pick_Cache_Function(DevTools_Cache_Userdata, DEVTOOLS_USE_USERDATA_CACHE);
context.Write = DevTools_Write;
DevTools_RunDump(value, context);
end
function DevTools_DumpCommand(msg, editBox)
if (string_match(msg,"^[A-Za-z_][A-Za-z0-9_]*$")) then
WriteMessage("Dump: " .. msg);
local val = _G[msg];
local tmp = {};
if (val == nil) then
local key = string_format(FORMATS.tableKeyAssignPrefix, '', prepSimpleKey(msg, {}));
WriteMessage(key .. "nil,");
else
tmp[msg] = val;
end
DevTools_Dump(tmp);
return;
end
WriteMessage("Dump: value=" .. msg);
local func,err = loadstring("return " .. msg);
if (not func) then
WriteMessage("Dump: ERROR: " .. err);
else
DevTools_Dump({func()}, "value");
end
end
DT.functionSymbols = {};
DT.userdataSymbols = {};
local funcSyms = DT.functionSymbols;
local userSyms = DT.userdataSymbols;
for k,v in pairs(getfenv(0)) do
if (type(v) == 'function') then
table.insert(funcSyms, k);
elseif (type(v) == 'table') then
if (type(rawget(v,0)) == 'userdata') then
table.insert(userSyms, k);
end
end
end
+17
View File
@@ -0,0 +1,17 @@
<Bindings>
<Binding name="Raid Marker" runOnUp="true" header="ELVUI">
RaidMark_HotkeyPressed(keystate);
</Binding>
<Binding name="Farm Mode" runOnUp="false">
FarmMode();
</Binding>
<Binding name="Toggle Chat (Left)" runOnUp="false">
HideLeftChat();
</Binding>
<Binding name="Toggle Chat (Right)" runOnUp="false">
HideRightChat();
</Binding>
<Binding name="Toggle Chat (Both)" runOnUp="false">
HideBothChat();
</Binding>
</Bindings>
+502
View File
@@ -0,0 +1,502 @@
local E, L, V, P, G = unpack(ElvUI); -- Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
--Cache global variables
--Lua functions
local _G = getfenv()
local type, ipairs, tonumber = type, ipairs, tonumber
local floor = math.floor
--WoW API / Variables
local CreateFrame = CreateFrame
local IsAddOnLoaded = IsAddOnLoaded
local GetScreenWidth = GetScreenWidth
local GetScreenHeight = GetScreenHeight
local RESET = RESET
local grid
local selectedValue = "ALL"
E.ConfigModeLayouts = {
"ALL",
"GENERAL",
"SOLO",
"PARTY",
"ARENA",
"RAID",
"ACTIONBARS"
}
E.ConfigModeLocalizedStrings = {
ALL = ALL,
GENERAL = GENERAL,
SOLO = SOLO,
PARTY = PARTY,
ARENA = ARENA,
RAID = RAID,
ACTIONBARS = ACTIONBARS_LABEL
}
function E:Grid_Show()
if not grid then
E:Grid_Create()
elseif grid.boxSize ~= E.db.gridSize then
grid:Hide()
E:Grid_Create()
else
grid:Show()
end
end
function E:Grid_Hide()
if grid then
grid:Hide()
end
end
function E:ToggleConfigMode(override, configType)
if override ~= nil and override ~= "" then E.ConfigurationMode = override end
if E.ConfigurationMode ~= true then
if not grid then
E:Grid_Create()
elseif grid.boxSize ~= E.db.gridSize then
grid:Hide()
E:Grid_Create()
else
grid:Show()
end
if not ElvUIMoverPopupWindow then
E:CreateMoverPopup()
end
ElvUIMoverPopupWindow:Show()
if(IsAddOnLoaded("ElvUI_Config")) then
LibStub("AceConfigDialog-3.0"):Close("ElvUI")
GameTooltip:Hide()
end
E.ConfigurationMode = true
else
if ElvUIMoverPopupWindow then
ElvUIMoverPopupWindow:Hide()
end
if grid then
grid:Hide()
end
E.ConfigurationMode = false
end
if type(configType) ~= "string" then
configType = nil
end
self:ToggleMovers(E.ConfigurationMode, configType or "ALL")
end
function E:Grid_Create()
grid = CreateFrame("Frame", "EGrid", UIParent)
grid.boxSize = E.db.gridSize
grid:SetAllPoints(E.UIParent)
grid:Show()
local size = 1
local width = E.eyefinity or GetScreenWidth()
local ratio = width / GetScreenHeight()
local height = GetScreenHeight() * ratio
local wStep = width / E.db.gridSize
local hStep = height / E.db.gridSize
for i = 0, E.db.gridSize do
local tx = grid:CreateTexture(nil, "BACKGROUND")
if i == E.db.gridSize / 2 then
tx:SetTexture(1, 0, 0)
else
tx:SetTexture(0, 0, 0)
end
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", i*wStep - (size/2), 0)
tx:SetPoint("BOTTOMRIGHT", grid, "BOTTOMLEFT", i*wStep + (size/2), 0)
end
height = GetScreenHeight()
do
local tx = grid:CreateTexture(nil, "BACKGROUND")
tx:SetTexture(1, 0, 0)
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2) + (size/2))
tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2 + size/2))
end
for i = 1, floor((height/2)/hStep) do
local tx = grid:CreateTexture(nil, "BACKGROUND")
tx:SetTexture(0, 0, 0)
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2+i*hStep) + (size/2))
tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2+i*hStep + size/2))
tx = grid:CreateTexture(nil, "BACKGROUND")
tx:SetTexture(0, 0, 0)
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2-i*hStep) + (size/2))
tx:SetPoint("BOTTOMRIGHT", grid, "TOPRIGHT", 0, -(height/2-i*hStep + size/2))
end
end
local function ConfigMode_OnClick(self)
selectedValue = self.value
E:ToggleConfigMode(false, self.value)
-- UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, self.value)
end
local function ConfigMode_Initialize()
local info = UIDropDownMenu_CreateInfo()
info.func = ConfigMode_OnClick
for _, configMode in ipairs(E.ConfigModeLayouts) do
info.text = E.ConfigModeLocalizedStrings[configMode]
info.value = configMode
UIDropDownMenu_AddButton(info)
end
--UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, selectedValue)
end
function E:NudgeMover(nudgeX, nudgeY)
local mover = ElvUIMoverNudgeWindow.child
local x, y, point = E:CalculateMoverPoints(mover, nudgeX, nudgeY)
mover:ClearAllPoints()
mover:SetPoint(mover.positionOverride or point, E.UIParent, mover.positionOverride and "BOTTOMLEFT" or point, x, y)
E:SaveMoverPosition(mover.name)
E:UpdateNudgeFrame(mover, x, y)
end
function E:UpdateNudgeFrame(mover, x, y)
if not(x and y) then
x, y = E:CalculateMoverPoints(mover)
end
x = E:Round(x, 0)
y = E:Round(y, 0)
ElvUIMoverNudgeWindow.xOffset:SetText(x)
ElvUIMoverNudgeWindow.yOffset:SetText(y)
ElvUIMoverNudgeWindow.xOffset.currentValue = x
ElvUIMoverNudgeWindow.yOffset.currentValue = y
ElvUIMoverNudgeWindowHeader.title:SetText(mover.textString)
end
function E:AssignFrameToNudge()
ElvUIMoverNudgeWindow.child = self
E:UpdateNudgeFrame(self)
end
function E:CreateMoverPopup()
local f = CreateFrame("Frame", "ElvUIMoverPopupWindow", UIParent)
f:SetFrameStrata("DIALOG")
f:SetToplevel(true)
f:EnableMouse(true)
f:SetMovable(true)
f:SetFrameLevel(99)
f:SetClampedToScreen(true)
f:SetWidth(360)
f:SetHeight(170)
E:SetTemplate(f, "Transparent")
f:SetPoint("BOTTOM", UIParent, "CENTER", 0, 100)
f:SetScript("OnHide", function()
if ElvUIMoverPopupWindowDropDown then
UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, "ALL")
end
end)
f:Hide()
local S = E:GetModule("Skins")
local header = CreateFrame("Button", nil, f)
E:SetTemplate(header, "Default", true)
header:SetWidth(100) header:SetHeight(25)
header:SetPoint("CENTER", f, "TOP")
header:SetFrameLevel(header:GetFrameLevel() + 2)
header:EnableMouse(true)
header:RegisterForClicks("AnyUp", "AnyDown")
header:SetScript("OnMouseDown", function() f:StartMoving() end)
header:SetScript("OnMouseUp", function() f:StopMovingOrSizing() end)
local title = header:CreateFontString("OVERLAY")
E:FontTemplate(title)
title:SetPoint("CENTER", header, "CENTER")
title:SetText("ElvUI")
local desc = f:CreateFontString("ARTWORK")
desc:SetFontObject("GameFontHighlight")
desc:SetJustifyV("TOP")
desc:SetJustifyH("LEFT")
desc:SetPoint("TOPLEFT", 18, -32)
desc:SetPoint("BOTTOMRIGHT", -18, 48)
desc:SetText(L["DESC_MOVERCONFIG"])
local snapping = CreateFrame("CheckButton", f:GetName().."CheckButton", f, "OptionsCheckButtonTemplate")
_G[snapping:GetName() .. "Text"]:SetText(L["Sticky Frames"])
snapping:SetScript("OnShow", function()
this:SetChecked(E.db.general.stickyFrames)
end)
snapping:SetScript("OnClick", function()
E.db.general.stickyFrames = this:GetChecked()
end)
local lock = CreateFrame("Button", f:GetName().."CloseButton", f, "OptionsButtonTemplate")
_G[lock:GetName() .. "Text"]:SetText(L["Lock"])
lock:SetScript("OnClick", function()
E:ToggleConfigMode(true)
if(IsAddOnLoaded("ElvUI_Config")) then
LibStub("AceConfigDialog-3.0-ElvUI"):Open("ElvUI")
end
selectedValue = "ALL"
UIDropDownMenu_SetSelectedValue(ElvUIMoverPopupWindowDropDown, selectedValue)
end)
local align = CreateFrame("EditBox", f:GetName().."EditBox", f, "InputBoxTemplate")
align:SetWidth(24)
align:SetHeight(17)
align:SetAutoFocus(false)
align:SetScript("OnEscapePressed", function()
this:SetText(E.db.gridSize)
EditBox_ClearFocus(this)
end)
align:SetScript("OnEnterPressed", function()
local text = this:GetText()
if tonumber(text) then
if tonumber(text) <= 256 and tonumber(text) >= 4 then
E.db.gridSize = tonumber(text)
else
this:SetText(E.db.gridSize)
end
else
this:SetText(E.db.gridSize)
end
E:Grid_Show()
EditBox_ClearFocus(this)
end)
align:SetScript("OnEditFocusLost", function()
this:SetText(E.db.gridSize)
end)
align:SetScript("OnEditFocusGained", align.HighlightText)
align:SetScript("OnShow", function()
EditBox_ClearFocus(this)
this:SetText(E.db.gridSize)
end)
align.text = align:CreateFontString(nil, "OVERLAY", "GameFontNormal")
align.text:SetPoint("RIGHT", align, "LEFT", -4, 0)
align.text:SetText(L["Grid Size:"])
--position buttons
snapping:SetPoint("BOTTOMLEFT", 14, 10)
lock:SetPoint("BOTTOMRIGHT", -14, 14)
align:SetPoint("TOPRIGHT", lock, "TOPLEFT", -4, -2)
S:HandleCheckBox(snapping)
S:HandleButton(lock)
S:HandleEditBox(align)
f:RegisterEvent("PLAYER_REGEN_DISABLED")
f:SetScript("OnEvent", function()
if this:IsShown() then
this:Hide()
E:Grid_Hide()
E:ToggleConfigMode(true)
end
end)
local configMode = CreateFrame("Frame", f:GetName().."DropDown", f, "UIDropDownMenuTemplate")
configMode:SetPoint("BOTTOMRIGHT", lock, "TOPRIGHT", 8, -5)
S:HandleDropDownBox(configMode, 148)
configMode.text = configMode:CreateFontString(nil, "OVERLAY", "GameFontNormal")
configMode.text:SetPoint("RIGHT", configMode.backdrop, "LEFT", -2, 0)
configMode.text:SetText(L["Config Mode:"])
--UIDropDownMenu_Initialize(configMode, ConfigMode_Initialize)
local nudgeFrame = CreateFrame("Frame", "ElvUIMoverNudgeWindow", E.UIParent)
nudgeFrame:SetFrameStrata("DIALOG")
nudgeFrame:SetWidth(200)
nudgeFrame:SetHeight(110)
E:SetTemplate(nudgeFrame, "Transparent")
nudgeFrame:SetPoint("TOP", ElvUIMoverPopupWindow, "BOTTOM", 0, -15)
nudgeFrame:SetFrameLevel(100)
nudgeFrame:Hide()
nudgeFrame:EnableMouse(true)
nudgeFrame:SetClampedToScreen(true)
--ElvUIMoverPopupWindow:HookScript("OnHide", function() ElvUIMoverNudgeWindow:Hide() end)
header = CreateFrame("Button", "ElvUIMoverNudgeWindowHeader", nudgeFrame)
E:SetTemplate(header, "Default", true)
header:SetWidth(100) header:SetHeight(25)
header:SetPoint("CENTER", nudgeFrame, "TOP")
header:SetFrameLevel(header:GetFrameLevel() + 2)
title = header:CreateFontString("OVERLAY")
E:FontTemplate(title)
title:SetPoint("CENTER", header, "CENTER")
title:SetText(L["Nudge"])
header.title = title
local xOffset = CreateFrame("EditBox", nudgeFrame:GetName().."XEditBox", nudgeFrame, "InputBoxTemplate")
xOffset:SetWidth(50)
xOffset:SetHeight(17)
xOffset:SetAutoFocus(false)
xOffset.currentValue = 0
xOffset:SetScript("OnEscapePressed", function()
this:SetText(E:Round(xOffset.currentValue))
EditBox_ClearFocus(this)
end)
xOffset:SetScript("OnEnterPressed", function()
local num = this:GetText()
if(tonumber(num)) then
local diff = num - xOffset.currentValue
xOffset.currentValue = num
E:NudgeMover(diff)
end
this:SetText(E:Round(xOffset.currentValue))
EditBox_ClearFocus(this)
end)
xOffset:SetScript("OnEditFocusLost", function()
this:SetText(E:Round(xOffset.currentValue))
end)
xOffset:SetScript("OnEditFocusGained", xOffset.HighlightText)
xOffset:SetScript("OnShow", function()
EditBox_ClearFocus(this)
this:SetText(E:Round(xOffset.currentValue))
end)
xOffset.text = xOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
xOffset.text:SetPoint("RIGHT", xOffset, "LEFT", -4, 0)
xOffset.text:SetText("X:")
xOffset:SetPoint("BOTTOMRIGHT", nudgeFrame, "CENTER", -6, 8)
nudgeFrame.xOffset = xOffset
S:HandleEditBox(xOffset)
local yOffset = CreateFrame("EditBox", nudgeFrame:GetName().."YEditBox", nudgeFrame, "InputBoxTemplate")
yOffset:SetWidth(50)
yOffset:SetHeight(17)
yOffset:SetAutoFocus(false)
yOffset.currentValue = 0
yOffset:SetScript("OnEscapePressed", function()
this:SetText(E:Round(yOffset.currentValue))
EditBox_ClearFocus(this)
end)
yOffset:SetScript("OnEnterPressed", function()
local num = this:GetText()
if(tonumber(num)) then
local diff = num - yOffset.currentValue
yOffset.currentValue = num
E:NudgeMover(nil, diff)
end
this:SetText(E:Round(yOffset.currentValue))
EditBox_ClearFocus(this)
end)
yOffset:SetScript("OnEditFocusLost", function()
this:SetText(E:Round(yOffset.currentValue))
end)
yOffset:SetScript("OnEditFocusGained", yOffset.HighlightText)
yOffset:SetScript("OnShow", function()
EditBox_ClearFocus(this)
this:SetText(E:Round(yOffset.currentValue))
end)
yOffset.text = yOffset:CreateFontString(nil, "OVERLAY", "GameFontNormal")
yOffset.text:SetPoint("RIGHT", yOffset, "LEFT", -4, 0)
yOffset.text:SetText("Y:")
yOffset:SetPoint("BOTTOMLEFT", nudgeFrame, "CENTER", 16, 8)
nudgeFrame.yOffset = yOffset
S:HandleEditBox(yOffset)
local resetButton = CreateFrame("Button", nudgeFrame:GetName().."ResetButton", nudgeFrame, "UIPanelButtonTemplate")
resetButton:SetText(RESET)
resetButton:SetPoint("TOP", nudgeFrame, "CENTER", 0, 2)
resetButton:SetWidth(100)
resetButton:SetHeight(25)
resetButton:SetScript("OnClick", function()
if(ElvUIMoverNudgeWindow.child.textString) then
E:ResetMovers(ElvUIMoverNudgeWindow.child.textString)
E:UpdateNudgeFrame(ElvUIMoverNudgeWindow.child)
end
end)
S:HandleButton(resetButton)
-- Up Button
local upButton = CreateFrame("Button", nudgeFrame:GetName().."PrevButton", nudgeFrame)
upButton:SetWidth(26)
upButton:SetHeight(26)
upButton:SetPoint("BOTTOMRIGHT", nudgeFrame, "BOTTOM", -6, 4)
upButton:SetScript("OnClick", function()
E:NudgeMover(nil, 1)
end)
upButton.icon = upButton:CreateTexture(nil, "ARTWORK")
upButton.icon:SetWidth(13)
upButton.icon:SetHeight(13)
upButton.icon:SetPoint("CENTER", 0, 0)
upButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
upButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
S:SquareButton_SetIcon(upButton, "UP")
S:HandleButton(upButton)
-- Down Button
local downButton = CreateFrame("Button", nudgeFrame:GetName().."DownButton", nudgeFrame)
downButton:SetWidth(26)
downButton:SetHeight(26)
downButton:SetPoint("BOTTOMLEFT", nudgeFrame, "BOTTOM", 6, 4)
downButton:SetScript("OnClick", function()
E:NudgeMover(nil, -1)
end)
downButton.icon = downButton:CreateTexture(nil, "ARTWORK")
downButton.icon:SetWidth(13)
downButton.icon:SetHeight(13)
downButton.icon:SetPoint("CENTER", 0, 0)
downButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
downButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
S:SquareButton_SetIcon(downButton, "DOWN")
S:HandleButton(downButton)
-- Left Button
local leftButton = CreateFrame("Button", nudgeFrame:GetName().."LeftButton", nudgeFrame)
leftButton:SetWidth(26)
leftButton:SetHeight(26)
leftButton:SetPoint("RIGHT", upButton, "LEFT", -6, 0)
leftButton:SetScript("OnClick", function()
E:NudgeMover(-1)
end)
leftButton.icon = leftButton:CreateTexture(nil, "ARTWORK")
leftButton.icon:SetWidth(13)
leftButton.icon:SetHeight(13)
leftButton.icon:SetPoint("CENTER", 0, 0)
leftButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
leftButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
S:SquareButton_SetIcon(leftButton, "LEFT")
S:HandleButton(leftButton)
-- Right Button
local rightButton = CreateFrame("Button", nudgeFrame:GetName().."RightButton", nudgeFrame)
rightButton:SetWidth(26)
rightButton:SetHeight(26)
rightButton:SetPoint("LEFT", downButton, "RIGHT", 6, 0)
rightButton:SetScript("OnClick", function()
E:NudgeMover(1)
end)
rightButton.icon = rightButton:CreateTexture(nil, "ARTWORK")
rightButton.icon:SetWidth(13)
rightButton.icon:SetHeight(13)
rightButton.icon:SetPoint("CENTER", 0, 0)
rightButton.icon:SetTexture([[Interface\AddOns\ElvUI\Media\Textures\SquareButtonTextures.blp]])
rightButton.icon:SetTexCoord(0.01562500, 0.20312500, 0.01562500, 0.20312500)
S:SquareButton_SetIcon(rightButton, "RIGHT")
S:HandleButton(rightButton)
end
+18
View File
@@ -0,0 +1,18 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="Math.lua"/>
<Script file="core.lua"/>
<Script file="fonts.lua"/>
<Script file="install.lua"/>
<Script file="pixelperfect.lua"/>
<Script file="toolkit.lua"/>
<Script file="commands.lua"/>
<Script file="staticpopups.lua"/>
<Script file="Movers.lua"/>
<Script file="Config.lua"/>
<Script file="tutorials.lua"/>
<Script file="distributor.lua"/>
<Script file="dropdown.lua"/>
<Script file="cooldowns.lua"/>
<Script file="aprilfools.lua"/>
<Script file="pluginInstaller.lua"/>
</Ui>
+403
View File
@@ -0,0 +1,403 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
--Cache global variables
--Lua functions
local select, unpack, assert, tonumber, type, pairs = select, unpack, assert, tonumber, type, pairs
local getn, tinsert, tremove = table.getn, tinsert, tremove
local abs, ceil, floor, modf, mod = math.abs, math.ceil, math.floor, math.modf, math.mod
local format, sub, upper, split, utf8sub = string.format, string.sub, string.upper, string.split, string.utf8sub
--WoW API / Variables
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
local CreateFrame = CreateFrame
function E:ShortValue(v)
if E.db.general.numberPrefixStyle == "METRIC" then
if abs(v) >= 1e9 then
return format("%.1fG", v / 1e9)
elseif abs(v) >= 1e6 then
return format("%.1fM", v / 1e6)
elseif abs(v) >= 1e3 then
return format("%.1fk", v / 1e3)
else
return format("%d", v)
end
elseif E.db.general.numberPrefixStyle == "CHINESE" then
if abs(v) >= 1e8 then
return format("%.1fY", v / 1e8)
elseif(abs(v) >= 1e4) then
return format("%.1fW", v / 1e4)
else
return format("%d", v)
end
else
if abs(v) >= 1e9 then
return format("%.1fB", v / 1e9)
elseif abs(v) >= 1e6 then
return format("%.1fM", v / 1e6)
elseif abs(v) >= 1e3 then
return format("%.1fK", v / 1e3)
else
return format("%d", v)
end
end
end
function E:IsEvenNumber(num)
return mod(num, 2) == 0
end
function E:ColorGradient(perc, ...)
if not arg[9] then return end
if perc >= 1 then
return arg[7], arg[8], arg[9]
elseif perc <= 0 then
return arg[1], arg[2], arg[3]
end
local num = getn(arg) / 3
local segment, relperc = math.modf(perc*(num-1))
local r1, g1, b1, r2, g2, b2 = select((segment*3)+1, unpack(arg))
return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
end
function E:Round(num, idp)
if idp and idp > 0 then
local mult = 10 ^ idp
return floor(num * mult + 0.5) / mult
end
return floor(num + 0.5)
end
function E:Truncate(v, decimals)
return 0
end
function E:RGBToHex(r, g, b)
r = r <= 1 and r >= 0 and r or 0
g = g <= 1 and g >= 0 and g or 0
b = b <= 1 and b >= 0 and b or 0
return format("|cff%02x%02x%02x", r*255, g*255, b*255)
end
function E:HexToRGB(hex)
local rhex, ghex, bhex = sub(hex, 1, 2), sub(hex, 3, 4), sub(hex, 5, 6)
return tonumber(rhex, 16), tonumber(ghex, 16), tonumber(bhex, 16)
end
function E:FramesOverlap(frameA, frameB)
if not frameA or not frameB then return end
local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
if not sA or not sB then return end
local frameALeft = frameA:GetLeft()
local frameARight = frameA:GetRight()
local frameABottom = frameA:GetBottom()
local frameATop = frameA:GetTop()
local frameBLeft = frameB:GetLeft()
local frameBRight = frameB:GetRight()
local frameBBottom = frameB:GetBottom()
local frameBTop = frameB:GetTop()
if not frameALeft or not frameARight or not frameABottom or not frameATop then return end
if not frameBLeft or not frameBRight or not frameBBottom or not frameBTop then return end
return ((frameALeft*sA) < (frameBRight*sB))
and ((frameBLeft*sB) < (frameARight*sA))
and ((frameABottom*sA) < (frameBTop*sB))
and ((frameBBottom*sB) < (frameATop*sA))
end
function E:GetScreenQuadrant(frame)
local x, y = frame:GetCenter()
local screenWidth = GetScreenWidth()
local screenHeight = GetScreenHeight()
local point
if not frame:GetCenter() then
return "UNKNOWN", frame:GetName()
end
if (x > (screenWidth / 3) and x < (screenWidth / 3)*2) and y > (screenHeight / 3)*2 then
point = "TOP"
elseif x < (screenWidth / 3) and y > (screenHeight / 3)*2 then
point = "TOPLEFT"
elseif x > (screenWidth / 3)*2 and y > (screenHeight / 3)*2 then
point = "TOPRIGHT"
elseif (x > (screenWidth / 3) and x < (screenWidth / 3)*2) and y < (screenHeight / 3) then
point = "BOTTOM"
elseif x < (screenWidth / 3) and y < (screenHeight / 3) then
point = "BOTTOMLEFT"
elseif x > (screenWidth / 3)*2 and y < (screenHeight / 3) then
point = "BOTTOMRIGHT"
elseif x < (screenWidth / 3) and (y > (screenHeight / 3) and y < (screenHeight / 3)*2) then
point = "LEFT"
elseif x > (screenWidth / 3)*2 and y < (screenHeight / 3)*2 and y > (screenHeight / 3) then
point = "RIGHT"
else
point = "CENTER"
end
return point
end
function E:GetXYOffset(position, override)
local default = E.Spacing
local x, y = override or default, override or default
if position == "TOP" then
return 0, y
elseif position == "TOPLEFT" then
return x, y
elseif position == "TOPRIGHT" then
return -x, y
elseif position == "BOTTOM" then
return 0, -y
elseif(position == "BOTTOMLEFT") then
return x, -y
elseif position == "BOTTOMRIGHT" then
return -x, -y
elseif position == "LEFT" then
return -x, 0
elseif position == "RIGHT" then
return x, 0
elseif position == "CENTER" then
return 0, 0
end
end
local styles = {
["CURRENT"] = "%s",
["CURRENT_MAX"] = "%s - %s",
["CURRENT_PERCENT"] = "%s - %.1f%%",
["CURRENT_MAX_PERCENT"] = "%s - %s | %.1f%%",
["PERCENT"] = "%.1f%%",
["DEFICIT"] = "-%s"
}
function E:GetFormattedText(style, min, max)
assert(styles[style], "Invalid format style: "..style)
assert(min, "You need to provide a current value. Usage: E:GetFormattedText(style, min, max)")
assert(max, "You need to provide a maximum value. Usage: E:GetFormattedText(style, min, max)")
if max == 0 then max = 1 end
local useStyle = styles[style]
if style == "DEFICIT" then
local deficit = max - min
if deficit <= 0 then
return ""
else
return format(useStyle, E:ShortValue(deficit))
end
elseif style == "PERCENT" then
local s = format(useStyle, min / max * 100)
return s
elseif style == "CURRENT" or ((style == "CURRENT_MAX" or style == "CURRENT_MAX_PERCENT" or style == "CURRENT_PERCENT") and min == max) then
return format(styles["CURRENT"], E:ShortValue(min))
elseif style == "CURRENT_MAX" then
return format(useStyle, E:ShortValue(min), E:ShortValue(max))
elseif style == "CURRENT_PERCENT" then
local s = format(useStyle, E:ShortValue(min), min / max * 100)
return s
elseif style == "CURRENT_MAX_PERCENT" then
local s = format(useStyle, E:ShortValue(min), E:ShortValue(max), min / max * 100)
return s
end
end
function E:AbbreviateString(string, allUpper)
local newString = ""
local words = {split(" ", string)}
for _, word in pairs(words) do
word = utf8sub(word, 1, 1)
if(allUpper) then
word = upper(word)
end
newString = newString..word
end
return newString
end
function E:ShortenString(string, numChars, dots)
local bytes = len(string)
if bytes <= numChars then
return string
else
local len, pos = 0, 1
while pos <= bytes do
len = len + 1
local c = byte(string, pos)
if c > 0 and c <= 127 then
pos = pos + 1
elseif c >= 192 and c <= 223 then
pos = pos + 2
elseif c >= 224 and c <= 239 then
pos = pos + 3
elseif c >= 240 and c <= 247 then
pos = pos + 4
end
if len == numChars then break end
end
if len == numChars and pos <= bytes then
return sub(string, 1, pos - 1)..(dots and "..." or "")
else
return string
end
end
end
local waitTable = {}
local waitFrame
function E:Delay(delay, func, arg)
if type(delay) ~= "number" or type(func) ~= "function" then
return false
end
if waitFrame == nil then
waitFrame = CreateFrame("Frame","WaitFrame", E.UIParent)
waitFrame:SetScript("onUpdate",function (_, elapse)
local count = getn(waitTable)
local i = 1
while i <= count do
local waitRecord = tremove(waitTable, i)
local d = tremove(waitRecord, 1)
local f = tremove(waitRecord, 1)
local p = tremove(waitRecord, 1)
if d > elapse then
tinsert(waitTable, i, {d-elapse, f, p})
i = i + 1
else
count = count - 1
f(unpack(p))
end
end
end)
end
tinsert(waitTable, {delay, func, {arg}})
return true
end
function E:StringTitle(str)
return gsub(str, "(.)", upper, 1)
end
E.TimeColors = {
[0] = "|cffeeeeee",
[1] = "|cffeeeeee",
[2] = "|cffeeeeee",
[3] = "|cffeeeeee",
[4] = "|cfffe0000"
}
E.TimeFormats = {
[0] = {"%dd", "%dd"},
[1] = {"%dh", "%dh"},
[2] = {"%dm", "%dm"},
[3] = {"%ds", "%d"},
[4] = {"%.1fs", "%.1f"}
}
local DAY, HOUR, MINUTE = 86400, 3600, 60
local DAYISH, HOURISH, MINUTEISH = HOUR * 23.5, MINUTE * 59.5, 59.5
local HALFDAYISH, HALFHOURISH, HALFMINUTEISH = DAY/2 + 0.5, HOUR/2 + 0.5, MINUTE/2 + 0.5
function E:GetTimeInfo(s, threshhold)
if s < MINUTE then
if s >= threshhold then
return floor(s), 3, 0.51
else
return s, 4, 0.051
end
elseif s < HOUR then
local minutes = floor((s/MINUTE)+.5)
return ceil(s / MINUTE), 2, minutes > 1 and (s - (minutes*MINUTE - HALFMINUTEISH)) or (s - MINUTEISH)
elseif s < DAY then
local hours = floor((s/HOUR)+.5)
return ceil(s / HOUR), 1, hours > 1 and (s - (hours*HOUR - HALFHOURISH)) or (s - HOURISH)
else
local days = floor((s/DAY)+.5)
return ceil(s / DAY), 0, days > 1 and (s - (days*DAY - HALFDAYISH)) or (s - DAYISH)
end
end
local COLOR_COPPER = "|cffeda55f"
local COLOR_SILVER = "|cffc7c7cf"
local COLOR_GOLD = "|cffffd700"
local ICON_COPPER = "|TInterface\\MoneyFrame\\UI-CopperIcon:12:12|t"
local ICON_SILVER = "|TInterface\\MoneyFrame\\UI-SilverIcon:12:12|t"
local ICON_GOLD = "|TInterface\\MoneyFrame\\UI-GoldIcon:12:12|t"
function E:FormatMoney(amount, style, textonly)
local coppername = textonly and L.copperabbrev or ICON_COPPER
local silvername = textonly and L.silverabbrev or ICON_SILVER
local goldname = textonly and L.goldabbrev or ICON_GOLD
local value = abs(amount)
local gold = floor(value / 10000)
local silver = floor(mod(value / 100, 100))
local copper = floor(mod(value, 100))
if not style or style == "SMART" then
local str = ""
if gold > 0 then
str = format("%d%s%s", gold, goldname, (silver > 0 or copper > 0) and " " or "")
end
if silver > 0 then
str = format("%s%d%s%s", str, silver, silvername, copper > 0 and " " or "")
end
if copper > 0 or value == 0 then
str = format("%s%d%s", str, copper, coppername)
end
return str
end
if style == "FULL" then
if gold > 0 then
return format("%d%s %d%s %d%s", gold, goldname, silver, silvername, copper, coppername)
elseif silver > 0 then
return format("%d%s %d%s", silver, silvername, copper, coppername)
else
return format("%d%s", copper, coppername)
end
elseif style == "SHORT" then
if gold > 0 then
return format("%.1f%s", amount / 10000, goldname)
elseif silver > 0 then
return format("%.1f%s", amount / 100, silvername)
else
return format("%d%s", amount, coppername)
end
elseif style == "SHORTINT" then
if gold > 0 then
return format("%d%s", gold, goldname)
elseif silver > 0 then
return format("%d%s", silver, silvername)
else
return format("%d%s", copper, coppername)
end
elseif style == "CONDENSED" then
if gold > 0 then
return format("%s%d|r.%s%02d|r.%s%02d|r", COLOR_GOLD, gold, COLOR_SILVER, silver, COLOR_COPPER, copper)
elseif silver > 0 then
return format("%s%d|r.%s%02d|r", COLOR_SILVER, silver, COLOR_COPPER, copper)
else
return format("%s%d|r", COLOR_COPPER, copper)
end
elseif style == "BLIZZARD" then
if gold > 0 then
return format("%s%s %d%s %d%s", gold, goldname, silver, silvername, copper, coppername)
elseif silver > 0 then
return format("%d%s %d%s", silver, silvername, copper, coppername)
else
return format("%d%s", copper, coppername)
end
end
return self:FormatMoney(amount, "SMART")
end
+496
View File
@@ -0,0 +1,496 @@
local E, L, V, P, G = unpack(ElvUI) --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local Sticky = LibStub("LibSimpleSticky-1.0")
local _G = getfenv()
local type, unpack, pairs = type, unpack, pairs
local format, split, find = string.format, string.split, string.find
local CreateFrame = CreateFrame
E.CreatedMovers = {}
E.DisabledMovers = {}
local function SizeChanged()
this.mover:SetWidth(this.dirtyWidth and this.dirtyWidth or this:GetWidth())
this.mover:SetHeight(this.dirtyHeight and this.dirtyHeight or this:GetHeight())
end
local function GetPoint(obj)
local point, anchor, secondaryPoint, x, y = obj:GetPoint()
if not anchor then anchor = ElvUIParent end
return format("%s,%s,%s,%d,%d", point, anchor:GetName(), secondaryPoint, E:Round(x), E:Round(y))
end
local function UpdateCoords()
local mover = this.child
local x, y, _, nudgePoint, nudgeInversePoint = E:CalculateMoverPoints(mover)
local coordX, coordY = E:GetXYOffset(nudgeInversePoint, 1)
ElvUIMoverNudgeWindow:ClearAllPoints()
ElvUIMoverNudgeWindow:SetPoint(nudgePoint, mover, nudgeInversePoint, coordX, coordY)
E:UpdateNudgeFrame(mover, x, y)
end
local isDragging = false
local coordFrame = CreateFrame("Frame")
coordFrame:SetScript("OnUpdate", UpdateCoords)
coordFrame:Hide()
local function CreateMover(parent, name, text, overlay, snapOffset, postdrag, shouldDisable)
if not parent then return end --If for some reason the parent isnt loaded yet
if E.CreatedMovers[name].Created then return end
if overlay == nil then overlay = true end
local point, anchor, secondaryPoint, x, y = split(",", GetPoint(parent))
local width = parent.dirtyWidth or parent:GetWidth()
local height = parent.dirtyHeight or parent:GetHeight()
local f = CreateFrame("Button", name, E.UIParent)
f:SetClampedToScreen(true)
f:RegisterForDrag("LeftButton", "RightButton")
f:EnableMouseWheel(true)
f:SetMovable(true)
f:SetWidth(width)
f:SetHeight(height)
E:SetTemplate(f, "Transparent", nil, nil, true)
f:Hide()
f.parent = parent
f.name = name
f.textString = text
f.postdrag = postdrag
f.overlay = overlay
f.snapOffset = snapOffset or -2
f.shouldDisable = shouldDisable
f:SetFrameLevel(parent:GetFrameLevel() + 1)
if(overlay == true) then
f:SetFrameStrata("DIALOG")
else
f:SetFrameStrata("BACKGROUND")
end
E.CreatedMovers[name].mover = f
E["snapBars"][getn(E["snapBars"]) + 1] = f
local fs = f:CreateFontString(nil, "OVERLAY")
E:FontTemplate(fs)
fs:SetJustifyH("CENTER")
fs:SetPoint("CENTER", f)
fs:SetText(text or name)
fs:SetTextColor(unpack(E["media"].rgbvaluecolor))
f:SetFontString(fs)
f.text = fs
if E.db["movers"] and E.db["movers"][name] then
if type(E.db["movers"][name]) == "table" then
f:SetPoint(E.db["movers"][name]["p"], E.UIParent, E.db["movers"][name]["p2"], E.db["movers"][name]["p3"], E.db["movers"][name]["p4"])
E.db["movers"][name] = GetPoint(f)
f:ClearAllPoints()
end
local delim
local anchorString = E.db["movers"][name]
if find(anchorString, "\031") then
delim = "\031"
elseif find(anchorString, ",") then
delim = ","
end
local point, anchor, secondaryPoint, x, y = split(delim, anchorString)
f:SetPoint(point, anchor, secondaryPoint, x, y)
else
f:SetPoint(point, anchor, secondaryPoint, x, y)
end
local function OnDragStart()
if E.db["general"].stickyFrames then
Sticky:StartMoving(this, E["snapBars"], f.snapOffset, f.snapOffset, f.snapOffset, f.snapOffset)
else
this:StartMoving()
end
coordFrame.child = this
coordFrame:Show()
isDragging = true
end
local function OnDragStop()
isDragging = false
if E.db["general"].stickyFrames then
Sticky:StopMoving(this)
else
this:StopMovingOrSizing()
end
local x, y, point = E:CalculateMoverPoints(this)
this:ClearAllPoints()
local overridePoint
if(this.positionOverride) then
if(this.positionOverride == "BOTTOM" or this.positionOverride == "TOP") then
overridePoint = "BOTTOM"
else
overridePoint = "BOTTOMLEFT"
end
end
this:SetPoint(this.positionOverride or point, E.UIParent, overridePoint and overridePoint or point, x, y)
if(this.positionOverride) then
this.parent:ClearAllPoints()
this.parent:SetPoint(this.positionOverride, this, this.positionOverride)
end
E:SaveMoverPosition(name)
if ElvUIMoverNudgeWindow then
E:UpdateNudgeFrame(this, x, y)
end
coordFrame.child = nil
coordFrame:Hide()
if postdrag ~= nil and type(postdrag) == "function" then
postdrag(this, E:GetScreenQuadrant(this))
end
this:SetUserPlaced(false)
end
local function OnEnter()
if isDragging then return end
this.text:SetTextColor(1, 1, 1)
ElvUIMoverNudgeWindow:Show()
E.AssignFrameToNudge(this)
coordFrame.child = this
coordFrame:GetScript("OnUpdate")(coordFrame)
end
local function OnMouseDown(button)
if button == "RightButton" then
isDragging = false
if E.db["general"].stickyFrames then
Sticky:StopMoving(this)
else
this:StopMovingOrSizing()
end
if IsControlKeyDown() and this.textString then
E:ResetMovers(this.textString)
elseif IsShiftKeyDown() then
this:Hide()
end
end
end
local function OnLeave(self)
if isDragging then return end
this.text:SetTextColor(unpack(E["media"].rgbvaluecolor))
end
local function OnShow(self)
this:SetBackdropBorderColor(unpack(E["media"].rgbvaluecolor))
end
local function OnMouseWheel(_, delta)
if(IsShiftKeyDown()) then
E:NudgeMover(delta)
else
E:NudgeMover(nil, delta)
end
end
f:SetScript("OnDragStart", OnDragStart)
f:SetScript("OnMouseUp", E.AssignFrameToNudge)
f:SetScript("OnDragStop", OnDragStop)
f:SetScript("OnEnter", OnEnter)
f:SetScript("OnMouseDown", OnMouseDown)
f:SetScript("OnLeave", OnLeave)
f:SetScript("OnShow", OnShow)
f:SetScript("OnMouseWheel", OnMouseWheel)
parent:SetScript("OnSizeChanged", SizeChanged)
parent.mover = f
parent:ClearAllPoints()
parent:SetPoint(point, f, 0, 0)
if postdrag ~= nil and type(postdrag) == "function" then
f:RegisterEvent("PLAYER_ENTERING_WORLD")
f:SetScript("OnEvent", function()
postdrag(f, E:GetScreenQuadrant(f))
this:UnregisterAllEvents()
end)
end
E.CreatedMovers[name].Created = true
end
function E:CalculateMoverPoints(mover, nudgeX, nudgeY)
local screenWidth, screenHeight, screenCenter = E.UIParent:GetRight(), E.UIParent:GetTop(), E.UIParent:GetCenter()
local x, y = mover:GetCenter()
local LEFT = screenWidth / 3
local RIGHT = screenWidth * 2 / 3
local TOP = screenHeight / 2
local point, nudgePoint, nudgeInversePoint
if(y >= TOP) then
point = "TOP"
nudgePoint = "TOP"
nudgeInversePoint = "BOTTOM"
y = -(screenHeight - mover:GetTop())
else
point = "BOTTOM"
nudgePoint = "BOTTOM"
nudgeInversePoint = "TOP"
y = mover:GetBottom()
end
if(x >= RIGHT) then
point = point .. "RIGHT"
nudgePoint = "RIGHT"
nudgeInversePoint = "LEFT"
x = mover:GetRight() - screenWidth
elseif(x <= LEFT) then
point = point .. "LEFT"
nudgePoint = "LEFT"
nudgeInversePoint = "RIGHT"
x = mover:GetLeft()
else
x = x - screenCenter
end
if(mover.positionOverride) then
if(mover.positionOverride == "TOPLEFT") then
x = mover:GetLeft() - E.diffGetLeft
y = mover:GetTop() - E.diffGetTop
elseif(mover.positionOverride == "TOPRIGHT") then
x = mover:GetRight() - E.diffGetRight
y = mover:GetTop() - E.diffGetTop
elseif(mover.positionOverride == "BOTTOMLEFT") then
x = mover:GetLeft() - E.diffGetLeft
y = mover:GetBottom() - E.diffGetBottom
elseif(mover.positionOverride == "BOTTOMRIGHT") then
x = mover:GetRight() - E.diffGetRight
y = mover:GetBottom() - E.diffGetBottom
elseif(mover.positionOverride == "BOTTOM") then
x = mover:GetCenter() - screenCenter
y = mover:GetBottom() - E.diffGetBottom
elseif(mover.positionOverride == "TOP") then
x = mover:GetCenter() - screenCenter
y = mover:GetTop() - E.diffGetTop
end
end
x = x + (nudgeX or 0)
y = y + (nudgeY or 0)
return x, y, point, nudgePoint, nudgeInversePoint
end
function E:UpdatePositionOverride(name)
if _G[name] and _G[name]:GetScript("OnDragStop") then
_G[name]:GetScript("OnDragStop")(_G[name])
end
end
function E:HasMoverBeenMoved(name)
if E.db["movers"] and E.db["movers"][name] then
return true
else
return false
end
end
function E:SaveMoverPosition(name)
if not _G[name] then return end
if not E.db.movers then E.db.movers = {} end
E.db.movers[name] = GetPoint(_G[name])
end
function E:SetMoverSnapOffset(name, offset)
if not _G[name] or not E.CreatedMovers[name] then return end
E.CreatedMovers[name].mover.snapOffset = offset or -2
E.CreatedMovers[name]["snapoffset"] = offset or -2
end
function E:SaveMoverDefaultPosition(name)
if not _G[name] then return end
E.CreatedMovers[name]["point"] = GetPoint(_G[name])
E.CreatedMovers[name]["postdrag"](_G[name], E:GetScreenQuadrant(_G[name]))
end
function E:CreateMover(parent, name, text, overlay, snapoffset, postdrag, moverTypes, shouldDisable)
if not moverTypes then moverTypes = "ALL,GENERAL" end
if E.CreatedMovers[name] == nil then
E.CreatedMovers[name] = {}
E.CreatedMovers[name]["parent"] = parent
E.CreatedMovers[name]["text"] = text
E.CreatedMovers[name]["overlay"] = overlay
E.CreatedMovers[name]["postdrag"] = postdrag
E.CreatedMovers[name]["snapoffset"] = snapOffset
E.CreatedMovers[name]["point"] = GetPoint(parent)
E.CreatedMovers[name]["shouldDisable"] = shouldDisable
E.CreatedMovers[name]["type"] = {}
local types = {split(",", moverTypes)}
for i = 1, getn(types) do
local moverType = types[i]
E.CreatedMovers[name]["type"][moverType] = true
end
end
CreateMover(parent, name, text, overlay, snapoffset, postdrag, shouldDisable)
end
function E:ToggleMovers(show, moverType)
self.configMode = show
for name, _ in pairs(E.CreatedMovers) do
if not show then
_G[name]:Hide()
else
if E.CreatedMovers[name]["type"][moverType] then
_G[name]:Show()
else
_G[name]:Hide()
end
end
end
end
function E:DisableMover(name)
if(self.DisabledMovers[name]) then return end
if(not self.CreatedMovers[name]) then
error("mover doesn't exist")
end
self.DisabledMovers[name] = {}
for x, y in pairs(self.CreatedMovers[name]) do
self.DisabledMovers[name][x] = y
end
if(self.configMode) then
_G[name]:Hide()
end
self.CreatedMovers[name] = nil
end
function E:EnableMover(name)
if(self.CreatedMovers[name]) then return end
if(not self.DisabledMovers[name]) then
error("mover doesn't exist")
end
self.CreatedMovers[name] = {}
for x, y in pairs(self.DisabledMovers[name]) do
self.CreatedMovers[name][x] = y
end
--Commented out, as it created an issue with trying to reset a mover after having used EnableMover on it. Not sure if this code is even needed anymore.
--[[
if(E.db["movers"] and E.db["movers"][name] and type(E.db["movers"][name]) == "string") then
self.CreatedMovers[name]["point"] = E.db["movers"][name]
end
]]
if(self.configMode) then
_G[name]:Show()
end
self.DisabledMovers[name] = nil
end
function E:ResetMovers(arg)
if arg == "" or arg == nil then
for name, _ in pairs(E.CreatedMovers) do
local f = _G[name]
local point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
f:ClearAllPoints()
f:SetPoint(point, anchor, secondaryPoint, x, y)
for key, value in pairs(E.CreatedMovers[name]) do
if key == "postdrag" and type(value) == "function" then
value(f, E:GetScreenQuadrant(f))
end
end
end
self.db.movers = nil
else
for name, _ in pairs(E.CreatedMovers) do
for key, value in pairs(E.CreatedMovers[name]) do
if key == "text" then
if arg == value then
local f = _G[name]
local point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
f:ClearAllPoints()
f:SetPoint(point, anchor, secondaryPoint, x, y)
if self.db.movers then
self.db.movers[name] = nil
end
if E.CreatedMovers[name]["postdrag"] ~= nil and type(E.CreatedMovers[name]["postdrag"]) == "function" then
E.CreatedMovers[name]["postdrag"](f, E:GetScreenQuadrant(f))
end
end
end
end
end
end
end
--Profile Change
function E:SetMoversPositions()
for name in pairs(E.DisabledMovers) do
local shouldDisable = ((E.DisabledMovers[name].shouldDisable and E.DisabledMovers[name]["shouldDisable"]()) or false)
if not shouldDisable then
E:EnableMover(name)
end
end
for name, _ in pairs(E.CreatedMovers) do
local f = _G[name]
local point, anchor, secondaryPoint, x, y
if E.db["movers"] and E.db["movers"][name] and type(E.db["movers"][name]) == "string" then
local delim
local anchorString = E.db["movers"][name]
if(find(anchorString, "\031")) then
delim = "\031"
elseif(find(anchorString, ",")) then
delim = ","
end
point, anchor, secondaryPoint, x, y = split(delim, anchorString)
f:ClearAllPoints()
f:SetPoint(point, anchor, secondaryPoint, x, y)
elseif f then
point, anchor, secondaryPoint, x, y = split(",", E.CreatedMovers[name]["point"])
f:ClearAllPoints()
f:SetPoint(point, anchor, secondaryPoint, x, y)
end
end
end
--Called from core.lua
function E:LoadMovers()
for n, _ in pairs(E.CreatedMovers) do
local p, t, o, so, pd
for key, value in pairs(E.CreatedMovers[n]) do
if key == "parent" then
p = value
elseif key == "text" then
t = value
elseif key == "overlay" then
o = value
elseif key == "snapoffset" then
so = value
elseif key == "postdrag" then
pd = value
end
end
CreateMover(p, n, t, o, so, pd)
end
end
+165
View File
@@ -0,0 +1,165 @@
local E, L, V, P, G = unpack(ElvUI);
local _G = getfenv();
local tonumber, type = tonumber, type;
local format, lower = string.format, string.lower;
local InCombatLockdown = InCombatLockdown;
local UIFrameFadeOut, UIFrameFadeIn = UIFrameFadeOut, UIFrameFadeIn;
local EnableAddOn, DisableAddOn, DisableAllAddOns = EnableAddOn, DisableAddOn, DisableAllAddOns;
local SetCVar = SetCVar;
local ReloadUI = ReloadUI;
local debugprofilestart, debugprofilestop = debugprofilestart, debugprofilestop;
local UpdateAddOnCPUUsage, GetAddOnCPUUsage = UpdateAddOnCPUUsage, GetAddOnCPUUsage;
local ResetCPUUsage = ResetCPUUsage;
local GetAddOnInfo = GetAddOnInfo;
local ERR_NOT_IN_COMBAT = ERR_NOT_IN_COMBAT;
function E:EnableAddon(addon)
local _, _, _, _, _, reason, _ = GetAddOnInfo(addon);
if(reason ~= "MISSING") then
EnableAddOn(addon);
ReloadUI();
else
E:Print(format("Addon '%s' not found.", addon));
end
end
function E:DisableAddon(addon)
local _, _, _, _, _, reason, _ = GetAddOnInfo(addon);
if(reason ~= "MISSING") then
DisableAddOn(addon);
ReloadUI();
else
E:Print(format("Addon '%s' not found.", addon));
end
end
function FarmMode()
if E.private.general.minimap.enable ~= true then return end
if Minimap:IsShown() then
UIFrameFadeOut(Minimap, 0.3)
UIFrameFadeIn(FarmModeMap, 0.3)
Minimap.fadeInfo.finishedFunc = function() Minimap:Hide(); _G.MinimapZoomIn:Click(); _G.MinimapZoomOut:Click(); Minimap:SetAlpha(1) end
FarmModeMap.enabled = true;
else
UIFrameFadeOut(FarmModeMap, 0.3)
UIFrameFadeIn(Minimap, 0.3)
FarmModeMap.fadeInfo.finishedFunc = function() FarmModeMap:Hide(); _G.MinimapZoomIn:Click(); _G.MinimapZoomOut:Click(); Minimap:SetAlpha(1) end
FarmModeMap.enabled = false
end
end
function E:FarmMode(msg)
if(E.private.general.minimap.enable ~= true) then return; end
if(msg and type(tonumber(msg)) == "number" and tonumber(msg) <= 500 and tonumber(msg) >= 20 and not InCombatLockdown()) then
E.db.farmSize = tonumber(msg);
FarmModeMap:Size(tonumber(msg));
end
FarmMode();
end
function E:Grid(msg)
if(msg and type(tonumber(msg)) == "number" and tonumber(msg) <= 256 and tonumber(msg) >= 4) then
E.db.gridSize = msg;
E:Grid_Show();
else
if(EGrid) then
E:Grid_Hide();
else
E:Grid_Show();
end
end
end
function E:LuaError(msg)
msg = lower(msg);
if(msg == "on") then
DisableAllAddOns();
EnableAddOn("ElvUI");
EnableAddOn("ElvUI_Config");
SetCVar("scriptErrors", 1);
ReloadUI();
elseif(msg == "off") then
SetCVar("scriptErrors", 0);
E:Print("Lua errors off.");
else
E:Print("/luaerror on - /luaerror off");
end
end
function E:BGStats()
local DT = E:GetModule("DataTexts");
DT.ForceHideBGStats = nil;
DT:LoadDataTexts();
E:Print(L["Battleground datatexts will now show again if you are inside a battleground."]);
end
local function OnCallback(command)
MacroEditBox:GetScript("OnEvent")(MacroEditBox, "EXECUTE_CHAT_LINE", command);
end
function E:DelayScriptCall(msg)
local secs, command = msg:match("^([^%s]+)%s+(.*)$");
secs = tonumber(secs);
if((not secs) or (getn(command) == 0)) then
self:Print("usage: /in <seconds> <command>");
self:Print("example: /in 1.5 /say hi");
else
E:ScheduleTimer(OnCallback, secs, command);
end
end
local num_frames = 0;
local function OnUpdate()
num_frames = num_frames + 1;
end
local f = CreateFrame("Frame");
f:Hide();
f:SetScript("OnUpdate", OnUpdate);
local toggleMode = false;
function E:GetCPUImpact()
if(not toggleMode) then
ResetCPUUsage();
num_frames = 0;
debugprofilestart();
f:Show();
toggleMode = true;
self:Print("CPU Impact being calculated, type /cpuimpact to get results when you are ready.");
else
f:Hide()
local ms_passed = debugprofilestop();
UpdateAddOnCPUUsage();
self:Print("Consumed " .. (GetAddOnCPUUsage("ElvUI") / num_frames) .. " milliseconds per frame. Each frame took " .. (ms_passed / num_frames) .. " to render.");
toggleMode = false;
end
end
function E:LoadCommands()
self:RegisterChatCommand("in", "DelayScriptCall");
self:RegisterChatCommand("ec", "ToggleConfig");
self:RegisterChatCommand("elvui", "ToggleConfig");
self:RegisterChatCommand("cpuimpact", "GetCPUImpact");
self:RegisterChatCommand("cpuusage", "GetTopCPUFunc");
self:RegisterChatCommand("bgstats", "BGStats");
self:RegisterChatCommand("hellokitty", "HelloKittyToggle");
self:RegisterChatCommand("hellokittyfix", "HelloKittyFix");
self:RegisterChatCommand("harlemshake", "HarlemShakeToggle");
self:RegisterChatCommand("luaerror", "LuaError");
self:RegisterChatCommand("egrid", "Grid");
self:RegisterChatCommand("moveui", "ToggleConfigMode");
self:RegisterChatCommand("resetui", "ResetUI");
self:RegisterChatCommand("enable", "EnableAddon");
self:RegisterChatCommand("disable", "DisableAddon");
self:RegisterChatCommand("farmmode", "FarmMode");
--self:RegisterChatCommand("aprilfools", "");
--if E:GetModule("ActionBars") and E.private.actionbar.enable then
-- self:RegisterChatCommand("kb", E:GetModule("ActionBars").ActivateBindMode);
--end
end
+138
View File
@@ -0,0 +1,138 @@
local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local floor = math.floor;
local GetTime = GetTime;
local CreateFrame = CreateFrame;
local hooksecurefunc = hooksecurefunc;
local ICON_SIZE = 36 --the normal size for an icon (don't change this)
local FONT_SIZE = 20 --the base font size to use at a scale of 1
local MIN_SCALE = 0.5 --the minimum scale we want to show cooldown counts at, anything below this will be hidden
local MIN_DURATION = 1.5 --the minimum duration to show cooldown text for
local TimeColors = {
[0] = "|cfffefefe",
[1] = "|cfffefefe",
[2] = "|cfffefefe",
[3] = "|cfffefefe",
[4] = "|cfffe0000",
}
local function Cooldown_OnUpdate(cd, elapsed)
if cd.nextUpdate > 0 then
cd.nextUpdate = cd.nextUpdate - elapsed
return
end
local remain = cd.duration - (GetTime() - cd.start)
if remain > 0.05 then
if (cd.fontScale * cd:GetEffectiveScale() / UIParent:GetScale()) < MIN_SCALE then
cd.text:SetText("")
cd.nextUpdate = 500
else
local timervalue, formatid
timervalue, formatid, cd.nextUpdate = E:GetTimeInfo(remain, E.db.cooldown.threshold)
cd.text:SetFormattedText(("%s%s|r"):format(TimeColors[formatid], E.TimeFormats[formatid][2]), timervalue)
end
else
E:Cooldown_StopTimer(cd)
end
end
function E:Cooldown_OnSizeChanged(cd, width)
local fontScale = floor(width +.5) / ICON_SIZE
local override = cd:GetParent():GetParent().SizeOverride
if override then
fontScale = override / FONT_SIZE
end
if fontScale == cd.fontScale then
return
end
cd.fontScale = fontScale
if fontScale < MIN_SCALE and not override then
cd:Hide()
else
cd:Show()
cd.text:FontTemplate(nil, fontScale * FONT_SIZE, "OUTLINE")
if cd.enabled then
self:Cooldown_ForceUpdate(cd)
end
end
end
function E:Cooldown_ForceUpdate(cd)
cd.nextUpdate = 0
cd:Show()
end
function E:Cooldown_StopTimer(cd)
cd.enabled = nil
cd:Hide()
end
function E:CreateCooldownTimer(parent)
local scaler = CreateFrame("Frame", nil, parent)
scaler:SetAllPoints()
local timer = CreateFrame("Frame", nil, scaler);
timer:Hide()
timer:SetAllPoints()
timer:SetScript("OnUpdate", Cooldown_OnUpdate)
local text = timer:CreateFontString(nil, "OVERLAY")
text:SetPoint("CENTER", 1, 1)
text:SetJustifyH("CENTER")
timer.text = text
self:Cooldown_OnSizeChanged(timer, parent:GetSize())
parent:SetScript("OnSizeChanged", function(_, w, h) self:Cooldown_OnSizeChanged(timer, w, h) end)
parent.timer = timer
return timer
end
function E:OnSetCooldown(start, duration)
if(self.noOCC) then return end
if start > 0 and duration > MIN_DURATION then
local timer = self.timer or E:CreateCooldownTimer(self)
timer.start = start
timer.duration = duration
timer.enabled = true
timer.nextUpdate = 0
if timer.fontScale >= MIN_SCALE then timer:Show() end
else
local timer = self.timer
if timer then
E:Cooldown_StopTimer(timer)
return
end
end
end
function E:RegisterCooldown(cooldown)
if(not E.private.cooldown.enable or cooldown.isHooked) then return end
--hooksecurefunc(cooldown, "SetCooldown", E.OnSetCooldown)
cooldown.isHooked = true
end
function E:UpdateCooldownSettings()
local color = self.db.cooldown.expiringColor
TimeColors[4] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that are soon to expire
color = self.db.cooldown.secondsColor
TimeColors[3] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have seconds remaining
color = self.db.cooldown.minutesColor
TimeColors[2] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have minutes remaining
color = self.db.cooldown.hoursColor
TimeColors[1] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have hours remaining
color = self.db.cooldown.daysColor
TimeColors[0] = E:RGBToHex(color.r, color.g, color.b) -- color for timers that have days remaining
end
File diff suppressed because it is too large Load Diff
View File
+88
View File
@@ -0,0 +1,88 @@
local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local LSM = LibStub("LibSharedMedia-3.0")
local SetCVar = SetCVar;
local function SetFont(obj, font, size, style, r, g, b, sr, sg, sb, sox, soy)
if(not obj) then return; end
obj:SetFont(font, size, style)
if sr and sg and sb then obj:SetShadowColor(sr, sg, sb) end
if sox and soy then obj:SetShadowOffset(sox, soy) end
if r and g and b then obj:SetTextColor(r, g, b)
elseif r then obj:SetAlpha(r) end
end
function E:UpdateBlizzardFonts()
local NORMAL = self["media"].normFont;
local COMBAT = LSM:Fetch("font", self.private.general.dmgfont);
local NUMBER = self["media"].normFont;
local NAMEFONT = LSM:Fetch("font", self.private.general.namefont);
local MONOCHROME = "";
UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = 12
CHAT_FONT_HEIGHTS = {10, 12, 13, 14, 15, 16, 17, 18, 19, 20}
UNIT_NAME_FONT = NAMEFONT;
NAMEPLATE_FONT = NAMEFONT;
DAMAGE_TEXT_FONT = COMBAT;
STANDARD_TEXT_FONT = NORMAL;
if self.db.general.font == "Homespun" then
MONOCHROME = "MONOCHROME"
end
if self.eyefinity then
-- damage are huge on eyefinity, so we disable it
InterfaceOptionsCombatTextPanelTargetDamage:Hide()
InterfaceOptionsCombatTextPanelPeriodicDamage:Hide()
InterfaceOptionsCombatTextPanelPetDamage:Hide()
InterfaceOptionsCombatTextPanelHealing:Hide()
SetCVar("CombatLogPeriodicSpells",0)
SetCVar("PetMeleeDamage",0)
SetCVar("CombatDamage",0)
SetCVar("CombatHealing",0)
-- set an invisible font for xp, honor kill, etc
local INVISIBLE = "Interface\\Addons\\ElvUI\\Media\\Fonts\\Invisible.ttf"
COMBAT = INVISIBLE
end
if(self.private.general.replaceBlizzFonts) then
SetFont(GameTooltipHeader, NORMAL, self.db.general.fontSize);
SetFont(NumberFont_OutlineThick_Mono_Small, NUMBER, self.db.general.fontSize, "OUTLINE");
SetFont(NumberFont_Outline_Huge, NUMBER, 28, MONOCHROME.."THICKOUTLINE", 28);
SetFont(NumberFont_Outline_Large, NUMBER, 15, MONOCHROME.."OUTLINE");
SetFont(NumberFont_Outline_Med, NUMBER, self.db.general.fontSize, "OUTLINE");
SetFont(NumberFont_Shadow_Med, NORMAL, self.db.general.fontSize);
SetFont(NumberFont_Shadow_Small, NORMAL, self.db.general.fontSize);
SetFont(QuestFont, NORMAL, self.db.general.fontSize);
SetFont(QuestFont_Large, NORMAL, 14);
SetFont(SystemFont_Large, NORMAL, 15);
SetFont(GameFontNormalMed3, NORMAL, 15);
SetFont(SystemFont_Shadow_Huge1, NORMAL, 20, MONOCHROME .. "OUTLINE");
SetFont(SystemFont_Med1, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_Med3, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_OutlineThick_Huge2, NORMAL, 20, MONOCHROME .. "THICKOUTLINE");
SetFont(SystemFont_Outline_Small, NUMBER, self.db.general.fontSize, "OUTLINE");
SetFont(SystemFont_Shadow_Large, NORMAL, 15);
SetFont(SystemFont_Shadow_Med1, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_Shadow_Med3, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_Shadow_Outline_Huge2, NORMAL, 20, MONOCHROME .. "OUTLINE");
SetFont(SystemFont_Shadow_Small, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_Small, NORMAL, self.db.general.fontSize);
SetFont(SystemFont_Tiny, NORMAL, self.db.general.fontSize);
SetFont(Tooltip_Med, NORMAL, self.db.general.fontSize);
SetFont(Tooltip_Small, NORMAL, self.db.general.fontSize);
SetFont(FriendsFont_Normal, NORMAL, self.db.general.fontSize);
SetFont(FriendsFont_Small, NORMAL, self.db.general.fontSize);
SetFont(FriendsFont_Large, NORMAL, self.db.general.fontSize);
SetFont(FriendsFont_UserText, NORMAL, self.db.general.fontSize);
SetFont(SpellFont_Small, NORMAL, self.db.general.fontSize*0.9);
SetFont(ZoneTextString, NORMAL, 32, MONOCHROME .. "OUTLINE");
SetFont(SubZoneTextString, NORMAL, 25, MONOCHROME .. "OUTLINE");
SetFont(PVPInfoTextString, NORMAL, 22, MONOCHROME .. "OUTLINE");
SetFont(PVPArenaTextString, NORMAL, 22, MONOCHROME .. "OUTLINE");
SetFont(CombatTextFont, COMBAT, 25, MONOCHROME .. "OUTLINE");
end
end
View File
+137
View File
@@ -0,0 +1,137 @@
local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local abs, floor, min, max = math.abs, math.floor, math.min, math.max;
local match = string.match;
local IsMacClient = IsMacClient;
local GetCVar, SetCVar = GetCVar, SetCVar;
local GetScreenHeight, GetScreenWidth = GetScreenHeight, GetScreenWidth;
local scale
function E:UIScale(event)
if IsMacClient() and self.global.screenheight and self.global.screenwidth and (self.screenheight ~= self.global.screenheight or self.screenwidth ~= self.global.screenwidth) then
self.screenheight = self.global.screenheight
self.screenwidth = self.global.screenwidth
end
if(GetCVar("UIScale")) then
self.global.uiScale = GetCVar("UIScale");
end
local minScale = self.global.general.minUiScale or 0.64;
if(self.global.general.autoScale) then
scale = max(minScale, min(1.00, 768/self.screenheight));
else
scale = max(minScale, min(1.00, self.global.uiScale or UIParent:GetScale() or 768/self.screenheight));
end
if self.screenwidth < 1600 then
self.lowversion = true;
elseif self.screenwidth >= 3840 and self.global.general.eyefinity then
local width = self.screenwidth;
local height = self.screenheight;
-- because some user enable bezel compensation, we need to find the real width of a single monitor.
-- I don't know how it really work, but i'm assuming they add pixel to width to compensate the bezel. :P
-- HQ resolution
if width >= 9840 then width = 3280; end -- WQSXGA
if width >= 7680 and width < 9840 then width = 2560; end -- WQXGA
if width >= 5760 and width < 7680 then width = 1920; end -- WUXGA & HDTV
if width >= 5040 and width < 5760 then width = 1680; end -- WSXGA+
-- adding height condition here to be sure it work with bezel compensation because WSXGA+ and UXGA/HD+ got approx same width
if width >= 4800 and width < 5760 and height == 900 then width = 1600; end -- UXGA & HD+
-- low resolution screen
if width >= 4320 and width < 4800 then width = 1440; end -- WSXGA
if width >= 4080 and width < 4320 then width = 1360; end -- WXGA
if width >= 3840 and width < 4080 then width = 1224; end -- SXGA & SXGA (UVGA) & WXGA & HDTV
-- yep, now set ElvUI to lower resolution if screen #1 width < 1600
if width < 1600 then
self.lowversion = true;
end
-- register a constant, we will need it later for launch.lua
self.eyefinity = width;
end
for screenwidth, screenheight in string.gfind(GetCVar("gxResolution"), "(.+)x(.+)") do
self.mult = 768/screenheight/scale
self.UIParent:SetWidth(screenwidth)
self.UIParent:SetHeight(screenheight)
end
--self.mult = 1;
self.Spacing = self.PixelMode and 0 or self.mult;
self.Border = (self.PixelMode and self.mult or self.mult*2);
--Set UIScale, NOTE: SetCVar for UIScale can cause taints so only do this when we need to..
if E.Round and E:Round(UIParent:GetScale(), 5) ~= E:Round(scale, 5) and (event == "PLAYER_LOGIN") then
SetCVar("UseUIScale", 1);
SetCVar("UIScale", scale);
WorldMapFrame.hasTaint = true;
end
if (event == "PLAYER_LOGIN" or event == "UPDATE_FLOATING_CHAT_WINDOWS") then
if IsMacClient() then
self.global.screenheight = floor(GetScreenHeight()*100+.5)/100
self.global.screenwidth = floor(GetScreenWidth()*100+.5)/100
end
--Resize self.UIParent if Eyefinity is on.
if self.eyefinity then
local width = self.eyefinity;
local height = self.screenheight;
-- if autoscale is off, find a new width value of self.UIParent for screen #1.
if not self.global.general.autoScale or height > 1200 then
local h = UIParent:GetHeight();
local ratio = self.screenheight / h;
local w = self.eyefinity / ratio;
width = w;
height = h;
end
self.UIParent:SetWidth(width);
self.UIParent:SetHeight(height);
else
--[[Eyefinity Test mode
Resize the E.UIParent to be smaller than it should be, all objects inside should relocate.
Dragging moveable frames outside the box and reloading the UI ensures that they are saving position correctly.
]]
--self.UIParent:SetSize(UIParent:GetWidth() - 250, UIParent:GetHeight() - 250);
--self.UIParent:SetWidth(UIParent:GetWidth());
--self.UIParent:SetHeight(UIParent:GetHeight());
end
self.UIParent:ClearAllPoints();
self.UIParent:SetPoint("CENTER", UIParent);
self.diffGetLeft = E:Round(abs(UIParent:GetLeft() - self.UIParent:GetLeft()));
self.diffGetRight = E:Round(abs(UIParent:GetRight() - self.UIParent:GetRight()));
self.diffGetTop = E:Round(abs(UIParent:GetTop() - self.UIParent:GetTop()));
self.diffGetBottom = E:Round(abs(UIParent:GetBottom() - self.UIParent:GetBottom()));
local change
if E.Round then
change = abs((E:Round(UIParent:GetScale(), 5) * 100) - (E:Round(scale, 5) * 100))
end
if event == "UPDATE_FLOATING_CHAT_WINDOWS" and change and change > 1 and self.global.general.autoScale then
E:StaticPopup_Show("FAILED_UISCALE")
elseif event == "UPDATE_FLOATING_CHAT_WINDOWS" and change and change > 1 then
E:StaticPopup_Show("CONFIG_RL")
end
self:UnregisterEvent("PLAYER_LOGIN")
end
end
-- pixel perfect script of custom ui scale.
function E:Scale(x)
return self.mult*floor(x/self.mult+.5);
end
File diff suppressed because it is too large Load Diff
+310
View File
@@ -0,0 +1,310 @@
local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local LSM = LibStub("LibSharedMedia-3.0")
local _G = getfenv();
local unpack, type, select, getmetatable = unpack, type, select, getmetatable;
local CreateFrame = CreateFrame;
local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
local CUSTOM_CLASS_COLORS = CUSTOM_CLASS_COLORS;
--Preload shit..
E.mult = 1;
local backdropr, backdropg, backdropb, backdropa, borderr, borderg, borderb = 0, 0, 0, 1, 0, 0, 0;
local function GetTemplate(t, isUnitFrameElement)
backdropa = 1
if t == "ClassColor" then
if(CUSTOM_CLASS_COLORS) then
borderr, borderg, borderb = CUSTOM_CLASS_COLORS[E.myclass].r, CUSTOM_CLASS_COLORS[E.myclass].g, CUSTOM_CLASS_COLORS[E.myclass].b;
else
borderr, borderg, borderb = RAID_CLASS_COLORS[E.myclass].r, RAID_CLASS_COLORS[E.myclass].g, RAID_CLASS_COLORS[E.myclass].b;
end
if t ~= "Transparent" then
backdropr, backdropg, backdropb = unpack(E["media"].backdropcolor)
else
backdropr, backdropg, backdropb, backdropa = unpack(E["media"].backdropfadecolor)
end
elseif t == "Transparent" then
if isUnitFrameElement then
borderr, borderg, borderb = unpack(E["media"].unitframeBorderColor)
else
borderr, borderg, borderb = unpack(E["media"].bordercolor)
end
backdropr, backdropg, backdropb, backdropa = unpack(E["media"].backdropfadecolor)
else
if isUnitFrameElement then
borderr, borderg, borderb = unpack(E["media"].unitframeBorderColor)
else
borderr, borderg, borderb = unpack(E["media"].bordercolor)
end
backdropr, backdropg, backdropb = unpack(E["media"].backdropcolor)
end
end
function E:Size(frame, width, height)
assert(width);
frame:SetSize(E:Scale(width), E:Scale(height or width));
end
function E:Width(frame, width)
frame:SetWidth(E:Scale(width))
end
function E:Height(frame, height)
assert(height)
frame:SetHeight(E:Scale(height));
end
function E:Point(obj, arg1, arg2, arg3, arg4, arg5)
if(arg2 == nil) then
arg2 = obj:GetParent();
end
if type(arg1)=="number" then arg1 = E:Scale(arg1) end
if type(arg2)=="number" then arg2 = E:Scale(arg2) end
if type(arg3)=="number" then arg3 = E:Scale(arg3) end
if type(arg4)=="number" then arg4 = E:Scale(arg4) end
if type(arg5)=="number" then arg5 = E:Scale(arg5) end
obj:SetPoint(arg1, arg2, arg3, arg4, arg5)
end
function E:SetOutside(obj, anchor, xOffset, yOffset, anchor2)
xOffset = xOffset or E.Border
yOffset = yOffset or E.Border
anchor = anchor or obj:GetParent()
assert(anchor);
if obj:GetPoint() then
obj:ClearAllPoints()
end
obj:SetPoint("TOPLEFT", anchor, "TOPLEFT", -xOffset, yOffset)
obj:SetPoint("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", xOffset, -yOffset)
end
function E:SetInside(obj, anchor, xOffset, yOffset, anchor2)
xOffset = xOffset or E.Border
yOffset = yOffset or E.Border
anchor = anchor or obj:GetParent()
assert(anchor);
if obj:GetPoint() then
obj:ClearAllPoints()
end
obj:SetPoint("TOPLEFT", anchor, "TOPLEFT", xOffset, -yOffset)
obj:SetPoint("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset)
end
function E:SetTemplate(f, t, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
GetTemplate(t, isUnitFrameElement)
if(t) then
f.template = t;
end
if(glossTex) then
f.glossTex = glossTex;
end
if(ignoreUpdates) then
f.ignoreUpdates = ignoreUpdates;
end
if(forcePixelMode) then
f.forcePixelMode = forcePixelMode
end
local bgFile = E.media.blankTex;
if(glossTex) then
bgFile = E.media.glossTex;
end
if(isUnitFrameElement) then
f.isUnitFrameElement = isUnitFrameElement
end
if(t ~= "NoBackdrop") then
if(E.private.general.pixelPerfect or f.forcePixelMode) then
f:SetBackdrop({
bgFile = bgFile,
edgeFile = E["media"].blankTex,
tile = false, tileSize = 0, edgeSize = E.mult,
insets = {left = 0, right = 0, top = 0, bottom = 0}
});
else
f:SetBackdrop({
bgFile = bgFile,
edgeFile = E["media"].blankTex,
tile = false, tileSize = 0, edgeSize = E.mult,
insets = {left = -E.mult, right = -E.mult, top = -E.mult, bottom = -E.mult}
});
end
if not f.oborder and not f.iborder and not E.private.general.pixelPerfect and not f.forcePixelMode then
local border = CreateFrame("Frame", nil, f)
E:SetInside(border, f, E.mult, E.mult)
border:SetBackdrop({
edgeFile = E["media"].blankTex,
edgeSize = E.mult,
insets = {left = E.mult, right = E.mult, top = E.mult, bottom = E.mult}
});
border:SetBackdropBorderColor(0, 0, 0, 1)
f.iborder = border
if f.oborder then return end
border = CreateFrame("Frame", nil, f)
E:SetOutside(border, f, E.mult, E.mult)
border:SetFrameLevel(f:GetFrameLevel() + 1)
border:SetBackdrop({
edgeFile = E["media"].blankTex,
edgeSize = E.mult,
insets = {left = E.mult, right = E.mult, top = E.mult, bottom = E.mult}
});
border:SetBackdropBorderColor(0, 0, 0, 1)
f.oborder = border
end
else
f:SetBackdrop(nil);
end
f:SetBackdropColor(backdropr, backdropg, backdropb, backdropa)
f:SetBackdropBorderColor(borderr, borderg, borderb)
if(not f.ignoreUpdates) then
if f.isUnitFrameElement then
E["unitFrameElements"][f] = true
else
E["frames"][f] = true
end
end
end
function E:CreateBackdrop(f, t, tex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
if not f then return end
if(not t) then t = "Default"; end
local b = CreateFrame("Frame", nil, f);
if(f.forcePixelMode or forcePixelMode) then
E:SetOutside(b, nil, E.mult, E.mult);
else
E:SetOutside(b);
end
E:SetTemplate(b, t, tex, ignoreUpdates, forcePixelMode, isUnitFrameElement);
if(f:GetFrameLevel() - 1 >= 0) then
b:SetFrameLevel(f:GetFrameLevel() - 1);
else
b:SetFrameLevel(0);
end
f.backdrop = b;
end
function E:CreateShadow(f)
if f.shadow then return end
borderr, borderg, borderb = 0, 0, 0
backdropr, backdropg, backdropb = 0, 0, 0
local shadow = CreateFrame("Frame", nil, f)
shadow:SetFrameLevel(1)
shadow:SetFrameStrata(f:GetFrameStrata())
E:SetOutside(shadow, f, 3, 3)
shadow:SetBackdrop({
edgeFile = LSM:Fetch("border", "ElvUI GlowBorder"), edgeSize = E:Scale(3),
insets = {left = E:Scale(5), right = E:Scale(5), top = E:Scale(5), bottom = E:Scale(5)}
});
shadow:SetBackdropColor(backdropr, backdropg, backdropb, 0)
shadow:SetBackdropBorderColor(borderr, borderg, borderb, 0.9)
f.shadow = shadow
end
function E:Kill(object)
if object.UnregisterAllEvents then
object:UnregisterAllEvents()
object:SetParent(E.HiddenFrame)
else
object.Show = object.Hide
end
object:Hide()
end
function E:StripTextures(object, kill)
for _, region in ipairs({object:GetRegions()}) do
if region and region:GetObjectType() == "Texture" then
if kill and type(kill) == "boolean" then
E:Kill(region)
elseif region:GetDrawLayer() == kill then
region:SetTexture(nil)
elseif kill and type(kill) == "string" and region:GetTexture() ~= kill then
region:SetTexture(nil)
else
region:SetTexture(nil)
end
end
end
end
function E:FontTemplate(fs, font, fontSize, fontStyle)
fs.font = font
fs.fontSize = fontSize
fs.fontStyle = fontStyle
font = font or LSM:Fetch("font", E.db["general"].font)
fontSize = fontSize or E.db.general.fontSize
if fontStyle == "OUTLINE" and (E.db.general.font == "Homespun") then
if (fontSize > 10 and not fs.fontSize) then
fontStyle = "MONOCHROMEOUTLINE"
fontSize = 10
end
end
fs:SetFont(font, fontSize, fontStyle)
if fontStyle and (fontStyle ~= "NONE") then
fs:SetShadowColor(0, 0, 0, 0.2)
else
fs:SetShadowColor(0, 0, 0, 1)
end
fs:SetShadowOffset((E.mult or 1), -(E.mult or 1))
E["texts"][fs] = true
end
function E:StyleButton(button, noHover, noPushed, noChecked)
if button.SetHighlightTexture and not button.hover and not noHover then
local hover = button:CreateTexture();
hover:SetTexture(1, 1, 1, 0.3)
E:SetInside(hover)
button.hover = hover
button:SetHighlightTexture(hover)
end
if button.SetPushedTexture and not button.pushed and not noPushed then
local pushed = button:CreateTexture();
pushed:SetTexture(0.9, 0.8, 0.1, 0.3)
E:SetInside(pushed)
button.pushed = pushed
button:SetPushedTexture(pushed)
end
if button.SetCheckedTexture and not button.checked and not noChecked then
local checked = button:CreateTexture();
checked:SetTexture(1, 1, 1)
E:SetInside(checked)
checked:SetAlpha(0.3)
button.checked = checked
button:SetCheckedTexture(checked)
end
local cooldown = button:GetName() and _G[button:GetName().."Cooldown"]
if cooldown then
cooldown:ClearAllPoints()
E:SetInside(cooldown)
end
end
+119
View File
@@ -0,0 +1,119 @@
local E, L, V, P, G = unpack(ElvUI); --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local _G = getfenv();
local CreateFrame = CreateFrame;
local DISABLE = DISABLE;
local HIDE = HIDE;
E.TutorialList = {
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"],
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."],
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."],
L["You can set your keybinds quickly by typing /kb."],
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."],
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."],
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."],
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."],
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."],
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."],
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"],
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."],
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."]
}
function E:SetNextTutorial()
self.db.currentTutorial = self.db.currentTutorial or 0
self.db.currentTutorial = self.db.currentTutorial + 1
if self.db.currentTutorial > gent(E.TutorialList) then
self.db.currentTutorial = 1
end
ElvUITutorialWindow.desc:SetText(E.TutorialList[self.db.currentTutorial])
end
function E:SetPrevTutorial()
self.db.currentTutorial = self.db.currentTutorial or 0
self.db.currentTutorial = self.db.currentTutorial - 1
if self.db.currentTutorial <= 0 then
self.db.currentTutorial = gent(E.TutorialList)
end
ElvUITutorialWindow.desc:SetText(E.TutorialList[self.db.currentTutorial])
end
function E:SpawnTutorialFrame()
local f = CreateFrame("Frame", "ElvUITutorialWindow", UIParent)
f:SetFrameStrata("DIALOG")
f:SetToplevel(true)
f:SetClampedToScreen(true)
f:SetWidth(360)
f:SetHeight(110)
E:SetTemplate(f, "Transparent")
f:Hide()
local S = E:GetModule("Skins")
local header = CreateFrame("Button", nil, f)
E:SetTemplate(header, "Default", true)
header:SetWidth(120); header:SetHeight(25)
header:SetPoint("CENTER", f, "TOP")
header:SetFrameLevel(header:GetFrameLevel() + 2)
local title = header:CreateFontString("OVERLAY")
title:FontTemplate()
title:SetPoint("CENTER", header, "CENTER")
title:SetText("ElvUI")
local desc = f:CreateFontString("ARTWORK")
desc:SetFontObject("GameFontHighlight")
desc:SetJustifyV("TOP")
desc:SetJustifyH("LEFT")
desc:SetPoint("TOPLEFT", 18, -32)
desc:SetPoint("BOTTOMRIGHT", -18, 30)
f.desc = desc
f.disableButton = CreateFrame("CheckButton", f:GetName().."DisableButton", f, "OptionsCheckButtonTemplate")
_G[f.disableButton:GetName() .. "Text"]:SetText(DISABLE)
f.disableButton:SetPoint("BOTTOMLEFT")
S:HandleCheckBox(f.disableButton)
f.disableButton:SetScript("OnShow", function(self) self:SetChecked(E.db.hideTutorial) end)
f.disableButton:SetScript("OnClick", function(self) E.db.hideTutorial = self:GetChecked() end)
f.hideButton = CreateFrame("Button", f:GetName().."HideButton", f, "OptionsButtonTemplate")
f.hideButton:SetPoint("BOTTOMRIGHT", -5, 5)
S:HandleButton(f.hideButton)
_G[f.hideButton:GetName() .. "Text"]:SetText(HIDE)
f.hideButton:SetScript("OnClick", function(self) E:StaticPopupSpecial_Hide(self:GetParent()) end)
f.nextButton = CreateFrame("Button", f:GetName().."NextButton", f, "OptionsButtonTemplate")
f.nextButton:SetPoint("RIGHT", f.hideButton, "LEFT", -4, 0)
f.nextButton:Width(20)
S:HandleButton(f.nextButton)
_G[f.nextButton:GetName() .. "Text"]:SetText(">")
f.nextButton:SetScript("OnClick", function() E:SetNextTutorial() end)
f.prevButton = CreateFrame("Button", f:GetName().."PrevButton", f, "OptionsButtonTemplate")
f.prevButton:SetPoint("RIGHT", f.nextButton, "LEFT", -4, 0)
f.prevButton:Width(20)
S:HandleButton(f.prevButton)
_G[f.prevButton:GetName() .. "Text"]:SetText("<")
f.prevButton:SetScript("OnClick", function() E:SetPrevTutorial() end)
return f
end
function E:Tutorials(forceShow)
if (not forceShow and self.db.hideTutorial) or (not forceShow and not self.private.install_complete) then return; end
local f = ElvUITutorialWindow
if not f then
f = E:SpawnTutorialFrame()
end
E:StaticPopupSpecial_Show(f)
self:SetNextTutorial()
end
+58
View File
@@ -0,0 +1,58 @@
--Cache global variables
--Lua functions
local _G = getfenv()
local print, tostring, select = print, tostring, select
local format = string.format
--WoW API / Variables
local GetMouseFocus = GetMouseFocus
--[[
Command to grab frame information when mouseing over a frame
Frame Name
Width
Height
Strata
Level
X Offset
Y Offset
Point
]]
SLASH_FRAME1 = "/frame"
SlashCmdList["FRAME"] = function(arg)
if arg ~= "" then
arg = _G[arg]
else
arg = GetMouseFocus()
end
if arg ~= nil then FRAME = arg end --Set the global variable FRAME to = whatever we are mousing over to simplify messing with frames that have no name.
if arg ~= nil and arg:GetName() ~= nil then
local point, relativeTo, relativePoint, xOfs, yOfs = arg:GetPoint()
ChatFrame1:AddMessage("|cffCC0000----------------------------")
ChatFrame1:AddMessage("Name: |cffFFD100"..arg:GetName())
if arg:GetParent() and arg:GetParent():GetName() then
ChatFrame1:AddMessage("Parent: |cffFFD100"..arg:GetParent():GetName())
end
ChatFrame1:AddMessage("Width: |cffFFD100"..format("%.2f",arg:GetWidth()))
ChatFrame1:AddMessage("Height: |cffFFD100"..format("%.2f",arg:GetHeight()))
ChatFrame1:AddMessage("Strata: |cffFFD100"..arg:GetFrameStrata())
ChatFrame1:AddMessage("Level: |cffFFD100"..arg:GetFrameLevel())
if xOfs then
ChatFrame1:AddMessage("X: |cffFFD100"..format("%.2f",xOfs))
end
if yOfs then
ChatFrame1:AddMessage("Y: |cffFFD100"..format("%.2f",yOfs))
end
if relativeTo and relativeTo:GetName() then
ChatFrame1:AddMessage("Point: |cffFFD100"..point.."|r anchored to "..relativeTo:GetName().."'s |cffFFD100"..relativePoint)
end
ChatFrame1:AddMessage("|cffCC0000----------------------------|r")
elseif arg == nil then
ChatFrame1:AddMessage("Invalid frame name")
else
ChatFrame1:AddMessage("Could not find frame info")
end
end
@@ -0,0 +1,6 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="ReloadUI.lua"/>
<Script file="Frame.lua"/>
<Script file="Test.lua"/>
<Script file="Table.lua"/>
</Ui>
+7
View File
@@ -0,0 +1,7 @@
--[[
Shortcut to ReloadUI
]]
SLASH_RELOADUI1 = "/rl"
SLASH_RELOADUI2 = "/reloadui"
SlashCmdList.RELOADUI = ReloadUI
+22
View File
@@ -0,0 +1,22 @@
--Cache global variables
local setmetatable, getmetatable = setmetatable, getmetatable
local pairs, type = pairs, type
local table = table
function table.copy(t, deep, seen)
seen = seen or {}
if t == nil then return nil end
if seen[t] then return seen[t] end
local nt = {}
for k, v in pairs(t) do
if deep and type(v) == "table" then
nt[k] = table.copy(v, deep, seen)
else
nt[k] = v
end
end
setmetatable(nt, table.copy(getmetatable(t), deep, seen))
seen[t] = nt
return nt
end
+5
View File
@@ -0,0 +1,5 @@
--[[
Going to leave this as my bullshit lua file.
So I can test stuff.
]]
+18
View File
@@ -0,0 +1,18 @@
## Interface: 11200
## Author: Elv, Bunny
## Version: 0.01
## Title: |cffA11313E|r|cffC4C4C4lvUI|r
## Notes: User Interface replacement AddOn for World of Warcraft.
## SavedVariables: ElvDB, ElvPrivateDB
## SavedVariablesPerCharacter: ElvCharacterDB
## OptionalDeps: SharedMedia
Developer\Load_Developer.xml
Libraries\Load_Libraries.xml
Locales\Load_Locales.xml
Media\Load_Media.xml
Init.lua
Settings\Load_Config.xml
Core\Load_Core.xml
Layout\Load_Layout.xml
Modules\Load_Modules.xml
+156
View File
@@ -0,0 +1,156 @@
--Cache global variables
_G = getfenv(0)
local pairs, unpack = pairs, unpack
BINDING_HEADER_ELVUI = GetAddOnMetadata("ElvUI", "Title")
ElvUI = {}
local AddOnName, Engine = "ElvUI", ElvUI
local AddOn = LibStub("AceAddon-3.0"):NewAddon(AddOnName, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceHook-3.0")
AddOn.callbacks = AddOn.callbacks or
LibStub("CallbackHandler-1.0"):New(AddOn)
AddOn.DF = {} AddOn.DF["profile"] = {} AddOn.DF["global"] = {} AddOn.privateVars = {} AddOn.privateVars["profile"] = {} -- Defaults
AddOn.Options = {
type = "group",
name = AddOnName,
args = {},
}
local Locale = LibStub("AceLocale-3.0"):GetLocale(AddOnName, false)
Engine[1] = AddOn
Engine[2] = Locale
Engine[3] = AddOn.privateVars["profile"]
Engine[4] = AddOn.DF["profile"]
Engine[5] = AddOn.DF["global"]
_G[AddOnName] = Engine
local tcopy = table.copy
function AddOn:OnInitialize()
if not ElvCharacterDB then
ElvCharacterDB = {}
end
self.db = tcopy(self.DF.profile, true)
self.global = tcopy(self.DF.global, true)
if ElvDB then
if ElvDB.global then
self:CopyTable(self.global, ElvDB.global)
end
local profileKey
if ElvDB.profileKeys then
profileKey = ElvDB.profileKeys[self.myname.." - "..self.myrealm]
end
if profileKey and ElvDB.profiles and ElvDB.profiles[profileKey] then
self:CopyTable(self.db, ElvDB.profiles[profileKey])
end
end
self.private = tcopy(self.privateVars.profile, true)
if ElvPrivateDB then
local profileKey
if ElvPrivateDB.profileKeys then
profileKey = ElvPrivateDB.profileKeys[self.myname.." - "..self.myrealm]
end
if profileKey and ElvPrivateDB.profiles and ElvPrivateDB.profiles[profileKey] then
self:CopyTable(self.private, ElvPrivateDB.profiles[profileKey])
end
end
if self.private.general.pixelPerfect then
self.Border = self.mult
self.Spacing = 0
self.PixelMode = true
end
self:UIScale()
self:UpdateMedia()
self:RegisterEvent("PLAYER_LOGIN", "Initialize")
--self:Contruct_StaticPopups()
self:InitializeInitialModules()
if IsAddOnLoaded("Tukui") then
self:StaticPopup_Show("TUKUI_ELVUI_INCOMPATIBLE")
end
local GameMenuButton = CreateFrame("Button", nil, GameMenuFrame, "GameMenuButtonTemplate")
GameMenuButton:SetWidth(GameMenuButtonLogout:GetWidth())
GameMenuButton:SetHeight(GameMenuButtonLogout:GetHeight())
GameMenuButton:SetText(AddOnName)
GameMenuButton:SetScript("OnClick", function()
AddOn:ToggleConfig()
HideUIPanel(GameMenuFrame)
end)
GameMenuFrame[AddOnName] = GameMenuButton
HookScript(GameMenuFrame, "OnShow", function()
if not GameMenuFrame.isElvUI then
GameMenuFrame:SetHeight(GameMenuFrame:GetHeight() + GameMenuButtonLogout:GetHeight() + 1)
GameMenuFrame.isElvUI = true
end
local _, relTo = GameMenuButtonLogout:GetPoint()
if relTo ~= GameMenuFrame[AddOnName] then
GameMenuFrame[AddOnName]:ClearAllPoints()
GameMenuFrame[AddOnName]:SetPoint("TOPLEFT", relTo, "BOTTOMLEFT", 0, -1)
GameMenuButtonLogout:ClearAllPoints()
GameMenuButtonLogout:SetPoint("TOPLEFT", GameMenuFrame[AddOnName], "BOTTOMLEFT", 0, -16)
end
end)
local S = AddOn:GetModule("Skins")
S:HandleButton(GameMenuButton)
end
function AddOn:ResetProfile()
local profileKey
if ElvPrivateDB.profileKeys then
profileKey = ElvPrivateDB.profileKeys[self.myname.." - "..self.myrealm]
end
if profileKey and ElvPrivateDB.profiles and ElvPrivateDB.profiles[profileKey] then
ElvPrivateDB.profiles[profileKey] = nil
end
ElvCharacterDB = nil
ReloadUI()
end
function AddOn:OnProfileReset()
self:StaticPopup_Show("RESET_PROFILE_PROMPT")
end
function AddOn:ToggleConfig()
if not IsAddOnLoaded("ElvUI_Config") then
local _, _, _, _, _, reason = GetAddOnInfo("ElvUI_Config")
if reason ~= "MISSING" and reason ~= "DISABLED" then
LoadAddOn("ElvUI_Config")
if GetAddOnMetadata("ElvUI_Config", "Version") ~= "1.01" then
self:StaticPopup_Show("CLIENT_UPDATE_REQUEST")
end
else
self:Print("|cffff0000Error -- Addon 'ElvUI_Config' not found or is disabled.|r")
return
end
end
local ACD = LibStub("AceConfigDialog-3.0")
local mode = "Close"
if not ACD.OpenFrames[AddOnName] then
mode = "Open"
end
if mode == "Open" then
PlaySound("igMainMenuOpen")
else
PlaySound("igMainMenuClose")
end
ACD[mode](ACD, AddOnName)
GameTooltip:Hide() --Just in case you're mouseovered something and it closes.
end
+415
View File
@@ -0,0 +1,415 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local LO = E:NewModule("Layout", "AceEvent-3.0");
--Cache global variables
--Lua functions
--WoW API / Variables
local CreateFrame = CreateFrame
local UIFrameFadeIn, UIFrameFadeOut = UIFrameFadeIn, UIFrameFadeOut
local PANEL_HEIGHT = 22
local SIDE_BUTTON_WIDTH = 16
E.Layout = LO
local function Panel_OnShow(self)
self:SetFrameLevel(0)
self:SetFrameStrata("BACKGROUND")
end
function LO:Initialize()
self:CreateChatPanels()
self:CreateMinimapPanels()
self:SetDataPanelStyle()
self.BottomPanel = CreateFrame("Frame", "ElvUI_BottomPanel", E.UIParent)
E:SetTemplate(self.BottomPanel, "Transparent")
self.BottomPanel:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOMLEFT", -1, -1)
self.BottomPanel:SetPoint("BOTTOMRIGHT", E.UIParent, "BOTTOMRIGHT", 1, -1)
self.BottomPanel:SetHeight(PANEL_HEIGHT)
self.BottomPanel:SetScript("OnShow", function() Panel_OnShow(this) end)
Panel_OnShow(self.BottomPanel)
self:BottomPanelVisibility()
self.TopPanel = CreateFrame("Frame", "ElvUI_TopPanel", E.UIParent)
E:SetTemplate(self.TopPanel, "Transparent")
self.TopPanel:SetPoint("TOPLEFT", E.UIParent, "TOPLEFT", -1, 1)
self.TopPanel:SetPoint("TOPRIGHT", E.UIParent, "TOPRIGHT", 1, 1)
self.TopPanel:SetHeight(PANEL_HEIGHT)
self.TopPanel:SetScript("OnShow", function() Panel_OnShow(this) end)
Panel_OnShow(self.TopPanel)
self:TopPanelVisibility()
end
function LO:BottomPanelVisibility()
if(E.db.general.bottomPanel) then
self.BottomPanel:Show()
else
self.BottomPanel:Hide()
end
end
function LO:TopPanelVisibility()
if E.db.general.topPanel then
self.TopPanel:Show()
else
self.TopPanel:Hide()
end
end
local function ChatPanelLeft_OnFade()
LeftChatPanel:Hide()
end
local function ChatPanelRight_OnFade()
RightChatPanel:Hide()
end
local function ChatButton_OnEnter()
if E.db[this.parent:GetName().."Faded"] then
this.parent:Show()
UIFrameFadeIn(this.parent, 0.2, this.parent:GetAlpha(), 1)
UIFrameFadeIn(this, 0.2, this:GetAlpha(), 1)
end
if this == LeftChatToggleButton then
GameTooltip:SetOwner(this, "ANCHOR_TOPLEFT", 0, (E.PixelMode and 1 or 3))
GameTooltip:ClearLines()
GameTooltip:AddDoubleLine(L["Left Click:"], L["Toggle Chat Frame"], 1, 1, 1)
else
GameTooltip:SetOwner(this, "ANCHOR_TOPRIGHT", 0, (E.PixelMode and 1 or 3))
GameTooltip:ClearLines()
GameTooltip:AddDoubleLine(L["Left Click:"], L["Toggle Chat Frame"], 1, 1, 1)
end
GameTooltip:Show()
end
local function ChatButton_OnLeave()
if E.db[this.parent:GetName().."Faded"] then
UIFrameFadeOut(this.parent, 0.2, this.parent:GetAlpha(), 0)
UIFrameFadeOut(this, 0.2, this:GetAlpha(), 0)
this.parent.fadeInfo.finishedFunc = this.parent.fadeFunc
end
GameTooltip:Hide()
end
local function ChatButton_OnClick()
GameTooltip:Hide()
if E.db[this.parent:GetName().."Faded"] then
E.db[this.parent:GetName().."Faded"] = nil
UIFrameFadeIn(this.parent, 0.2, this.parent:GetAlpha(), 1)
UIFrameFadeIn(this, 0.2, this:GetAlpha(), 1)
else
E.db[this.parent:GetName().."Faded"] = true
UIFrameFadeOut(this.parent, 0.2, this.parent:GetAlpha(), 0)
UIFrameFadeOut(this, 0.2, this:GetAlpha(), 0)
this.parent.fadeInfo.finishedFunc = this.parent.fadeFunc
end
end
function HideLeftChat()
ChatButton_OnClick(LeftChatToggleButton)
end
function HideRightChat()
ChatButton_OnClick(RightChatToggleButton)
end
function HideBothChat()
ChatButton_OnClick(LeftChatToggleButton)
ChatButton_OnClick(RightChatToggleButton)
end
function LO:ToggleChatTabPanels(rightOverride, leftOverride)
if leftOverride or not E.db.chat.panelTabBackdrop then
LeftChatTab:Hide()
else
LeftChatTab:Show()
end
if rightOverride or not E.db.chat.panelTabBackdrop then
RightChatTab:Hide()
else
RightChatTab:Show()
end
end
function LO:SetChatTabStyle()
if E.db.chat.panelTabTransparency then
E:SetTemplate(LeftChatTab, "Transparent")
E:SetTemplate(RightChatTab, "Transparent")
else
E:SetTemplate(LeftChatTab, "Default", true)
E:SetTemplate(RightChatTab, "Default", true)
end
end
function LO:SetDataPanelStyle()
if E.db.datatexts.panelTransparency then
if not E.db.datatexts.panelBackdrop then
E:SetTemplate(LeftChatDataPanel, "NoBackdrop")
E:SetTemplate(LeftChatToggleButton, "NoBackdrop")
E:SetTemplate(RightChatDataPanel, "NoBackdrop")
E:SetTemplate(RightChatToggleButton, "NoBackdrop")
else
E:SetTemplate(LeftChatDataPanel, "Transparent")
E:SetTemplate(LeftChatToggleButton, "Transparent")
E:SetTemplate(RightChatDataPanel, "Transparent")
E:SetTemplate(RightChatToggleButton, "Transparent")
end
E:SetTemplate(LeftMiniPanel, "Transparent")
E:SetTemplate(RightMiniPanel, "Transparent")
else
if not E.db.datatexts.panelBackdrop then
E:SetTemplate(LeftChatDataPanel, "NoBackdrop")
E:SetTemplate(LeftChatToggleButton, "NoBackdrop")
E:SetTemplate(RightChatDataPanel, "NoBackdrop")
E:SetTemplate(RightChatToggleButton, "NoBackdrop")
else
E:SetTemplate(LeftChatDataPanel, "Default", true)
E:SetTemplate(LeftChatToggleButton, "Default", true)
E:SetTemplate(RightChatDataPanel, "Default", true)
E:SetTemplate(RightChatToggleButton, "Default", true)
end
E:SetTemplate(RightMiniPanel, "Default", true)
E:SetTemplate(LeftMiniPanel, "Default", true)
end
end
function LO:ToggleChatPanels()
LeftChatDataPanel:ClearAllPoints()
RightChatDataPanel:ClearAllPoints()
local SPACING = E.Border*3 - E.Spacing
if E.db.datatexts.leftChatPanel then
LeftChatDataPanel:Show()
LeftChatToggleButton:Show()
else
LeftChatDataPanel:Hide()
LeftChatToggleButton:Hide()
end
if E.db.datatexts.rightChatPanel then
RightChatDataPanel:Show()
RightChatToggleButton:Show()
else
RightChatDataPanel:Hide()
RightChatToggleButton:Hide()
end
local panelBackdrop = E.db.chat.panelBackdrop
if(panelBackdrop == "SHOWBOTH") then
LeftChatPanel.backdrop:Show()
RightChatPanel.backdrop:Show()
LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT", SPACING, SPACING)
LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING, SPACING)
RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", -SPACING, SPACING)
LO:ToggleChatTabPanels()
elseif(panelBackdrop == "HIDEBOTH") then
LeftChatPanel.backdrop:Hide()
RightChatPanel.backdrop:Hide()
LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SIDE_BUTTON_WIDTH, 0)
RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT")
LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT")
RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT")
LO:ToggleChatTabPanels(true, true)
elseif(panelBackdrop == "LEFT") then
LeftChatPanel.backdrop:Show()
RightChatPanel.backdrop:Hide()
LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT")
LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SPACING, SPACING)
RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT")
LO:ToggleChatTabPanels(true)
else
LeftChatPanel.backdrop:Hide()
RightChatPanel.backdrop:Show()
LeftChatDataPanel:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT", SIDE_BUTTON_WIDTH, 0)
RightChatDataPanel:SetPoint("BOTTOMLEFT", RightChatPanel, "BOTTOMLEFT", SPACING, SPACING)
LeftChatToggleButton:SetPoint("BOTTOMLEFT", LeftChatPanel, "BOTTOMLEFT")
RightChatToggleButton:SetPoint("BOTTOMRIGHT", RightChatPanel, "BOTTOMRIGHT", -SPACING, SPACING)
LO:ToggleChatTabPanels(nil, true)
end
end
function LO:CreateChatPanels()
local SPACING = E.Border*3 - E.Spacing
--Left Chat
local lchat = CreateFrame("Frame", "LeftChatPanel", E.UIParent)
lchat:SetFrameStrata("BACKGROUND")
lchat:SetWidth(E.db.chat.panelWidth)
lchat:SetHeight(E.db.chat.panelHeight)
lchat:SetPoint("BOTTOMLEFT", E.UIParent, 4, 4)
lchat:SetFrameLevel(lchat:GetFrameLevel() + 2)
E:CreateBackdrop(lchat, "Transparent")
lchat.backdrop:SetAllPoints()
E:CreateMover(lchat, "LeftChatMover", L["Left Chat"])
--Background Texture
lchat.tex = lchat:CreateTexture(nil, "OVERLAY")
E:SetInside(lchat.tex)
lchat.tex:SetTexture(E.db.chat.panelBackdropNameLeft)
lchat.tex:SetAlpha(E.db.general.backdropfadecolor.a - 0.7 > 0 and E.db.general.backdropfadecolor.a - 0.7 or 0.5)
--Left Chat Tab
local lchattab = CreateFrame("Frame", "LeftChatTab", LeftChatPanel)
lchattab:SetPoint("TOPLEFT", lchat, "TOPLEFT", SPACING, -SPACING)
lchattab:SetPoint("BOTTOMRIGHT", lchat, "TOPRIGHT", -SPACING, -(SPACING + PANEL_HEIGHT))
E:SetTemplate(lchattab, E.db.chat.panelTabTransparency == true and "Transparent" or "Default", true)
--Left Chat Data Panel
local lchatdp = CreateFrame("Frame", "LeftChatDataPanel", LeftChatPanel)
lchatdp:SetWidth(E.db.chat.panelWidth -((SPACING*2) + SIDE_BUTTON_WIDTH))
lchatdp:SetHeight(PANEL_HEIGHT)
lchatdp:SetPoint("BOTTOMLEFT", lchat, "BOTTOMLEFT", SPACING + SIDE_BUTTON_WIDTH, SPACING)
E:SetTemplate(lchatdp, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
E:GetModule("DataTexts"):RegisterPanel(lchatdp, 3, "ANCHOR_TOPLEFT", -16, (E.PixelMode and 1 or 3))
--Left Chat Toggle Button
local lchattb = CreateFrame("Button", "LeftChatToggleButton", E.UIParent)
lchattb.parent = LeftChatPanel
LeftChatPanel.fadeFunc = ChatPanelLeft_OnFade
lchattb:SetPoint("TOPRIGHT", lchatdp, "TOPLEFT", E.Border - E.Spacing*3, 0)
lchattb:SetPoint("BOTTOMLEFT", lchat, "BOTTOMLEFT", SPACING, SPACING)
E:SetTemplate(lchattb, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
lchattb:SetScript("OnEnter", ChatButton_OnEnter)
lchattb:SetScript("OnLeave", ChatButton_OnLeave)
lchattb:SetScript("OnClick", ChatButton_OnClick)
lchattb.text = lchattb:CreateFontString(nil, "OVERLAY")
E:FontTemplate(lchattb.text)
lchattb.text:SetPoint("CENTER", lchattb)
lchattb.text:SetJustifyH("CENTER")
lchattb.text:SetText("<")
--Right Chat
local rchat = CreateFrame("Frame", "RightChatPanel", E.UIParent)
rchat:SetFrameStrata("BACKGROUND")
rchat:SetWidth(E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth)
rchat:SetHeight(E.db.chat.separateSizes and E.db.chat.panelHeightRight or E.db.chat.panelHeight)
rchat:SetPoint("BOTTOMRIGHT", E.UIParent, -4, 4)
rchat:SetFrameLevel(lchat:GetFrameLevel() + 2)
E:CreateBackdrop(rchat, "Transparent")
rchat.backdrop:SetAllPoints()
E:CreateMover(rchat, "RightChatMover", L["Right Chat"])
--Background Texture
rchat.tex = rchat:CreateTexture(nil, "OVERLAY")
E:SetInside(rchat.tex)
rchat.tex:SetTexture(E.db.chat.panelBackdropNameRight)
rchat.tex:SetAlpha(E.db.general.backdropfadecolor.a - 0.7 > 0 and E.db.general.backdropfadecolor.a - 0.7 or 0.5)
--Right Chat Tab
local rchattab = CreateFrame("Frame", "RightChatTab", RightChatPanel)
rchattab:SetPoint("TOPRIGHT", rchat, "TOPRIGHT", -SPACING, -SPACING)
rchattab:SetPoint("BOTTOMLEFT", rchat, "TOPLEFT", SPACING, -(SPACING + PANEL_HEIGHT))
E:SetTemplate(rchattab, E.db.chat.panelTabTransparency == true and "Transparent" or "Default", true)
--Right Chat Data Panel
local rchatdp = CreateFrame("Frame", "RightChatDataPanel", RightChatPanel)
rchatdp:SetWidth((E.db.chat.separateSizes and E.db.chat.panelWidthRight or E.db.chat.panelWidth) -((SPACING*2) + SIDE_BUTTON_WIDTH))
rchatdp:SetHeight(PANEL_HEIGHT)
rchatdp:SetPoint("BOTTOMLEFT", rchat, "BOTTOMLEFT", SPACING, SPACING)
E:SetTemplate(rchatdp, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
E:GetModule("DataTexts"):RegisterPanel(rchatdp, 3, "ANCHOR_TOPRIGHT", 16, (E.PixelMode and 1 or 3))
--Right Chat Toggle Button
local rchattb = CreateFrame("Button", "RightChatToggleButton", E.UIParent)
rchattb.parent = RightChatPanel
RightChatPanel.fadeFunc = ChatPanelRight_OnFade
rchattb:SetPoint("TOPLEFT", rchatdp, "TOPRIGHT", -E.Border + E.Spacing*3, 0)
rchattb:SetPoint("BOTTOMRIGHT", rchat, "BOTTOMRIGHT", -SPACING, SPACING)
E:SetTemplate(rchattb, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
rchattb:SetScript("OnEnter", ChatButton_OnEnter)
rchattb:SetScript("OnLeave", ChatButton_OnLeave)
rchattb:SetScript("OnClick", ChatButton_OnClick)
rchattb.text = rchattb:CreateFontString(nil, "OVERLAY")
E:FontTemplate(rchattb.text)
rchattb.text:SetPoint("CENTER", rchattb)
rchattb.text:SetJustifyH("CENTER")
rchattb.text:SetText(">")
--Load Settings
if E.db["LeftChatPanelFaded"] then
LeftChatToggleButton:SetAlpha(0)
LeftChatPanel:Hide()
end
if E.db["RightChatPanelFaded"] then
RightChatToggleButton:SetAlpha(0)
RightChatPanel:Hide()
end
self:ToggleChatPanels()
end
function LO:CreateMinimapPanels()
local lminipanel = CreateFrame("Frame", "LeftMiniPanel", Minimap.backdrop)
lminipanel:SetWidth(E.db.general.minimap.size/2 + (E.PixelMode and 1 or 3))
lminipanel:SetHeight(PANEL_HEIGHT)
lminipanel:SetPoint("TOPLEFT", Minimap, "BOTTOMLEFT", -E.Border, (E.PixelMode and 0 or -3))
E:SetTemplate(lminipanel, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
E:GetModule("DataTexts"):RegisterPanel(lminipanel, 1, "ANCHOR_BOTTOMLEFT", lminipanel:GetWidth() * 2, -(E.PixelMode and 1 or 3))
local rminipanel = CreateFrame("Frame", "RightMiniPanel", Minimap.backdrop)
rminipanel:SetWidth(E.db.general.minimap.size/2 + (E.PixelMode and 1 or 3))
rminipanel:SetHeight(PANEL_HEIGHT)
rminipanel:SetPoint("TOPRIGHT", Minimap, "BOTTOMRIGHT", E.Border, (E.PixelMode and 0 or -3))
E:SetTemplate(rminipanel, E.db.datatexts.panelTransparency and "Transparent" or "Default", true)
E:GetModule("DataTexts"):RegisterPanel(rminipanel, 1, "ANCHOR_BOTTOM", 0, -(E.PixelMode and 1 or 3))
if E.db.datatexts.minimapPanels then
LeftMiniPanel:Show()
RightMiniPanel:Show()
else
LeftMiniPanel:Hide()
RightMiniPanel:Hide()
end
local f = CreateFrame("Frame", "BottomMiniPanel", Minimap.backdrop)
f:SetPoint("BOTTOM", Minimap, "BOTTOM")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOM", 0, -10)
f = CreateFrame("Frame", "TopMiniPanel", Minimap.backdrop)
f:SetPoint("TOP", Minimap, "TOP")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOM", 0, -10)
f = CreateFrame("Frame", "TopLeftMiniPanel", Minimap.backdrop)
f:SetPoint("TOPLEFT", Minimap, "TOPLEFT")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMLEFT", 0, -10)
f = CreateFrame("Frame", "TopRightMiniPanel", Minimap.backdrop)
f:SetPoint("TOPRIGHT", Minimap, "TOPRIGHT")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMRIGHT", 0, -10)
f = CreateFrame("Frame", "BottomLeftMiniPanel", Minimap.backdrop)
f:SetPoint("BOTTOMLEFT", Minimap, "BOTTOMLEFT")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMLEFT", 0, -10)
f = CreateFrame("Frame", "BottomRightMiniPanel", Minimap.backdrop)
f:SetPoint("BOTTOMRIGHT", Minimap, "BOTTOMRIGHT")
f:SetWidth(75)
f:SetHeight(20)
E:GetModule("DataTexts"):RegisterPanel(f, 1, "ANCHOR_BOTTOMRIGHT", 0, -10)
end
local function InitializeCallback()
LO:Initialize()
end
E:RegisterModule(LO:GetName(), InitializeCallback)
+3
View File
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="Layout.lua"/>
</Ui>
@@ -0,0 +1,674 @@
--- **AceAddon-3.0** provides a template for creating addon objects.
-- It'll provide you with a set of callback functions that allow you to simplify the loading
-- process of your addon.\\
-- Callbacks provided are:\\
-- * **OnInitialize**, which is called directly after the addon is fully loaded.
-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
-- * **OnDisable**, which is only called when your addon is manually being disabled.
-- @usage
-- -- A small (but complete) addon, that doesn't do anything,
-- -- but shows usage of the callbacks.
-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
--
-- function MyAddon:OnInitialize()
-- -- do init tasks here, like loading the Saved Variables,
-- -- or setting up slash commands.
-- end
--
-- function MyAddon:OnEnable()
-- -- Do more initialization here, that really enables the use of your addon.
-- -- Register Events, Hook functions, Create Frames, Get information from
-- -- the game that wasn't available in OnInitialize
-- end
--
-- function MyAddon:OnDisable()
-- -- Unhook, Unregister Events, Hide frames that you created.
-- -- You would probably only use an OnDisable if you want to
-- -- build a "standby" mode, or be able to toggle modules on/off.
-- end
-- @class file
-- @name AceAddon-3.0.lua
-- @release $Id: AceAddon-3.0.lua 1084 2013-04-27 20:14:11Z nevcairiel $
local MAJOR, MINOR = "AceAddon-3.0", 12
local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceAddon then return end -- No Upgrade needed.
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
AceAddon.addons = AceAddon.addons or {} -- addons in general
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
-- Lua APIs
local getn, tinsert, tconcat, tremove = table.getn, table.insert, table.concat, table.remove
local fmt, tostring = string.format, tostring
local select, pairs, next, type, unpack = select, pairs, next, type, unpack
local loadstring, assert, error = loadstring, assert, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = arg1, arg2
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do
ARGS[i] = "arg"..i
end
code = string.gsub(code, "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
--print(Dispatchers[getn(arg)](func, unpack(arg)))
return func(unpack(arg))
end
end
-- local functions that will be implemented further down
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
-- used in the addon metatable
local function addontostring( self ) return self.name end
-- Check if the addon is queued for initialization
local function queuedForInitialization(addon)
for i = 1, getn(AceAddon.initializequeue) do
if AceAddon.initializequeue[i] == addon then
return true
end
end
return false
end
--- Create a new AceAddon-3.0 addon.
-- Any libraries you specified will be embeded, and the addon will be scheduled for
-- its OnInitialize and OnEnable callbacks.
-- The final addon object, with all libraries embeded, will be returned.
-- @paramsig [object ,]name[, lib, ...]
-- @param object Table to use as a base for the addon (optional)
-- @param name Name of the addon object to create
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a simple addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
--
-- -- Create a Addon object based on the table of a frame
-- local MyFrame = CreateFrame("Frame")
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
function AceAddon:NewAddon(objectorname, ...)
local object,name
local i=1
if type(objectorname)=="table" then
object=objectorname
name=unpack(arg)
i=2
else
name=objectorname
end
if type(name)~="string" then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
end
if self.addons[name] then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
end
object = object or {}
object.name = name
local addonmeta = {}
local oldmeta = getmetatable(object)
if oldmeta then
for k, v in pairs(oldmeta) do addonmeta[k] = v end
end
addonmeta.__tostring = addontostring
setmetatable( object, addonmeta )
self.addons[name] = object
object.modules = {}
object.orderedModules = {}
object.defaultModuleLibraries = {}
Embed( object ) -- embed NewModule, GetModule methods
self:EmbedLibraries(object, unpack(arg))
-- add to queue of addons to be initialized upon ADDON_LOADED
tinsert(self.initializequeue, object)
return object
end
--- Get the addon object by its name from the internal AceAddon registry.
-- Throws an error if the addon object cannot be found (except if silent is set).
-- @param name unique name of the addon object
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
function AceAddon:GetAddon(name, silent)
if not silent and not self.addons[name] then
error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
end
return self.addons[name]
end
-- - Embed a list of libraries into the specified addon.
-- This function will try to embed all of the listed libraries into the addon
-- and error if a single one fails.
--
-- **Note:** This function is for internal use by :NewAddon/:NewModule
-- @paramsig addon, [lib, ...]
-- @param addon addon object to embed the libs in
-- @param lib List of libraries to embed into the addon
function AceAddon:EmbedLibraries(addon, ...)
for i=1, getn(arg) do
local libname = arg[i]
self:EmbedLibrary(addon, libname, false, 4)
end
end
-- - Embed a library into the addon object.
-- This function will check if the specified library is registered with LibStub
-- and if it has a :Embed function to call. It'll error if any of those conditions
-- fails.
--
-- **Note:** This function is for internal use by :EmbedLibraries
-- @paramsig addon, libname[, silent[, offset]]
-- @param addon addon object to embed the library in
-- @param libname name of the library to embed
-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
function AceAddon:EmbedLibrary(addon, libname, silent, offset)
local lib = LibStub:GetLibrary(libname, true)
if not lib and not silent then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
elseif lib and type(lib.Embed) == "function" then
lib:Embed(addon)
tinsert(self.embeds[addon], libname)
return true
elseif lib then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
end
end
--- Return the specified module from an addon object.
-- Throws an error if the addon object cannot be found (except if silent is set)
-- @name //addon//:GetModule
-- @paramsig name[, silent]
-- @param name unique name of the module
-- @param silent if true, the module is optional, silently return nil if its not found (optional)
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- -- Get the Module
-- MyModule = MyAddon:GetModule("MyModule")
function GetModule(self, name, silent)
if not self.modules[name] and not silent then
error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
end
return self.modules[name]
end
local function IsModuleTrue(self) return true end
--- Create a new module for the addon.
-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
-- an addon object.
-- @name //addon//:NewModule
-- @paramsig name[, prototype|lib[, lib, ...]]
-- @param name unique name of the module
-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a module with some embeded libraries
-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
--
-- -- Create a module with a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
function NewModule(self, name, prototype, ...)
if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
module.IsModule = IsModuleTrue
module:SetEnabledState(self.defaultModuleState)
module.moduleName = name
if type(prototype) == "string" then
AceAddon:EmbedLibraries(module, prototype, unpack(arg))
else
AceAddon:EmbedLibraries(module, unpack(arg))
end
AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
if not prototype or type(prototype) == "string" then
prototype = self.defaultModulePrototype or nil
end
if type(prototype) == "table" then
local mt = getmetatable(module)
mt.__index = prototype
setmetatable(module, mt) -- More of a Base class type feel.
end
safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
self.modules[name] = module
tinsert(self.orderedModules, module)
return module
end
--- Returns the real name of the addon or module, without any prefix.
-- @name //addon//:GetName
-- @paramsig
-- @usage
-- print(MyAddon:GetName())
-- -- prints "MyAddon"
function GetName(self)
return self.moduleName or self.name
end
--- Enables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
-- and enabling all modules of the addon (unless explicitly disabled).\\
-- :Enable() also sets the internal `enableState` variable to true
-- @name //addon//:Enable
-- @paramsig
-- @usage
-- -- Enable MyModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
function Enable(self)
self:SetEnabledState(true)
-- nevcairiel 2013-04-27: don't enable an addon/module if its queued for init still
-- it'll be enabled after the init process
if not queuedForInitialization(self) then
return AceAddon:EnableAddon(self)
end
end
--- Disables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
-- and disabling all modules of the addon.\\
-- :Disable() also sets the internal `enableState` variable to false
-- @name //addon//:Disable
-- @paramsig
-- @usage
-- -- Disable MyAddon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:Disable()
function Disable(self)
self:SetEnabledState(false)
return AceAddon:DisableAddon(self)
end
--- Enables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
-- @name //addon//:EnableModule
-- @paramsig name
-- @usage
-- -- Enable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
--
-- -- Enable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:EnableModule("MyModule")
function EnableModule(self, name)
local module = self:GetModule( name )
return module:Enable()
end
--- Disables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
-- @name //addon//:DisableModule
-- @paramsig name
-- @usage
-- -- Disable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Disable()
--
-- -- Disable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:DisableModule("MyModule")
function DisableModule(self, name)
local module = self:GetModule( name )
return module:Disable()
end
--- Set the default libraries to be mixed into all modules created by this object.
-- Note that you can only change the default module libraries before any module is created.
-- @name //addon//:SetDefaultModuleLibraries
-- @paramsig lib[, lib, ...]
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
-- -- Create a module
-- MyModule = MyAddon:NewModule("MyModule")
function SetDefaultModuleLibraries(self, ...)
if next(self.modules) then
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleLibraries = {unpack(arg)}
end
--- Set the default state in which new modules are being created.
-- Note that you can only change the default state before any module is created.
-- @name //addon//:SetDefaultModuleState
-- @paramsig state
-- @param state Default state for new modules, true for enabled, false for disabled
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Set the default state to "disabled"
-- MyAddon:SetDefaultModuleState(false)
-- -- Create a module and explicilty enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
function SetDefaultModuleState(self, state)
if next(self.modules) then
error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleState = state
end
--- Set the default prototype to use for new modules on creation.
-- Note that you can only change the default prototype before any module is created.
-- @name //addon//:SetDefaultModulePrototype
-- @paramsig prototype
-- @param prototype Default prototype for the new modules (table)
-- @usage
-- -- Define a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- -- Set the default prototype
-- MyAddon:SetDefaultModulePrototype(prototype)
-- -- Create a module and explicitly Enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
-- -- should print "OnEnable called!" now
-- @see NewModule
function SetDefaultModulePrototype(self, prototype)
if next(self.modules) then
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
end
if type(prototype) ~= "table" then
error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
end
self.defaultModulePrototype = prototype
end
--- Set the state of an addon or module
-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
-- @name //addon//:SetEnabledState
-- @paramsig state
-- @param state the state of an addon or module (enabled=true, disabled=false)
function SetEnabledState(self, state)
self.enabledState = state
end
--- Return an iterator of all modules associated to the addon.
-- @name //addon//:IterateModules
-- @paramsig
-- @usage
-- -- Enable all modules
-- for name, module in MyAddon:IterateModules() do
-- module:Enable()
-- end
local function IterateModules(self) return pairs(self.modules) end
-- Returns an iterator of all embeds in the addon
-- @name //addon//:IterateEmbeds
-- @paramsig
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
--- Query the enabledState of an addon.
-- @name //addon//:IsEnabled
-- @paramsig
-- @usage
-- if MyAddon:IsEnabled() then
-- MyAddon:Disable()
-- end
local function IsEnabled(self) return self.enabledState end
local mixins = {
NewModule = NewModule,
GetModule = GetModule,
Enable = Enable,
Disable = Disable,
EnableModule = EnableModule,
DisableModule = DisableModule,
IsEnabled = IsEnabled,
SetDefaultModuleLibraries = SetDefaultModuleLibraries,
SetDefaultModuleState = SetDefaultModuleState,
SetDefaultModulePrototype = SetDefaultModulePrototype,
SetEnabledState = SetEnabledState,
IterateModules = IterateModules,
IterateEmbeds = IterateEmbeds,
GetName = GetName,
}
local function IsModule(self) return false end
local pmixins = {
defaultModuleState = true,
enabledState = true,
IsModule = IsModule,
}
-- Embed( target )
-- target (object) - target object to embed aceaddon in
--
-- this is a local function specifically since it's meant to be only called internally
function Embed(target, skipPMixins)
for k, v in pairs(mixins) do
target[k] = v
end
if not skipPMixins then
for k, v in pairs(pmixins) do
target[k] = target[k] or v
end
end
end
-- - Initialize the addon after creation.
-- This function is only used internally during the ADDON_LOADED event
-- It will call the **OnInitialize** function on the addon object (if present),
-- and the **OnEmbedInitialize** function on all embeded libraries.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- @param addon addon object to intialize
function AceAddon:InitializeAddon(addon)
safecall(addon.OnInitialize, addon)
local embeds = self.embeds[addon]
for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true)
--if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
end
-- we don't call InitializeAddon on modules specifically, this is handled
-- from the event handler and only done _once_
end
-- - Enable the addon after creation.
-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
-- It will call the **OnEnable** function on the addon object (if present),
-- and the **OnEmbedEnable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Enable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:EnableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if self.statuses[addon.name] or not addon.enabledState then return false end
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
self.statuses[addon.name] = true
safecall(addon.OnEnable, addon)
-- make sure we're still enabled before continueing
if self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedEnable, lib, addon) end
end
-- enable possible modules.
local modules = addon.orderedModules
for i = 1, getn(modules) do
self:EnableAddon(modules[i])
end
end
return self.statuses[addon.name] -- return true if we're disabled
end
-- - Disable the addon
-- Note: This function is only used internally.
-- It will call the **OnDisable** function on the addon object (if present),
-- and the **OnEmbedDisable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Disable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:DisableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if not self.statuses[addon.name] then return false end
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
self.statuses[addon.name] = false
safecall( addon.OnDisable, addon )
-- make sure we're still disabling...
if not self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedDisable, lib, addon) end
end
-- disable possible modules.
local modules = addon.orderedModules
for i = 1, getn(modules) do
self:DisableAddon(modules[i])
end
end
return not self.statuses[addon.name] -- return true if we're disabled
end
--- Get an iterator over all registered addons.
-- @usage
-- -- Print a list of all installed AceAddon's
-- for name, addon in AceAddon:IterateAddons() do
-- print("Addon: " .. name)
-- end
function AceAddon:IterateAddons() return pairs(self.addons) end
--- Get an iterator over the internal status registry.
-- @usage
-- -- Print a list of all enabled addons
-- for name, status in AceAddon:IterateAddonStatus() do
-- if status then
-- print("EnabledAddon: " .. name)
-- end
-- end
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
-- Following Iterators are deprecated, and their addon specific versions should be used
-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
local IsLoggedIn
-- Event Handling
local function onEvent()
-- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up
if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
while(getn(AceAddon.initializequeue) > 0) do
local addon = tremove(AceAddon.initializequeue, 1)
-- this might be an issue with recursion - TODO: validate
if event == "ADDON_LOADED" then addon.baseName = arg1 end
AceAddon:InitializeAddon(addon)
tinsert(AceAddon.enablequeue, addon)
end
if event == "PLAYER_LOGIN" then
IsLoggedIn = true
end
if IsLoggedIn then
while(getn(AceAddon.enablequeue) > 0) do
local addon = tremove(AceAddon.enablequeue, 1)
AceAddon:EnableAddon(addon)
end
end
end
end
AceAddon.frame:RegisterEvent("ADDON_LOADED")
AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
AceAddon.frame:SetScript("OnEvent", onEvent)
-- upgrade embeded
for name, addon in pairs(AceAddon.addons) do
Embed(addon, true)
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceAddon-3.0.lua"/>
</Ui>
@@ -0,0 +1,306 @@
--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels.
-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
--
-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceComm itself.\\
-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceComm.
-- @class file
-- @name AceComm-3.0
-- @release $Id: AceComm-3.0.lua 1107 2014-02-19 16:40:32Z nevcairiel $
--[[ AceComm-3.0
TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
]]
local MAJOR, MINOR = "AceComm-3.0", 9
local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceComm then return end
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
-- Lua APIs
local type, next, pairs, tostring = type, next, pairs, tostring
local strlen, strsub, strfind = string.len, string.sub, string.find
local tinsert, tconcat, tgetn, tremove = table.insert, table.concat, table.getn, table.remove
local error, assert = error, assert
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix
AceComm.embeds = AceComm.embeds or {}
-- for my sanity and yours, let's give the message type bytes some names
local MSG_MULTI_FIRST = "\001"
local MSG_MULTI_NEXT = "\002"
local MSG_MULTI_LAST = "\003"
local MSG_ESCAPE = "\004"
-- remove old structures (pre WoW 4.0)
AceComm.multipart_origprefixes = nil
AceComm.multipart_reassemblers = nil
-- the multipart message spool: indexed by a combination of sender+distribution+
AceComm.multipart_spool = AceComm.multipart_spool or {}
--- Register for Addon Traffic on a specified prefix
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters
-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
function AceComm:RegisterComm(prefix, method)
if method == nil then
method = "OnCommReceived"
end
if strlen(prefix) > 16 then -- TODO: 15?
error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters")
end
return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
end
local warnedPrefix=false
--- Send a message over the Addon Channel
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- @param text Data to send, nils (\000) not allowed. Any length.
-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
-- @param target Destination for some distributions; see SendAddonMessage API
-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg)
prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
if not( type(prefix)=="string" and
type(text)=="string" and
type(distribution)=="string" and
(target==nil or type(target)=="string") and
(prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
) then
error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
end
local textlen = strlen(text)
-- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327
-- Ace3v: substract the prefix length
local maxtextlen = 254 - strlen(prefix)
local queueName = prefix..distribution..(target or "")
local ctlCallback = nil
if callbackFn then
ctlCallback = function(sent)
return callbackFn(callbackArg, sent, textlen)
end
end
local forceMultipart
if strfind(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character
-- we need to escape the first character with a \004
if textlen+1 > maxtextlen then -- would we go over the size limit?
forceMultipart = true -- just make it multipart, no escape problems then
else
text = "\004" .. text
end
end
if not forceMultipart and textlen <= maxtextlen then
-- fits all in one message
CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
else
maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1)
-- first part
local chunk = strsub(text, 1, maxtextlen)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen)
-- continuation
local pos = 1+maxtextlen
while pos+maxtextlen <= textlen do
chunk = strsub(text, pos, pos+maxtextlen-1)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
pos = pos + maxtextlen
end
-- final part
chunk = strsub(text, pos)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen)
end
end
----------------------------------------
-- Message receiving
----------------------------------------
do
local compost = setmetatable({}, {__mode = "k"})
local function new()
local t = next(compost)
if t then
compost[t]=nil
for i=tgetn(t),3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
tremove(t) -- Ace3v: t[i] = nil wont affect the tgetn return value
end
return t
end
return {}
end
local function lostdatawarning(prefix,sender,where)
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
end
function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
--[[
if spool[key] then
lostdatawarning(prefix,sender,"First")
-- continue and overwrite
end
--]]
spool[key] = message -- plain string for now
end
function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"Next")
return
end
if type(olddata)~="table" then
-- ... but what we have is not a table. So make it one. (Pull a composted one if available)
local t = new()
t[1] = olddata -- add old data as first string
t[2] = message -- and new message as second string
spool[key] = t -- and put the table in the spool instead of the old string
else
tinsert(olddata, message)
end
end
function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"End")
return
end
spool[key] = nil
if type(olddata) == "table" then
-- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
tinsert(olddata, message)
AceComm.callbacks:Fire(prefix, 3, tconcat(olddata, ""), distribution, sender)
compost[olddata] = true
else
-- if we've only received a "first", the spooled data will still only be a string
AceComm.callbacks:Fire(prefix, 3, olddata..message, distribution, sender)
end
end
end
----------------------------------------
-- Embed CallbackHandler
----------------------------------------
if not AceComm.callbacks then
AceComm.callbacks = CallbackHandler:New(AceComm,
"_RegisterComm",
"UnregisterComm",
"UnregisterAllComm")
end
AceComm.callbacks.OnUsed = nil
AceComm.callbacks.OnUnused = nil
-- Ace3v: in vanilla, global vars:
-- event -> event type
-- arg1 -> prefix
-- arg2 -> message
-- arg3 -> channel
-- arg4 -> sender
local function OnEvent()
local prefix, message, distribution, sender = arg1, arg2, arg3, arg4
if event == "CHAT_MSG_ADDON" then
local _, _, control, rest = strfind(message, "^([\001-\009])(.*)")
if control then
if control==MSG_MULTI_FIRST then
AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_NEXT then
AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_LAST then
AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
elseif control==MSG_ESCAPE then
AceComm.callbacks:Fire(prefix, 3, rest, distribution, sender)
else
-- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
end
else
-- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
AceComm.callbacks:Fire(prefix, 3, message, distribution, sender)
end
else
assert(false, "Received "..tostring(event).." event?!")
end
end
AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
AceComm.frame:SetScript("OnEvent", OnEvent)
AceComm.frame:UnregisterAllEvents()
AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
----------------------------------------
-- Base library stuff
----------------------------------------
local mixins = {
"RegisterComm",
"UnregisterComm",
"UnregisterAllComm",
"SendCommMessage",
}
-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceComm-3.0 in
function AceComm:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
function AceComm:OnEmbedDisable(target)
target:UnregisterAllComm()
end
-- Update embeds
for target, v in pairs(AceComm.embeds) do
AceComm:Embed(target)
end
@@ -0,0 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="ChatThrottleLib.lua"/>
<Script file="AceComm-3.0.lua"/>
</Ui>
@@ -0,0 +1,527 @@
--
-- ChatThrottleLib by Mikk
--
-- Manages AddOn chat output to keep player from getting kicked off.
--
-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
--
-- Priorities get an equal share of available bandwidth when fully loaded.
-- Communication channels are separated on extension+chattype+destination and
-- get round-robinned. (Destination only matters for whispers and channels,
-- obviously)
--
-- Will install hooks for SendChatMessage and SendAddonMessage to measure
-- bandwidth bypassing the library and use less bandwidth itself.
--
--
-- Fully embeddable library. Just copy this file into your addon directory,
-- add it to the .toc, and it's done.
--
-- Can run as a standalone addon also, but, really, just embed it! :-)
--
-- LICENSE: ChatThrottleLib is released into the Public Domain
--
local CTL_VERSION = 23
local AceCore = LibStub("AceCore-3.0")
local _G = AceCore._G
local hooksecurefunc = AceCore.hooksecurefunc
local wipe = AceCore.wipe
if _G.ChatThrottleLib then
if _G.ChatThrottleLib.version >= CTL_VERSION then
-- There's already a newer (or same) version loaded. Buh-bye.
return
elseif not _G.ChatThrottleLib.securelyHooked then
print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, <v16) in an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=v16) in it!")
-- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
-- ... and if someone has securehooked, they can kiss that goodbye too... >.<
_G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
if _G.ChatThrottleLib.ORIG_SendAddonMessage then
_G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
end
end
_G.ChatThrottleLib.ORIG_SendChatMessage = nil
_G.ChatThrottleLib.ORIG_SendAddonMessage = nil
end
if not _G.ChatThrottleLib then
_G.ChatThrottleLib = {}
end
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
local ChatThrottleLib = _G.ChatThrottleLib
ChatThrottleLib.version = CTL_VERSION
------------------ TWEAKABLES -----------------
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
local setmetatable = setmetatable
local table_remove = table.remove
local tinsert = table.insert
local tostring = tostring
local GetTime = GetTime
local math_min = math.min
local math_max = math.max
local next = next
local strlen = string.len
local GetFramerate = GetFramerate
local strlower = string.lower
local unpack,type,pairs,wipe = unpack,type,pairs,wipe
local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty
-----------------------------------------------------------------------
-- Double-linked ring implementation
local Ring = {}
local RingMeta = { __index = Ring }
function Ring:New()
local ret = {}
setmetatable(ret, RingMeta)
return ret
end
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if self.pos then
obj.prev = self.pos.prev
obj.prev.next = obj
obj.next = self.pos
obj.next.prev = obj
else
obj.next = obj
obj.prev = obj
self.pos = obj
end
end
function Ring:Remove(obj)
obj.next.prev = obj.prev
obj.prev.next = obj.next
if self.pos == obj then
self.pos = obj.next
if self.pos == obj then
self.pos = nil
end
end
end
-----------------------------------------------------------------------
-- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue of messages
-- Pipes normally live in Rings of pipes (3 rings total, one per priority)
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"})
local function DelPipe(pipe)
PipeBin[pipe] = true
end
local function NewPipe()
local pipe = next(PipeBin)
if pipe then
wipe(pipe)
PipeBin[pipe] = nil
return pipe
end
return {}
end
-----------------------------------------------------------------------
-- Recycling bin for messages
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
local MsgBin = setmetatable({}, {__mode="k"})
local function DelMsg(msg)
msg[1] = nil
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
MsgBin[msg] = true
end
local function NewMsg()
local msg = next(MsgBin)
if msg then
MsgBin[msg] = nil
return msg
end
return {}
end
-----------------------------------------------------------------------
-- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc
function ChatThrottleLib:Init()
-- Set up queues
if not self.Prio then
self.Prio = {}
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
end
-- v4: total send counters per priority
for _, Prio in pairs(self.Prio) do
Prio.nTotalSent = Prio.nTotalSent or 0
end
if not self.avail then
self.avail = 0 -- v5
end
if not self.nTotalSent then
self.nTotalSent = 0 -- v5
end
-- Set up a frame to get OnUpdate events
if not self.Frame then
self.Frame = CreateFrame("Frame")
self.Frame:Hide()
end
self.Frame:SetScript("OnUpdate", self.OnUpdate)
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.OnUpdateDelay = 0
self.LastAvailUpdate = GetTime()
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if not self.securelyHooked then
-- Use secure hooks as of v16. Old regular hook support yanked out in v21.
self.securelyHooked = true
--SendChatMessage
hooksecurefunc("SendChatMessage", function(text, chattype, language, destination)
return ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
end)
--SendAddonMessage
hooksecurefunc("SendAddonMessage", function(prefix, text, chattype, destination)
return ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination)
end)
end
self.nBypass = 0
end
-----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
local bMyTraffic = false
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(prefix or ""));
size = size + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
-----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available
function ChatThrottleLib:UpdateAvail()
local now = GetTime()
local MAX_CPS = self.MAX_CPS;
local newavail = MAX_CPS * (now - self.LastAvailUpdate)
local avail = self.avail
if now - self.HardThrottlingBeginTime < 5 then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5)
self.bChoking = true -- just a statistic
else
avail = math_min(self.BURST, avail + newavail)
self.bChoking = false
end
avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
self.avail = avail
self.LastAvailUpdate = now
return avail
end
-----------------------------------------------------------------------
-- Despooling logic
-- Reminder:
-- - We have 3 Priorities, each containing a "Ring" construct ...
-- - ... made up of N "Pipe"s (1 for each destination/pipename)
-- - and each pipe contains messages
function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(ring.pos, 1)
if not ring.pos[1] then -- did we remove last msg in this pipe?
local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil
DelPipe(pipe)
else
Prio.Ring.pos = Prio.Ring.pos.next
end
local didSend=false
local lowerDest = strlower(msg[3] or "")
if lowerDest == "raid" and not UnitInRaid("player") then
-- do nothing
elseif lowerDest == "party" and not UnitInParty("player") then
-- do nothing
else
Prio.avail = Prio.avail - msg.nSize
bMyTraffic = true
msg.f(unpack(msg, 1, msg.n))
bMyTraffic = false
Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg)
didSend = true
end
-- notify caller of delivery (even if we didn't send it)
if msg.callbackFn then
msg.callbackFn (msg.callbackArg, didSend)
end
-- USER CALLBACK MAY ERROR
end
end
function ChatThrottleLib.OnEvent()
-- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
local self = ChatThrottleLib
if event == "PLAYER_ENTERING_WORLD" then
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
self.avail = 0
end
end
function ChatThrottleLib.OnUpdate()
local self = ChatThrottleLib
self.OnUpdateDelay = self.OnUpdateDelay + arg1
if self.OnUpdateDelay < 0.08 then
return
end
self.OnUpdateDelay = 0
self:UpdateAvail()
if self.avail < 0 then
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
end
-- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
local n = 0
for prioname,Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
n = n + 1
end
end
-- Anything queued still?
if n<1 then
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
for prioname, Prio in pairs(self.Prio) do
self.avail = self.avail + Prio.avail
Prio.avail = 0
end
self.bQueueing = false
self.Frame:Hide()
return
end
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
local avail = self.avail/n
self.avail = 0
for prioname, Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
Prio.avail = Prio.avail + avail
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
self:Despool(Prio)
-- Note: We might not get here if the user-supplied callback function errors out! Take care!
end
end
end
end
-----------------------------------------------------------------------
-- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename]
if not pipe then
self.Frame:Show()
pipe = NewPipe()
pipe.name = pipename
Prio.ByName[pipename] = pipe
Prio.Ring:Add(pipe)
end
tinsert(pipe,msg)
self.bQueueing = true
end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = strlen(text)
if nSize>255 then
error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
end
nSize = nSize + self.MSG_OVERHEAD
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendChatMessage(text, chattype, language, destination)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg, true)
end
-- USER CALLBACK MAY ERROR
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendChatMessage
msg[1] = text
msg[2] = chattype or "SAY"
msg[3] = language
msg[4] = destination
msg.n = 4
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
end
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = strlen(text);
if RegisterAddonMessagePrefix then
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
end
else
nSize = nSize + strlen(prefix) + 1
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
end
end
nSize = nSize + self.MSG_OVERHEAD;
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendAddonMessage(prefix, text, chattype, target)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg, true)
end
-- USER CALLBACK MAY ERROR
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendAddonMessage
msg[1] = prefix
msg[2] = text
msg[3] = chattype
msg[4] = target
msg.n = (target~=nil) and 4 or 3;
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
end
-----------------------------------------------------------------------
-- Get the ball rolling!
ChatThrottleLib:Init()
--[[ WoWBench debugging snippet
if(WOWB_VER) then
local function SayTimer()
print("SAY: "..GetTime().." "..arg1)
end
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
end
]]
@@ -0,0 +1,250 @@
--- **AceConsole-3.0** provides registration facilities for slash commands.
-- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
-- to your addons individual needs.
--
-- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceConsole itself.\\
-- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceConsole.
-- @class file
-- @name AceConsole-3.0
-- @release $Id: AceConsole-3.0.lua 1143 2016-07-11 08:52:03Z nevcairiel $
local MAJOR,MINOR = "AceConsole-3.0", 7
local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConsole then return end -- No upgrade needed
AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
-- Lua APIs
local tconcat, tostring, select = table.concat, tostring, select
local type, pairs, error = type, pairs, error
local format, strfind, strsub = string.format, string.find, string.sub
local max = math.max
-- WoW APIs
local _G = getfenv()
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
local tmp={}
local function Print(self,frame,...)
local n=0
if self ~= AceConsole then
n=n+1
tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
end
for i=1, getn(arg) do
n=n+1
tmp[n] = tostring(arg[i])
end
frame:AddMessage( tconcat(tmp," ",1,n) )
end
--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] ...
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
-- @param ... List of any values to be printed
function AceConsole:Print(...)
local frame = arg
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, arg[2])
else
return Print(self, DEFAULT_CHAT_FRAME, arg)
end
end
--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] "format"[, ...]
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
-- @param format Format string - same syntax as standard Lua format()
-- @param ... Arguments to the format string
function AceConsole:Printf(...)
local frame = arg
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, format(arg[2]))
else
return Print(self, DEFAULT_CHAT_FRAME, format(arg))
end
end
--- Register a simple chat command
-- @param command Chat command to be registered WITHOUT leading "/"
-- @param func Function to call when the slash command is being used (funcref or methodname)
-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
function AceConsole:RegisterChatCommand( command, func, persist )
if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
local name = "ACECONSOLE_"..string.upper(command)
if type( func ) == "string" then
SlashCmdList[name] = function(input, editBox)
self[func](self, input, editBox)
end
else
SlashCmdList[name] = func
end
_G["SLASH_"..name.."1"] = "/"..string.lower(command)
AceConsole.commands[command] = name
-- non-persisting commands are registered for enabling disabling
if not persist then
if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
AceConsole.weakcommands[self][command] = func
end
return true
end
--- Unregister a chatcommand
-- @param command Chat command to be unregistered WITHOUT leading "/"
function AceConsole:UnregisterChatCommand( command )
local name = AceConsole.commands[command]
if name then
SlashCmdList[name] = nil
_G["SLASH_" .. name .. "1"] = nil
hash_SlashCmdList["/" .. command:upper()] = nil
AceConsole.commands[command] = nil
end
end
--- Get an iterator over all Chat Commands registered with AceConsole
-- @return Iterator (pairs) over all commands
function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
local function nils(n, ...)
if n>1 then
return nil, nils(n-1, arg)
elseif n==1 then
return nil, arg
else
return arg
end
end
--- Retreive one or more space-separated arguments from a string.
-- Treats quoted strings and itemlinks as non-spaced.
-- @param str The raw argument string
-- @param numargs How many arguments to get (default 1)
-- @param startpos Where in the string to start scanning (default 1)
-- @return Returns arg1, arg2, ..., nextposition\\
-- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
function AceConsole:GetArgs(str, numargs, startpos)
numargs = numargs or 1
startpos = max(startpos or 1, 1)
local pos=startpos
-- find start of new arg
pos = strfind(str, "[^ ]", pos)
if not pos then -- whoops, end of string
return nils(numargs, 1e9)
end
if numargs<1 then
return pos
end
-- quoted or space separated? find out which pattern to use
local delim_or_pipe
local ch = strsub(str, pos, pos)
if ch=='"' then
pos = pos + 1
delim_or_pipe='([|"])'
elseif ch=="'" then
pos = pos + 1
delim_or_pipe="([|'])"
else
delim_or_pipe="([| ])"
end
startpos = pos
while true do
-- find delimiter or hyperlink
local ch,_
pos,_,ch = strfind(str, delim_or_pipe, pos)
if not pos then break end
if ch=="|" then
-- some kind of escape
if strsub(str,pos,pos+1)=="|H" then
-- It's a |H....|hhyper link!|h
pos=strfind(str, "|h", pos+2) -- first |h
if not pos then break end
pos=strfind(str, "|h", pos+2) -- second |h
if not pos then break end
elseif strsub(str,pos, pos+1) == "|T" then
-- It's a |T....|t texture
pos=strfind(str, "|t", pos+2)
if not pos then break end
end
pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
else
-- found delimiter, done with this arg
return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
end
end
-- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
return strsub(str, startpos), nils(numargs-1, 1e9)
end
--- embedding and embed handling
local mixins = {
"Print",
"Printf",
"RegisterChatCommand",
"UnregisterChatCommand",
"GetArgs",
}
-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceBucket in
function AceConsole:Embed( target )
for k, v in pairs( mixins ) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
function AceConsole:OnEmbedEnable( target )
if AceConsole.weakcommands[target] then
for command, func in pairs( AceConsole.weakcommands[target] ) do
target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
end
end
end
function AceConsole:OnEmbedDisable( target )
if AceConsole.weakcommands[target] then
for command, func in pairs( AceConsole.weakcommands[target] ) do
target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
end
end
end
for addon in pairs(AceConsole.embeds) do
AceConsole:Embed(addon)
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceConsole-3.0.lua"/>
</Ui>
@@ -0,0 +1,205 @@
local ACECORE_MAJOR, ACECORE_MINOR = "AceCore-3.0", 1
local AceCore, oldminor = LibStub:NewLibrary(ACECORE_MAJOR, ACECORE_MINOR)
if not AceCore then return end -- No upgrade needed
AceCore._G = AceCore._G or getfenv()
local _G = AceCore._G
local strsub, strgsub, strfind = string.sub, string.gsub, string.find
local tremove, tconcat = table.remove, table.concat
local tgetn, tsetn = table.getn, table.setn
local new, del
do
local list = setmetatable({}, {__mode = "k"})
function new()
local t = next(list)
if not t then
return {}
end
list[t] = nil
return t
end
function del(t)
setmetatable(t, nil)
for k in pairs(t) do
t[k] = nil
end
tsetn(t,0)
list[t] = true
end
-- debug
function AceCore.listcount()
local count = 0
for k in list do
count = count + 1
end
return count
end
end -- AceCore.new, AceCore.del
AceCore.new, AceCore.del = new, del
local function errorhandler(err)
return geterrorhandler()(err)
end
AceCore.errorhandler = errorhandler
local function CreateSafeDispatcher(argCount)
local code = [[
local errorhandler = LibStub("AceCore-3.0").errorhandler
local method, UP_ARGS
local function call()
local func, ARGS = method, UP_ARGS
method, UP_ARGS = nil, NILS
return func(ARGS)
end
return function(func, ARGS)
method, UP_ARGS = func, ARGS
return xpcall(call, errorhandler)
end
]]
local c = 4*argCount-1
local s = "b01,b02,b03,b04,b05,b06,b07,b08,b09,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20"
code = strgsub(code, "UP_ARGS", string.sub(s,1,c))
s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
code = strgsub(code, "ARGS", string.sub(s,1,c))
s = "nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil"
code = strgsub(code, "NILS", string.sub(s,1,c))
return assert(loadstring(code, "safecall SafeDispatcher["..tostring(argCount).."]"))()
end
local SafeDispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher
if not tonumber(argCount) then dbg(debugstack()) end
if argCount > 0 then
dispatcher = CreateSafeDispatcher(argCount)
else
dispatcher = function(func) return xpcall(func,errorhandler) end
end
rawset(self, argCount, dispatcher)
return dispatcher
end})
local function safecall(func,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return SafeDispatchers[argc](func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
end
end
AceCore.safecall = safecall
local function CreateDispatcher(argCount)
local code = [[
return function(func,ARGS)
return func(ARGS)
end
]]
local s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
code = strgsub(code, "ARGS", string.sub(s,1,4*argCount-1))
return assert(loadstring(code, "call Dispatcher["..tostring(argCount).."]"))()
end
AceCore.Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher
if argCount > 0 then
dispatcher = CreateDispatcher(argCount)
else
dispatcher = function(func) return func() end
end
rawset(self, argCount, dispatcher)
return dispatcher
end})
-- some string functions
-- vanilla available string operations:
-- sub, gfind, rep, gsub, char, dump, find, upper, len, format, byte, lower
-- we will just replace every string.match with string.find in the code
function AceCore.strtrim(s)
return strgsub(s, "^%s*(.-)%s*$", "%1")
end
local function strsplit(delim, s, n)
if n and n < 2 then return s end
beg = beg or 1
local i,j = string.find(s,delim,beg)
if not i then
return s, nil
end
return string.sub(s,1,j-1), strsplit(delim, string.sub(s,j+1), n and n-1 or nil)
end
AceCore.strsplit = strsplit
-- Ace3v: fonctions copied from AceHook-2.1
local protFuncs = {
CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
TurnOrActionStart = true, TurnOrActionStop = true,
PitchUpStart = true, PitchUpStop = true,
PitchDownStart = true, PitchDownStop = true,
MoveBackwardStart = true, MoveBackwardStop = true,
MoveForwardStart = true, MoveForwardStop = true,
Jump = true, StrafeLeftStart = true,
StrafeLeftStop = true, StrafeRightStart = true,
StrafeRightStop = true, ToggleMouseMove = true,
ToggleRun = true, TurnLeftStart = true,
TurnLeftStop = true, TurnRightStart = true,
TurnRightStop = true,
}
local function issecurevariable(x)
return protFuncs[x] and 1 or nil
end
AceCore.issecurevariable = issecurevariable
local function hooksecurefunc(arg1, arg2, arg3)
if type(arg1) == "string" then
arg1, arg2, arg3 = _G, arg1, arg2
end
local orig = arg1[arg2]
if type(orig) ~= "function" then
error("The function "..arg2.." does not exist", 2)
end
arg1[arg2] = function(...)
local tmp = {orig(unpack(arg))}
arg3(unpack(arg))
return unpack(tmp)
end
end
AceCore.hooksecurefunc = hooksecurefunc
-- pickfirstset() - picks the first non-nil value and returns it
local function pickfirstset(argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
if (argc <= 1) or (a1 ~= nil) then
return a1
else
return pickfirstset(argc-1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
end
end
AceCore.pickfirstset = pickfirstset
local function countargs(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
if (a1 == nil) then return 0 end
return 1 + countargs(a2,a3,a4,a5,a6,a7,a8,a9,a10)
end
AceCore.countargs = countargs
-- wipe preserves metatable
function AceCore.wipe(t)
for k,v in pairs(t) do t[k] = nil end
tsetn(t,0)
return t
end
function AceCore.truncate(t,e)
e = e or tgetn(t)
for i=1,e do
if t[i] == nil then
tsetn(t,i-1)
return
end
end
tsetn(t,e)
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceCore-3.0.lua"/>
</Ui>
@@ -0,0 +1,755 @@
--- **AceDB-3.0** manages the SavedVariables of your addon.
-- It offers profile management, smart defaults and namespaces for modules.\\
-- Data can be saved in different data-types, depending on its intended usage.
-- The most common data-type is the `profile` type, which allows the user to choose
-- the active profile, and manage the profiles of all of his characters.\\
-- The following data types are available:
-- * **char** Character-specific data. Every character has its own database.
-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
-- * **class** Class-specific data. All of the players characters of the same class share this database.
-- * **race** Race-specific data. All of the players characters of the same race share this database.
-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
-- * **locale** Locale specific data, based on the locale of the players game client.
-- * **global** Global Data. All characters on the same account share this database.
-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
--
-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
-- of the DBObjectLib listed here. \\
-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
--
-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
--
-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
--
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
--
-- -- declare defaults to be used in the DB
-- local defaults = {
-- profile = {
-- setting = true,
-- }
-- }
--
-- function MyAddon:OnInitialize()
-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
-- end
-- @class file
-- @name AceDB-3.0.lua
-- @release $Id: AceDB-3.0.lua 1142 2016-07-11 08:36:19Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
if not AceDB then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
-- Lua APIs
local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-- WoW APIs
local _G = AceCore._G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub
AceDB.db_registry = AceDB.db_registry or {}
AceDB.frame = AceDB.frame or CreateFrame("Frame")
local CallbackHandler
local CallbackDummy = { Fire = function() end }
local DBObjectLib = {}
-- Ace3v: for all recursive functions we must declare the iterator as local again, this step is necessary in vanilla
-- Example:
-- for k,v in pairs(table) do
-- local v = v
-- ...
--[[-------------------------------------------------------------------------
AceDB Utility Functions
---------------------------------------------------------------------------]]
-- Simple shallow copy for copying defaults
local function copyTable(src, dest)
if type(dest) ~= "table" then dest = {} end
if type(src) == "table" then
for k,v in pairs(src) do
local v = v
if type(v) == "table" then
-- try to index the key first so that the metatable creates the defaults, if set, and use that table
v = copyTable(v, dest[k])
end
dest[k] = v
end
end
return dest
end
-- Called to add defaults to a section of the database
--
-- When a ["*"] default section is indexed with a new key, a table is returned
-- and set in the host table. These tables must be cleaned up by removeDefaults
-- in order to ensure we don't write empty default tables.
local function copyDefaults(dest, src)
-- this happens if some value in the SV overwrites our default value with a non-table
--if type(dest) ~= "table" then return end
for k, v in pairs(src) do
local v = v
if k == "*" or k == "**" then
if type(v) == "table" then
-- This is a metatable used for table defaults
local mt = {
-- This handles the lookup and creation of new subtables
__index = function(t,k)
if k == nil then return nil end
local tbl = {}
copyDefaults(tbl, v)
rawset(t, k, tbl)
return tbl
end,
}
setmetatable(dest, mt)
-- handle already existing tables in the SV
for dk, dv in pairs(dest) do
if not rawget(src, dk) and type(dv) == "table" then
copyDefaults(dv, v)
end
end
else
-- Values are not tables, so this is just a simple return
local mt = {__index = function(t,k) return k~=nil and v or nil end}
setmetatable(dest, mt)
end
elseif type(v) == "table" then
if not rawget(dest, k) then rawset(dest, k, {}) end
if type(dest[k]) == "table" then
copyDefaults(dest[k], v)
if src['**'] then
copyDefaults(dest[k], src['**'])
end
end
else
if rawget(dest, k) == nil then
rawset(dest, k, v)
end
end
end
end
-- Called to remove all defaults in the default table from the database
local function removeDefaults(db, defaults, blocker)
-- remove all metatables from the db, so we don't accidentally create new sub-tables through them
setmetatable(db, nil)
-- loop through the defaults and remove their content
for k,v in pairs(defaults) do
local v = v
if k == "*" or k == "**" then
if type(v) == "table" then
-- Loop through all the actual k,v pairs and remove
for key, value in pairs(db) do
local value = value
if type(value) == "table" then
-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
if defaults[key] == nil and (not blocker or blocker[key] == nil) then
removeDefaults(value, v)
-- if the table is empty afterwards, remove it
if next(value) == nil then
db[key] = nil
end
-- if it was specified, only strip ** content, but block values which were set in the key table
elseif k == "**" then
removeDefaults(value, v, defaults[key])
end
end
end
elseif k == "*" then
-- check for non-table default
for key, value in pairs(db) do
if defaults[key] == nil and v == value then
db[key] = nil
end
end
end
elseif type(v) == "table" and type(db[k]) == "table" then
-- if a blocker was set, dive into it, to allow multi-level defaults
removeDefaults(db[k], v, blocker and blocker[k])
if next(db[k]) == nil then
db[k] = nil
end
else
-- check if the current value matches the default, and that its not blocked by another defaults table
if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
db[k] = nil
end
end
end
end
-- This is called when a table section is first accessed, to set up the defaults
local function initSection(db, section, svstore, key, defaults)
local sv = rawget(db, "sv")
local tableCreated
if not sv[svstore] then sv[svstore] = {} end
if not sv[svstore][key] then
sv[svstore][key] = {}
tableCreated = true
end
local tbl = sv[svstore][key]
if defaults then
copyDefaults(tbl, defaults)
end
rawset(db, section, tbl)
return tableCreated, tbl
end
-- Metatable to handle the dynamic creation of sections and copying of sections.
local dbmt = {
__index = function(t, section)
local keys = rawget(t, "keys")
local key = keys[section]
if key then
local defaultTbl = rawget(t, "defaults")
local defaults = defaultTbl and defaultTbl[section]
if section == "profile" then
if initSection(t, section, "profiles", key, defaults) then
-- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", 2, t, key)
end
elseif section == "profiles" then
local sv = rawget(t, "sv")
if not sv.profiles then sv.profiles = {} end
rawset(t, "profiles", sv.profiles)
elseif section == "global" then
local sv = rawget(t, "sv")
if not sv.global then sv.global = {} end
if defaults then
copyDefaults(sv.global, defaults)
end
rawset(t, section, sv.global)
else
initSection(t, section, section, key, defaults)
end
end
return rawget(t, section)
end
}
local function validateDefaults(defaults, keyTbl, offset)
if not defaults then return end
offset = offset or 0
for k in pairs(defaults) do
if not keyTbl[k] or k == "profiles" then
error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
end
end
end
local preserve_keys = {
["callbacks"] = true,
["RegisterCallback"] = true,
["UnregisterCallback"] = true,
["UnregisterAllCallbacks"] = true,
["children"] = true,
}
local realmKey = GetRealmName()
local charKey = UnitName("player") .. " - " .. realmKey
local _, classKey = UnitClass("player")
local _, raceKey = UnitRace("player")
local _, factionKey = UnitFactionGroup("player")
-- Ace3v: the faction key may error when in GM mode
factionKey = factionKey or "Others"
local localeKey = string.lower(GetLocale())
-- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent)
-- Generate the database keys for each section
-- map "true" to our "Default" profile
if defaultProfile == true then defaultProfile = "Default" end
local profileKey
if not parent then
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
-- Try to get the profile selected from the char db
profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
-- save the selected profile for later
sv.profileKeys[charKey] = profileKey
else
-- Use the profile of the parents DB
profileKey = parent.keys.profile or defaultProfile or charKey
-- clear the profileKeys in the DB, namespaces don't need to store them
sv.profileKeys = nil
end
-- This table contains keys that enable the dynamic creation
-- of each section of the table. The 'global' and 'profiles'
-- have a key of true, since they are handled in a special case
local keyTbl= {
["char"] = charKey,
["realm"] = realmKey,
["class"] = classKey,
["race"] = raceKey,
["faction"] = factionKey,
["factionrealm"] = factionKey .. " - " .. realmKey,
["profile"] = profileKey,
["locale"] = localeKey,
["global"] = true,
["profiles"] = true,
}
validateDefaults(defaults, keyTbl, 1)
-- This allows us to use this function to reset an entire database
-- Clear out the old database
if olddb then
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
end
-- Give this database the metatable so it initializes dynamically
local db = setmetatable(olddb or {}, dbmt)
if not rawget(db, "callbacks") then
-- try to load CallbackHandler-1.0 if it loaded after our library
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
end
-- Copy methods locally into the database object, to avoid hitting
-- the metatable when calling methods
if not parent then
for name, func in pairs(DBObjectLib) do
db[name] = func
end
else
-- hack this one in
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
-- Set some properties in the database object
db.profiles = sv.profiles
db.keys = keyTbl
db.sv = sv
--db.sv_name = name
db.defaults = defaults
db.parent = parent
-- store the DB in the registry
AceDB.db_registry[db] = true
return db
end
-- handle PLAYER_LOGOUT
-- strip all defaults from all databases
-- and cleans up empty sections
local function logoutHandler()
if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", 1, db)
db:RegisterDefaults(nil)
-- cleanup sections that are empty without defaults
local sv = rawget(db, "sv")
for section in pairs(db.keys) do
if rawget(sv, section) then
-- global is special, all other sections have sub-entrys
-- also don't delete empty profiles on main dbs, only on namespaces
if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
for key in pairs(sv[section]) do
if not next(sv[section][key]) then
sv[section][key] = nil
end
end
end
if not next(sv[section]) then
sv[section] = nil
end
end
end
end
end
end
AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
AceDB.frame:SetScript("OnEvent", logoutHandler)
--[[-------------------------------------------------------------------------
AceDB Object Method Definitions
---------------------------------------------------------------------------]]
--- Sets the defaults table for the given database object by clearing any
-- that are currently set, and then setting the new defaults.
-- @param defaults A table of defaults for this database
function DBObjectLib:RegisterDefaults(defaults)
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
end
validateDefaults(defaults, self.keys)
-- Remove any currently set defaults
if self.defaults then
for section,key in pairs(self.keys) do
if self.defaults[section] and rawget(self, section) then
removeDefaults(self[section], self.defaults[section])
end
end
end
-- Set the DBObject.defaults table
self.defaults = defaults
-- Copy in any defaults, only touching those sections already created
if defaults then
for section,key in pairs(self.keys) do
if defaults[section] and rawget(self, section) then
copyDefaults(self[section], defaults[section])
end
end
end
end
--- Changes the profile of the database and all of it's namespaces to the
-- supplied named profile
-- @param name The name of the profile to set as the current profile
function DBObjectLib:SetProfile(name)
if type(name) ~= "string" then
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
end
-- changing to the same profile, dont do anything
if name == self.keys.profile then return end
local oldProfile = self.profile
local defaults = self.defaults and self.defaults.profile
-- Callback: OnProfileShutdown, database
self.callbacks:Fire("OnProfileShutdown", 1, self)
if oldProfile and defaults then
-- Remove the defaults from the old profile
removeDefaults(oldProfile, defaults)
end
self.profile = nil
self.keys["profile"] = name
-- if the storage exists, save the new profile
-- this won't exist on namespaces.
if self.sv.profileKeys then
self.sv.profileKeys[charKey] = name
end
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.SetProfile(db, name)
end
end
-- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", 2, self, name)
end
--- Returns a table with the names of the existing profiles in the database.
-- You can optionally supply a table to re-use for this purpose.
-- @param tbl A table to store the profile names in (optional)
function DBObjectLib:GetProfiles(tbl)
if tbl and type(tbl) ~= "table" then
error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
end
-- Clear the container table
if tbl then
for k,v in pairs(tbl) do tbl[k] = nil end
else
tbl = {}
end
local curProfile = self.keys.profile
local i = 0
for profileKey in pairs(self.profiles) do
i = i + 1
tbl[i] = profileKey
if curProfile and profileKey == curProfile then curProfile = nil end
end
-- Add the current profile, if it hasn't been created yet
if curProfile then
i = i + 1
tbl[i] = curProfile
end
return tbl, i
end
--- Returns the current profile name used by the database
function DBObjectLib:GetCurrentProfile()
return self.keys.profile
end
--- Deletes a named profile. This profile must not be the active profile.
-- @param name The name of the profile to be deleted
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:DeleteProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
end
if self.keys.profile == name then
error("Cannot delete the active profile in an AceDBObject.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
end
self.profiles[name] = nil
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.DeleteProfile(db, name, true)
end
end
-- switch all characters that use this profile back to the default
if self.sv.profileKeys then
for key, profile in pairs(self.sv.profileKeys) do
if profile == name then
self.sv.profileKeys[key] = nil
end
end
end
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", 2, self, name)
end
--- Copies a named profile into the current profile, overwriting any conflicting
-- settings.
-- @param name The name of the profile to be copied into the current profile
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:CopyProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
end
if name == self.keys.profile then
error("Cannot have the same source and destination profiles.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
end
-- Reset the profile before copying
DBObjectLib.ResetProfile(self, nil, true)
local profile = self.profile
local source = self.profiles[name]
copyTable(source, profile)
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.CopyProfile(db, name, true)
end
end
-- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", 2, self, name)
end
--- Resets the current profile to the default values (if specified).
-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
function DBObjectLib:ResetProfile(noChildren, noCallbacks)
local profile = self.profile
for k,v in pairs(profile) do
profile[k] = nil
end
local defaults = self.defaults and self.defaults.profile
if defaults then
copyDefaults(profile, defaults)
end
-- populate to child namespaces
if self.children and not noChildren then
for _, db in pairs(self.children) do
DBObjectLib.ResetProfile(db, nil, noCallbacks)
end
end
-- Callback: OnProfileReset, database
if not noCallbacks then
self.callbacks:Fire("OnProfileReset", 2, self, self.keys["profile"])
end
end
--- Resets the entire database, using the string defaultProfile as the new default
-- profile.
-- @param defaultProfile The profile name to use as the default
function DBObjectLib:ResetDB(defaultProfile)
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
end
local sv = self.sv
for k,v in pairs(sv) do
sv[k] = nil
end
local parent = self.parent
initdb(sv, self.defaults, defaultProfile, self)
-- fix the child namespaces
if self.children then
if not sv.namespaces then sv.namespaces = {} end
for name, db in pairs(self.children) do
if not sv.namespaces[name] then sv.namespaces[name] = {} end
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
end
end
-- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", 1, self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", 2, self, self.keys["profile"])
return self
end
--- Creates a new database namespace, directly tied to the database. This
-- is a full scale database in it's own rights other than the fact that
-- it cannot control its profile individually
-- @param name The name of the new namespace
-- @param defaults A table of values to use as defaults
function DBObjectLib:RegisterNamespace(name, defaults)
if type(name) ~= "string" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
end
if self.children and self.children[name] then
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
end
local sv = self.sv
if not sv.namespaces then sv.namespaces = {} end
if not sv.namespaces[name] then
sv.namespaces[name] = {}
end
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
if not self.children then self.children = {} end
self.children[name] = newDB
return newDB
end
--- Returns an already existing namespace from the database object.
-- @param name The name of the new namespace
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- local namespace = self.db:GetNamespace('namespace')
-- @return the namespace object if found
function DBObjectLib:GetNamespace(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
end
if not silent and not (self.children and self.children[name]) then
error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
end
if not self.children then self.children = {} end
return self.children[name]
end
--[[-------------------------------------------------------------------------
AceDB Exposed Methods
---------------------------------------------------------------------------]]
--- Creates a new database object that can be used to handle database settings and profiles.
-- By default, an empty DB is created, using a character specific profile.
--
-- You can override the default profile used by passing any profile name as the third argument,
-- or by passing //true// as the third argument to use a globally shared profile called "Default".
--
-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
-- will use a profile named "char", and not a character-specific profile.
-- @param tbl The name of variable, or table to use for the database
-- @param defaults A table of database defaults
-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
-- You can also pass //true// to use a shared global profile called "Default".
-- @usage
-- -- Create an empty DB using a character-specific default profile.
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
-- @usage
-- -- Create a DB using defaults and using a shared default profile
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
function AceDB:New(tbl, defaults, defaultProfile)
if type(tbl) == "string" then
local name = tbl
tbl = _G[name]
if not tbl then
tbl = {}
_G[name] = tbl
end
end
if type(tbl) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
end
if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
end
return initdb(tbl, defaults, defaultProfile)
end
-- upgrade existing databases
for db in pairs(AceDB.db_registry) do
if not db.parent then
for name,func in pairs(DBObjectLib) do
db[name] = func
end
else
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceDB-3.0.lua"/>
</Ui>
@@ -0,0 +1,129 @@
--- AceEvent-3.0 provides event registration and secure dispatching.
-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
-- CallbackHandler, and dispatches all game events or addon message to the registrees.
--
-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceEvent itself.\\
-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceEvent.
-- @class file
-- @name AceEvent-3.0
-- @release $Id: AceEvent-3.0.lua 975 2010-10-23 11:26:18Z nevcairiel $
local MAJOR, MINOR = "AceEvent-3.0", 3
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
if not AceEvent then return end
-- Lua APIs
local pairs = pairs
local CallbackHandler = LibStub("CallbackHandler-1.0")
AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
-- APIs and registry for blizzard events, using CallbackHandler lib
if not AceEvent.events then
AceEvent.events = CallbackHandler:New(AceEvent,
"RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
end
function AceEvent.events:OnUsed(target, eventname)
AceEvent.frame:RegisterEvent(eventname)
end
function AceEvent.events:OnUnused(target, eventname)
AceEvent.frame:UnregisterEvent(eventname)
end
-- APIs and registry for IPC messages, using CallbackHandler lib
if not AceEvent.messages then
AceEvent.messages = CallbackHandler:New(AceEvent,
"RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
)
AceEvent.SendMessage = AceEvent.messages.Fire
end
--- embedding and embed handling
local mixins = {
"RegisterEvent", "UnregisterEvent",
"RegisterMessage", "UnregisterMessage",
"SendMessage",
"UnregisterAllEvents", "UnregisterAllMessages",
}
--- Register for a Blizzard Event.
-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
-- Any arguments to the event will be passed on after that.
-- @name AceEvent:RegisterEvent
-- @class function
-- @paramsig event[, callback [, arg]]
-- @param event The event to register for
-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
-- @param arg An optional argument to pass to the callback function
--- Unregister an event.
-- @name AceEvent:UnregisterEvent
-- @class function
-- @paramsig event
-- @param event The event to unregister
--- Register for a custom AceEvent-internal message.
-- The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied)
-- Any arguments to the event will be passed on after that.
-- @name AceEvent:RegisterMessage
-- @class function
-- @paramsig message[, callback [, arg]]
-- @param message The message to register for
-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
-- @param arg An optional argument to pass to the callback function
--- Unregister a message
-- @name AceEvent:UnregisterMessage
-- @class function
-- @paramsig message
-- @param message The message to unregister
--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
-- @name AceEvent:SendMessage
-- @class function
-- @paramsig message, ...
-- @param message The message to send
-- @param ... Any arguments to the message
-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceEvent in
function AceEvent:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
-- AceEvent:OnEmbedDisable( target )
-- target (object) - target object that is being disabled
--
-- Unregister all events messages etc when the target disables.
-- this method should be called by the target manually or by an addon framework
function AceEvent:OnEmbedDisable(target)
target:UnregisterAllEvents()
target:UnregisterAllMessages()
end
-- Script to fire blizzard events into the event listeners
-- Ace3v: in vanilla the arguments are set to global:
-- event, arg1, arg2, arg3 ...
-- the user have always access to them, so we save the table cost here
local events = AceEvent.events
AceEvent.frame:SetScript("OnEvent", function()
events:Fire(event)
end)
--- Finally: upgrade our old embeds
for target, v in pairs(AceEvent.embeds) do
AceEvent:Embed(target)
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceEvent-3.0.lua"/>
</Ui>
@@ -0,0 +1,540 @@
--- **AceHook-3.0** offers safe Hooking/Unhooking of functions, methods and frame scripts.
-- Using AceHook-3.0 is recommended when you need to unhook your hooks again, so the hook chain isn't broken
-- when you manually restore the original function.
--
-- **AceHook-3.0** can be embeded into your addon, either explicitly by calling AceHook:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceHook itself.\\
-- It is recommended to embed AceHook, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceHook.
-- @class file
-- @name AceHook-3.0
-- @release $Id: AceHook-3.0.lua 1118 2014-10-12 08:21:54Z nevcairiel $
local ACEHOOK_MAJOR, ACEHOOK_MINOR = "AceHook-3.0", 8
local AceHook, oldminor = LibStub:NewLibrary(ACEHOOK_MAJOR, ACEHOOK_MINOR)
if not AceHook then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
AceHook.embeded = AceHook.embeded or {}
AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end })
AceHook.handlers = AceHook.handlers or {}
AceHook.actives = AceHook.actives or {}
AceHook.scripts = AceHook.scripts or {}
AceHook.onceSecure = AceHook.onceSecure or {}
AceHook.hooks = AceHook.hooks or {}
-- local upvalues
local registry = AceHook.registry
local handlers = AceHook.handlers
local actives = AceHook.actives
local scripts = AceHook.scripts
local onceSecure = AceHook.onceSecure
-- Lua APIs
local pairs, next, type = pairs, next, type
local format = string.format
local assert, error = assert, error
-- WoW APIs
local hooksecurefunc, issecurevariable = AceCore.hooksecurefunc, AceCore.issecurevariable
local _G = AceCore._G
local protectedScripts = {
OnClick = true,
}
-- upgrading of embeded is done at the bottom of the file
local mixins = {
"Hook", "SecureHook",
"HookScript", "SecureHookScript",
"Unhook", "UnhookAll",
"IsHooked",
"RawHook", "RawHookScript"
}
-- AceHook:Embed( target )
-- target (object) - target object to embed AceHook in
--
-- Embeds AceEevent into the target object making the functions from the mixins list available on target:..
function AceHook:Embed( target )
for k, v in pairs( mixins ) do
target[v] = self[v]
end
self.embeded[target] = true
-- inject the hooks table safely
target.hooks = target.hooks or {}
return target
end
-- AceHook:OnEmbedDisable( target )
-- target (object) - target object that is being disabled
--
-- Unhooks all hooks when the target disables.
-- this method should be called by the target manually or by an addon framework
function AceHook:OnEmbedDisable( target )
target:UnhookAll()
end
-- failsafe means even the hooking method fails, the original method will
-- always be called
local function createHook(self, handler, orig, secure, failsafe)
local uid
local method = type(handler) == "string"
-- Ace3v: when this function called in the "hook" function, we have
-- failsafe = not (raw or secure), so the first check condition
-- is same as "if failsafe" or "if not raw and not secure"
if failsafe and not secure then
-- failsafe hook creation
uid = function(...)
if actives[uid] then
if method then
self[handler](self,unpack(arg))
else
handler(unpack(arg))
end
end
return orig(unpack(arg))
end
-- /failsafe hook
else
-- all other hooks
uid = function(...)
if actives[uid] then
if method then
return self[handler](self,unpack(arg))
else
return handler(unpack(arg))
end
elseif not secure then -- backup on non secure
return orig(unpack(arg))
end
end
-- /hook
end
return uid
end
local function donothing() end
-- @param self
-- @param obj nil or a frame object, use with script = true
-- @param method string, the name of a global function or the name of an object method
-- @param handler function, or string when it's a method of 'self', if nil then will use the same value as method
-- @param script boolean, must be true, if the hooked object is a frame
-- @param secure boolean, if hooking a secure script, if true the original script will be called first, else later
-- @param raw boolean, if raw hooking (replacing the original method)
-- @param forceSecure boolean, if forcing to hook a secure method
-- @param usage
local function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
if not handler then handler = method end
-- These asserts make sure AceHooks's devs play by the rules.
assert(not script or type(script) == "boolean")
assert(not secure or type(secure) == "boolean")
assert(not raw or type(raw) == "boolean")
assert(not forceSecure or type(forceSecure) == "boolean")
assert(usage)
-- Error checking Battery!
if obj and type(obj) ~= "table" then
error(format("%s: 'object' - nil or table expected got %s", usage, type(obj)), 3)
end
if type(method) ~= "string" then
error(format("%s: 'method' - string expected got %s", usage, type(method)), 3)
end
if type(handler) ~= "string" and type(handler) ~= "function" then
error(format("%s: 'handler' - nil, string, or function expected got %s", usage, type(handler)), 3)
end
if type(handler) == "string" and type(self[handler]) ~= "function" then
error(format("%s: 'handler' - Handler specified does not exist at self[handler]", usage), 3)
end
if script then
if not obj or not obj.GetScript or not obj:HasScript(method) then
error(format("%s: You can only hook a script on a frame object", usage), 3)
end
if not secure and obj.IsProtected and obj:IsProtected() and protectedScripts[method] then
error(format("Cannot hook secure script %q; Use SecureHookScript(obj, method, [handler]) instead.", method), 3)
end
else
local issecure
if obj then
issecure = onceSecure[obj] and onceSecure[obj][method] or issecurevariable(obj, method)
else
issecure = onceSecure[method] or issecurevariable(method)
end
if issecure then
if forceSecure then
if obj then
onceSecure[obj] = onceSecure[obj] or {}
onceSecure[obj][method] = true
else
onceSecure[method] = true
end
elseif not secure then
error(format("%s: Attempt to hook secure function %s. Use `SecureHook' or add `true' to the argument list to override.", usage, method), 3)
end
end
end
local uid
if obj then
uid = registry[self][obj] and registry[self][obj][method]
else
uid = registry[self][method]
end
if uid then
if actives[uid] then
-- Only two sane choices exist here. We either a) error 100% of the time or b) always unhook and then hook
-- choice b would likely lead to odd debuging conditions or other mysteries so we're going with a.
error(format("Attempting to rehook already active hook %s.", method))
end
if handlers[uid] == handler then -- turn on a decative hook, note enclosures break this ability, small memory leak
actives[uid] = true
return
elseif obj then -- is there any reason not to call unhook instead of doing the following several lines?
if self.hooks and self.hooks[obj] then
self.hooks[obj][method] = nil
end
registry[self][obj][method] = nil
else
if self.hooks then
self.hooks[method] = nil
end
registry[self][method] = nil
end
handlers[uid], actives[uid], scripts[uid] = nil, nil, nil
uid = nil
end
local orig
if script then
-- Sometimes there is not a original function for a script.
orig = obj:GetScript(method) or donothing
elseif obj then
orig = obj[method]
else
orig = _G[method]
end
if not orig then
error(format("%s: Attempting to hook a non existing target", usage), 3)
end
uid = createHook(self, handler, orig, secure, not (raw or secure))
if obj then
registry[self][obj] = registry[self][obj] or new()
registry[self][obj][method] = uid
if not secure then
self.hooks[obj] = self.hooks[obj] or new()
self.hooks[obj][method] = orig
end
if script then
if not secure then
obj:SetScript(method, uid)
else
obj:SetScript(method, function(...)
local tmp = {orig(unpack(arg))}
uid(unpack(arg))
return unpack(tmp)
end)
--obj:HookScript(method, uid) -- Ace3v: vanilla frame has no HookScript
end
else
if not secure then
obj[method] = uid
else
hooksecurefunc(obj, method, uid)
end
end
else
registry[self][method] = uid
if not secure then
_G[method] = uid
self.hooks[method] = orig
else
hooksecurefunc(method, uid)
end
end
actives[uid], handlers[uid], scripts[uid] = true, handler, script and true or nil
end
--- Hook a function or a method on an object.
-- The hook created will be a "safe hook", that means that your handler will be called
-- before the hooked function ("Pre-Hook"), and you don't have to call the original function yourself,
-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
-- This type of hook is typically used if you need to know if some function got called, and don't want to modify it.
-- @paramsig [object], method, [handler], [hookSecure]
-- @param object The object to hook a method from
-- @param method If object was specified, the name of the method, or the name of the function to hook.
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
-- @param hookSecure If true, AceHook will allow hooking of secure functions.
-- @usage
-- -- create an addon with AceHook embeded
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
--
-- function MyAddon:OnEnable()
-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
-- self:Hook("ActionButton_UpdateHotkeys", true)
-- end
--
-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
-- print(button:GetName() .. " is updating its HotKey")
-- end
function AceHook:Hook(object, method, handler, hookSecure)
if type(object) == "string" then
method, handler, hookSecure, object = object, method, handler, nil
end
if handler == true then
handler, hookSecure = nil, true
end
hook(self, object, method, handler, false, false, false, hookSecure or false, "Usage: Hook([object], method, [handler], [hookSecure])")
end
--- RawHook a function or a method on an object.
-- The hook created will be a "raw hook", that means that your handler will completly replace
-- the original function, and your handler has to call the original function (or not, depending on your intentions).\\
-- The original function will be stored in `self.hooks[object][method]` or `self.hooks[functionName]` respectively.\\
-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
-- or want to control execution of the original function.
-- @paramsig [object], method, [handler], [hookSecure]
-- @param object The object to hook a method from
-- @param method If object was specified, the name of the method, or the name of the function to hook.
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
-- @param hookSecure If true, AceHook will allow hooking of secure functions.
-- @usage
-- -- create an addon with AceHook embeded
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
--
-- function MyAddon:OnEnable()
-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
-- self:RawHook("ActionButton_UpdateHotkeys", true)
-- end
--
-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
-- if button:GetName() == "MyButton" then
-- -- do stuff here
-- else
-- self.hooks.ActionButton_UpdateHotkeys(button, type)
-- end
-- end
function AceHook:RawHook(object, method, handler, hookSecure)
if type(object) == "string" then
method, handler, hookSecure, object = object, method, handler, nil
end
if handler == true then
handler, hookSecure = nil, true
end
hook(self, object, method, handler, false, false, true, hookSecure or false, "Usage: RawHook([object], method, [handler], [hookSecure])")
end
--- SecureHook a function or a method on an object.
-- This function is a wrapper around the `hooksecurefunc` function in the WoW API. Using AceHook
-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
-- required anymore, or the addon is being disabled.\\
-- Secure Hooks should be used if the secure-status of the function is vital to its function,
-- and taint would block execution. Secure Hooks are always called after the original function was called
-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
-- @paramsig [object], method, [handler]
-- @param object The object to hook a method from
-- @param method If object was specified, the name of the method, or the name of the function to hook.
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
function AceHook:SecureHook(object, method, handler)
if type(object) == "string" then
method, handler, object = object, method, nil
end
hook(self, object, method, handler, false, true, false, false, "Usage: SecureHook([object], method, [handler])")
end
--- Hook a script handler on a frame.
-- The hook created will be a "safe hook", that means that your handler will be called
-- before the hooked script ("Pre-Hook"), and you don't have to call the original function yourself,
-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
-- This is the frame script equivalent of the :Hook safe-hook. It would typically be used to be notified
-- when a certain event happens to a frame.
-- @paramsig frame, script, [handler]
-- @param frame The Frame to hook the script on
-- @param script The script to hook
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
-- @usage
-- -- create an addon with AceHook embeded
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
--
-- function MyAddon:OnEnable()
-- -- Hook the OnShow of FriendsFrame
-- self:HookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
-- end
--
-- function MyAddon:FriendsFrameOnShow(frame)
-- print("The FriendsFrame was shown!")
-- end
function AceHook:HookScript(frame, script, handler)
hook(self, frame, script, handler, true, false, false, false, "Usage: HookScript(object, method, [handler])")
end
--- RawHook a script handler on a frame.
-- The hook created will be a "raw hook", that means that your handler will completly replace
-- the original script, and your handler has to call the original script (or not, depending on your intentions).\\
-- The original script will be stored in `self.hooks[frame][script]`.\\
-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
-- or want to control execution of the original script.
-- @paramsig frame, script, [handler]
-- @param frame The Frame to hook the script on
-- @param script The script to hook
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
-- @usage
-- -- create an addon with AceHook embeded
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
--
-- function MyAddon:OnEnable()
-- -- Hook the OnShow of FriendsFrame
-- self:RawHookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
-- end
--
-- function MyAddon:FriendsFrameOnShow(frame)
-- -- Call the original function
-- self.hooks[frame].OnShow(frame)
-- -- Do our processing
-- -- .. stuff
-- end
function AceHook:RawHookScript(frame, script, handler)
hook(self, frame, script, handler, true, false, true, false, "Usage: RawHookScript(object, method, [handler])")
end
--- SecureHook a script handler on a frame.
-- This function is a wrapper around the `frame:HookScript` function in the WoW API. Using AceHook
-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
-- required anymore, or the addon is being disabled.\\
-- Secure Hooks should be used if the secure-status of the function is vital to its function,
-- and taint would block execution. Secure Hooks are always called after the original function was called
-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
-- @paramsig frame, script, [handler]
-- @param frame The Frame to hook the script on
-- @param script The script to hook
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
function AceHook:SecureHookScript(frame, script, handler)
hook(self, frame, script, handler, true, true, false, false, "Usage: SecureHookScript(object, method, [handler])")
end
--- Unhook from the specified function, method or script.
-- @paramsig [obj], method
-- @param obj The object or frame to unhook from
-- @param method The name of the method, function or script to unhook from.
function AceHook:Unhook(obj, method)
local usage = "Usage: Unhook([obj], method)"
if type(obj) == "string" then
method, obj = obj, nil
end
if obj and type(obj) ~= "table" then
error(format("%s: 'obj' - expecting nil or table got %s", usage, type(obj)), 2)
end
if type(method) ~= "string" then
error(format("%s: 'method' - expeting string got %s", usage, type(method)), 2)
end
local uid
if obj then
uid = registry[self][obj] and registry[self][obj][method]
else
uid = registry[self][method]
end
if not uid or not actives[uid] then
-- Declining to error on an unneeded unhook since the end effect is the same and this would just be annoying.
return false
end
actives[uid], handlers[uid] = nil, nil
if obj then
local tmp = registry[self][obj]
tmp[method] = nil
if not next(tmp) then
del(tmp)
registry[self][obj] = nil
end
-- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking
if not self.hooks[obj] or not self.hooks[obj][method] then return true end
if scripts[uid] and obj:GetScript(method) == uid then -- unhooks scripts
obj:SetScript(method, self.hooks[obj][method] ~= donothing and self.hooks[obj][method] or nil)
scripts[uid] = nil
elseif obj and self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then -- unhooks methods
obj[method] = self.hooks[obj][method]
end
tmp = self.hooks[obj]
tmp[method] = nil
if not next(tmp) then
del(tmp)
self.hooks[obj] = nil
end
else
registry[self][method] = nil
-- if self.hooks[method] doesn't exist, then this is a SecureHook, just bail out
if not self.hooks[method] then return true end
if self.hooks[method] and _G[method] == uid then -- unhooks functions
_G[method] = self.hooks[method]
end
self.hooks[method] = nil
end
return true
end
--- Unhook all existing hooks for this addon.
function AceHook:UnhookAll()
for key, value in pairs(registry[self]) do
if type(key) == "table" then
for method in pairs(value) do
self:Unhook(key, method)
end
else
self:Unhook(key)
end
end
end
--- Check if the specific function, method or script is already hooked.
-- @paramsig [obj], method
-- @param obj The object or frame to unhook from
-- @param method The name of the method, function or script to unhook from.
function AceHook:IsHooked(obj, method)
-- we don't check if registry[self] exists, this is done by evil magicks in the metatable
if type(obj) == "string" then
if registry[self][obj] and actives[registry[self][obj]] then
return true, handlers[registry[self][obj]]
end
else
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
return true, handlers[registry[self][obj][method]]
end
end
return false, nil
end
--- Upgrade our old embeded
for target, v in pairs( AceHook.embeded ) do
AceHook:Embed( target )
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceHook-3.0.lua"/>
</Ui>
@@ -0,0 +1,137 @@
--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
-- @class file
-- @name AceLocale-3.0
-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
local MAJOR,MINOR = "AceLocale-3.0", 6
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceLocale then return end -- no upgrade needed
-- Lua APIs
local assert, tostring, error = assert, tostring, error
local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GAME_LOCALE, geterrorhandler
local gameLocale = GetLocale()
if gameLocale == "enGB" then
gameLocale = "enUS"
end
AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
-- This metatable is used on all tables returned from GetLocale
local readmeta = {
__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
rawset(self, key, key) -- only need to see the warning once, really
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
return key
end
}
-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
local readmetasilent = {
__index = function(self, key) -- requesting totally unknown entries: return key
rawset(self, key, key) -- only need to invoke this function once
return key
end
}
-- Remember the locale table being registered right now (it gets set by :NewLocale())
-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
local registering
-- local assert false function
local assertfalse = function() assert(false) end
-- This metatable proxy is used when registering nondefault locales
local writeproxy = setmetatable({}, {
__newindex = function(self, key, value)
rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
end,
__index = assertfalse
})
-- This metatable proxy is used when registering the default locale.
-- It refuses to overwrite existing values
-- Reason 1: Allows loading locales in any order
-- Reason 2: If 2 modules have the same string, but only the first one to be
-- loaded has a translation for the current locale, the translation
-- doesn't get overwritten.
--
local writedefaultproxy = setmetatable({}, {
__newindex = function(self, key, value)
if not rawget(registering, key) then
rawset(registering, key, value == true and key or value)
end
end,
__index = assertfalse
})
--- Register a new locale (or extend an existing one) for the specified application.
-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
-- game locale.
-- @paramsig application, locale[, isDefault[, silent]]
-- @param application Unique name of addon / module
-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
-- @usage
-- -- enUS.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
-- L["string1"] = true
--
-- -- deDE.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
-- if not L then return end
-- L["string1"] = "Zeichenkette1"
-- @return Locale Table to add localizations to, or nil if the current locale is not required.
function AceLocale:NewLocale(application, locale, isDefault, silent)
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
local gameLocale = GAME_LOCALE or gameLocale
local app = AceLocale.apps[application]
if silent and app and getmetatable(app) ~= readmetasilent then
geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
end
if not app then
if silent=="raw" then
app = {}
else
app = setmetatable({}, silent and readmetasilent or readmeta)
end
AceLocale.apps[application] = app
AceLocale.appnames[app] = application
end
if locale ~= gameLocale and not isDefault then
return nil -- nop, we don't need these translations
end
registering = app -- remember globally for writeproxy and writedefaultproxy
if isDefault then
return writedefaultproxy
end
return writeproxy
end
--- Returns localizations for the current locale (or default locale if translations are missing).
-- Errors if nothing is registered (spank developer, not just a missing translation)
-- @param application Unique name of addon / module
-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
-- @return The locale table for the current language.
function AceLocale:GetLocale(application, silent)
if not silent and not AceLocale.apps[application] then
error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
end
return AceLocale.apps[application]
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceLocale-3.0.lua"/>
</Ui>
@@ -0,0 +1,286 @@
--- **AceSerializer-3.0** can serialize any variable (except functions or userdata) into a string format,
-- that can be send over the addon comm channel. AceSerializer was designed to keep all data intact, especially
-- very large numbers or floating point numbers, and table structures. The only caveat currently is, that multiple
-- references to the same table will be send individually.
--
-- **AceSerializer-3.0** can be embeded into your addon, either explicitly by calling AceSerializer:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceSerializer itself.\\
-- It is recommended to embed AceSerializer, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceSerializer.
-- @class file
-- @name AceSerializer-3.0
-- @release $Id: AceSerializer-3.0.lua 1135 2015-09-19 20:39:16Z nevcairiel $
local MAJOR,MINOR = "AceSerializer-3.0", 5
local AceSerializer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceSerializer then return end
-- Lua APIs
local strbyte, strchar, gsub, gfind, format = string.byte, string.char, string.gsub, string.gfind, string.format
local assert, error, pcall = assert, error, pcall
local type, tostring, tonumber = type, tostring, tonumber
local pairs, select, frexp = pairs, select, math.frexp
local tconcat, tgetn = table.concat, table.getn
-- quick copies of string representations of wonky numbers
local inf = 1/0
local serNaN -- can't do this in 4.3, see ace3 ticket 268
local serInf, serInfMac = "1.#INF", "inf"
local serNegInf, serNegInfMac = "-1.#INF", "-inf"
-- Serialization functions
local function SerializeStringHelper(ch) -- Used by SerializeValue for strings
-- We use \126 ("~") as an escape character for all nonprints plus a few more
local n = strbyte(ch)
if n==30 then -- v3 / ticket 115: catch a nonprint that ends up being "~^" when encoded... DOH
return "\126\122"
elseif n<=32 then -- nonprint + space
return "\126"..strchar(n+64)
elseif n==94 then -- value separator
return "\126\125"
elseif n==126 then -- our own escape character
return "\126\124"
elseif n==127 then -- nonprint (DEL)
return "\126\123"
else
assert(false) -- can't be reached if caller uses a sane regex
end
end
local function SerializeValue(v, res, nres)
-- We use "^" as a value separator, followed by one byte for type indicator
local t=type(v)
if t=="string" then -- ^S = string (escaped to remove nonprints, "^"s, etc)
res[nres+1] = "^S"
res[nres+2] = gsub(v,"[%c \94\126\127]", SerializeStringHelper)
nres=nres+2
elseif t=="number" then -- ^N = number (just tostring()ed) or ^F (float components)
local str = tostring(v)
if tonumber(str)==v --[[not in 4.3 or str==serNaN]] then
-- translates just fine, transmit as-is
res[nres+1] = "^N"
res[nres+2] = str
nres=nres+2
elseif v == inf or v == -inf then
res[nres+1] = "^N"
res[nres+2] = v == inf and serInf or serNegInf
nres=nres+2
else
local m,e = frexp(v)
res[nres+1] = "^F"
res[nres+2] = format("%.0f",m*2^53) -- force mantissa to become integer (it's originally 0.5--0.9999)
res[nres+3] = "^f"
res[nres+4] = tostring(e-53) -- adjust exponent to counteract mantissa manipulation
nres=nres+4
end
elseif t=="table" then -- ^T...^t = table (list of key,value pairs)
nres=nres+1
res[nres] = "^T"
for k,v in pairs(v) do
nres = SerializeValue(k, res, nres)
nres = SerializeValue(v, res, nres)
end
nres=nres+1
res[nres] = "^t"
elseif t=="boolean" then -- ^B = true, ^b = false
nres=nres+1
if v then
res[nres] = "^B" -- true
else
res[nres] = "^b" -- false
end
elseif t=="nil" then -- ^Z = nil (zero, "N" was taken :P)
nres=nres+1
res[nres] = "^Z"
else
error(MAJOR..": Cannot serialize a value of type '"..t.."'") -- can't produce error on right level, this is wildly recursive
end
return nres
end
local serializeTbl = { "^1" } -- "^1" = Hi, I'm data serialized by AceSerializer protocol rev 1
--- Serialize the data passed into the function.
-- Takes a list of values (strings, numbers, booleans, nils, tables)
-- and returns it in serialized form (a string).\\
-- May throw errors on invalid data types.
-- @param ... List of values to serialize
-- @return The data in its serialized form (string)
function AceSerializer:Serialize(...)
local nres = 1
for i = 1,tgetn(arg) do
local v = arg[i]
nres = SerializeValue(v, serializeTbl, nres)
end
serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data
return tconcat(serializeTbl, "", 1, nres+1)
end
-- Deserialization functions
local function DeserializeStringHelper(escape)
if escape<"~\122" then
return strchar(strbyte(escape,2,2)-64)
elseif escape=="~\122" then -- v3 / ticket 115: special case encode since 30+64=94 ("^") - OOPS.
return "\030"
elseif escape=="~\123" then
return "\127"
elseif escape=="~\124" then
return "\126"
elseif escape=="~\125" then
return "\94"
end
error("DeserializeStringHelper got called for '"..escape.."'?!?") -- can't be reached unless regex is screwed up
end
local function DeserializeNumberHelper(number)
--[[ not in 4.3 if number == serNaN then
return 0/0
else]]if number == serNegInf or number == serNegInfMac then
return -inf
elseif number == serInf or number == serInfMac then
return inf
else
return tonumber(number)
end
end
-- DeserializeValue: worker function for :Deserialize()
-- It works in two modes:
-- Main (top-level) mode: Deserialize a list of values and return them all
-- Recursive (table) mode: Deserialize only a single value (_may_ of course be another table with lots of subvalues in it)
--
-- The function _always_ works recursively due to having to build a list of values to return
--
-- Callers are expected to pcall(DeserializeValue) to trap errors
local function DeserializeValue(iter,single,ctl,data)
if not single then
ctl,data = iter()
end
if not ctl then
error("Supplied data misses AceSerializer terminator ('^^')")
end
if ctl=="^^" then
-- ignore extraneous data
return
end
local res
if ctl=="^S" then
res = gsub(data, "~.", DeserializeStringHelper)
elseif ctl=="^N" then
res = DeserializeNumberHelper(data)
if not res then
error("Invalid serialized number: '"..tostring(data).."'")
end
elseif ctl=="^F" then -- ^F<mantissa>^f<exponent>
local ctl2,e = iter()
if ctl2~="^f" then
error("Invalid serialized floating-point number, expected '^f', not '"..tostring(ctl2).."'")
end
local m=tonumber(data)
e=tonumber(e)
if not (m and e) then
error("Invalid serialized floating-point number, expected mantissa and exponent, got '"..tostring(m).."' and '"..tostring(e).."'")
end
res = m*(2^e)
elseif ctl=="^B" then -- yeah yeah ignore data portion
res = true
elseif ctl=="^b" then -- yeah yeah ignore data portion
res = false
elseif ctl=="^Z" then -- yeah yeah ignore data portion
res = nil
elseif ctl=="^T" then
-- ignore ^T's data, future extensibility?
res = {}
local k,v
while true do
ctl,data = iter()
if ctl=="^t" then break end -- ignore ^t's data
k = DeserializeValue(iter,true,ctl,data)
if k==nil then
error("Invalid AceSerializer table format (no table end marker)")
end
ctl,data = iter()
v = DeserializeValue(iter,true,ctl,data)
if v==nil then
error("Invalid AceSerializer table format (no table end marker)")
end
res[k]=v
end
else
error("Invalid AceSerializer control code '"..ctl.."'")
end
if not single then
return res,DeserializeValue(iter)
else
return res
end
end
--- Deserializes the data into its original values.
-- Accepts serialized data, ignoring all control characters and whitespace.
-- @param str The serialized data (from :Serialize)
-- @return true followed by a list of values, OR false followed by an error message
function AceSerializer:Deserialize(str)
str = gsub(str, "[%c ]", "") -- ignore all control characters; nice for embedding in email and stuff
local iter = gfind(str, "(^.)([^^]*)") -- Any ^x followed by string of non-^
local ctl,data = iter()
if not ctl or ctl~="^1" then
-- we purposefully ignore the data portion of the start code, it can be used as an extension mechanism
return false, "Supplied data is not AceSerializer data (rev 1)"
end
return pcall(DeserializeValue, iter)
end
----------------------------------------
-- Base library stuff
----------------------------------------
AceSerializer.internals = { -- for test scripts
SerializeValue = SerializeValue,
SerializeStringHelper = SerializeStringHelper,
}
local mixins = {
"Serialize",
"Deserialize",
}
AceSerializer.embeds = AceSerializer.embeds or {}
function AceSerializer:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
-- Update embeds
for target, v in pairs(AceSerializer.embeds) do
AceSerializer:Embed(target)
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceSerializer-3.0.lua"/>
</Ui>
@@ -0,0 +1,474 @@
--- **AceTimer-3.0** provides a central facility for registering timers.
-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled
-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
-- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change
-- in the future, but for now it seemed like a good compromise in efficiency and accuracy.
--
-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
-- need to cancel or reschedule the timer you just registered.
--
-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceTimer itself.\\
-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceTimer.
-- @class file
-- @name AceTimer-3.0
-- @release $Id: AceTimer-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
--[[
Basic assumptions:
* In a typical system, we do more re-scheduling per second than there are timer pulses per second
* Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10)
This implementation:
CON: The smallest timer interval is constrained by HZ (currently 1/10s).
PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds
PRO: In lag bursts, the system simly skips missed timer intervals to decrease load
CON: Algorithms depending on a timer firing "N times per minute" will fail
PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket.
CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease.
Major assumptions upheld:
- ALLOWS scheduling multiple timers with the same funcref/method
- ALLOWS scheduling more timers during OnUpdate processing
- ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing
]]
local MAJOR, MINOR = "AceTimer-3.0", 6
local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceTimer then return end -- No upgrade needed
AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member)
-- Linked list gets around ACE-88 and ACE-90.
AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...}
AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
-- Lua APIs
local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local select, pairs, type, next, tostring = select, pairs, type, next, tostring
local floor, max, min = math.floor, math.max, math.min
local tconcat = table.concat
-- WoW APIs
local GetTime = GetTime
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: DEFAULT_CHAT_FRAME, geterrorhandler
-- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes.
local timerCache = nil
--[[
Timers will not be fired more often than HZ-1 times per second.
Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade.
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local HZ = 11
--[[
Prime for good distribution
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local BUCKETS = 131
local hash = AceTimer.hash
for i=1,BUCKETS do
hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
end
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, function(err) return geterrorhandler()(err) end)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = gsub(code, "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {
__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end
})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[getn(arg)](func, unpack(arg))
end
local lastint = floor(GetTime() * HZ)
-- --------------------------------------------------------------------
-- OnUpdate handler
--
-- traverse buckets, always chasing "now", and fire timers that have expired
local function OnUpdate()
local now = GetTime()
local nowint = floor(now * HZ)
-- Have we passed into a new hash bucket?
if nowint == lastint then return end
local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
-- Pass through each bucket at most once
-- Happens on e.g. instance loads, but COULD happen on high local load situations also
for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration
local curbucket = (math.mod(curint, BUCKETS))+1
-- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
local nexttimer = hash[curbucket]
hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
while nexttimer do
local timer = nexttimer
nexttimer = timer.next
local when = timer.when
if when < soon then
-- Call the timer func, either as a method on given object, or a straight function ref
local callback = timer.callback
if type(callback) == "string" then
safecall(timer.object[callback], timer.object, timer.arg)
elseif callback then
safecall(callback, timer.arg)
else
-- probably nilled out by CancelTimer
timer.delay = nil -- don't reschedule it
end
local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
if not delay then
-- single-shot timer (or cancelled)
AceTimer.selfs[timer.object][tostring(timer)] = nil
timerCache = timer
else
-- repeating timer
local newtime = when + delay
if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
newtime = now + delay
end
timer.when = newtime
-- add next timer execution to the correct bucket
local bucket = (math.mod(floor(newtime * HZ), BUCKETS)) + 1
timer.next = hash[bucket]
hash[bucket] = timer
end
else -- if when>=soon
-- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
timer.next = hash[curbucket]
hash[curbucket] = timer
end -- if when<soon ... else
end -- while nexttimer do
end -- for curint=lastint,nowint
lastint = nowint
end
-- ---------------------------------------------------------------------
-- Reg( callback, delay, arg, repeating )
--
-- callback( function or string ) - direct function ref or method name in our object for the callback
-- delay(int) - delay for the timer
-- arg(variant) - any argument to be passed to the callback function
-- repeating(boolean) - repeating timer, or oneshot
--
-- returns the handle of the timer for later processing (canceling etc)
local function Reg(self, callback, delay, arg, repeating)
if type(callback) ~= "string" and type(callback) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3)
end
if type(callback) == "string" then
if type(self)~="table" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3)
end
if type(self[callback]) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3)
end
end
if delay < (1 / (HZ - 1)) then
delay = 1 / (HZ - 1)
end
-- Create and stuff timer in the correct hash bucket
local now = GetTime()
local timer = timerCache or {} -- Get new timer object (from cache if available)
timerCache = nil
timer.object = self
timer.callback = callback
timer.delay = (repeating and delay)
timer.arg = arg
timer.when = now + delay
local bucket = (math.mod(floor((now+delay)*HZ), BUCKETS)) + 1
timer.next = hash[bucket]
hash[bucket] = timer
-- Insert timer in our self->handle->timer registry
local handle = tostring(timer)
local selftimers = AceTimer.selfs[self]
if not selftimers then
selftimers = {}
AceTimer.selfs[self] = selftimers
end
selftimers[handle] = timer
selftimers.__ops = (selftimers.__ops or 0) + 1
return handle
end
--- Schedule a new one-shot timer.
-- The timer will fire once in `delay` seconds, unless canceled before.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self:ScheduleTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- print("5 seconds passed")
-- end
function AceTimer:ScheduleTimer(callback, delay, arg)
return Reg(self, callback, delay, arg)
end
--- Schedule a repeating timer.
-- The timer will fire every `delay` seconds, until canceled.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self.timerCount = 0
-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- self.timerCount = self.timerCount + 1
-- print(("%d seconds passed"):format(5 * self.timerCount))
-- -- run 30 seconds in total
-- if self.timerCount == 6 then
-- self:CancelTimer(self.testTimer)
-- end
-- end
function AceTimer:ScheduleRepeatingTimer(callback, delay, arg)
return Reg(self, callback, delay, arg, true)
end
--- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer`
-- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid
-- and the timer has not fired yet or was canceled before.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled)
-- @return True if the timer was successfully cancelled.
function AceTimer:CancelTimer(handle, silent)
if not handle then return end -- nil handle -> bail out without erroring
if type(handle) ~= "string" then
error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if silent then
if timer then
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
-- The timer object is removed in the OnUpdate loop
end
return not not timer -- might return "true" even if we double-cancel. we'll live.
else
if not timer then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered")
return false
end
if not timer.callback then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired")
return false
end
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
return true
end
end
--- Cancels all timers registered to the current addon object ('self')
function AceTimer:CancelAllTimers()
if not(type(self) == "string" or type(self) == "table") then
error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2)
end
if self == AceTimer then
error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
end
local selftimers = AceTimer.selfs[self]
if selftimers then
for handle,v in pairs(selftimers) do
if type(v) == "table" then -- avoid __ops, etc
AceTimer.CancelTimer(self, handle, true)
end
end
end
end
--- Returns the time left for a timer with the given handle, registered by the current addon object ('self').
-- This function will raise a warning when the handle is invalid, but not stop execution.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @return The time left on the timer, or false if the handle is invalid.
function AceTimer:TimeLeft(handle)
if not handle then return end
if type(handle) ~= "string" then
error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if not timer then
geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered")
return false
end
return timer.when - GetTime()
end
-- ---------------------------------------------------------------------
-- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step
-- and clean it out - otherwise the table indices can grow indefinitely
-- if an addon starts and stops a lot of timers. AceBucket does this!
--
-- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua
local lastCleaned = nil
local function OnEvent()
if event~="PLAYER_REGEN_ENABLED" then
return
end
-- Get the next 'self' to process
local selfs = AceTimer.selfs
local self = next(selfs, lastCleaned)
if not self then
self = next(selfs)
end
lastCleaned = self
if not self then -- should only happen if .selfs[] is empty
return
end
-- Time to clean it out?
local list = selfs[self]
if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (worst case!). For one 'self'.
return
end
-- Create a new table and copy all members over
local newlist = {}
local n=0
for k,v in pairs(list) do
newlist[k] = v
if type(v)=="table" and v.callback then -- if the timer is actually live: count it
n=n+1
end
end
newlist.__ops = 0 -- Reset operation count
-- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not.
if n>BUCKETS then
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?")
end
selfs[self] = newlist
end
-- ---------------------------------------------------------------------
-- Embed handling
AceTimer.embeds = AceTimer.embeds or {}
local mixins = {
"ScheduleTimer", "ScheduleRepeatingTimer",
"CancelTimer", "CancelAllTimers",
"TimeLeft"
}
function AceTimer:Embed(target)
AceTimer.embeds[target] = true
for _,v in pairs(mixins) do
target[v] = AceTimer[v]
end
return target
end
-- AceTimer:OnEmbedDisable( target )
-- target (object) - target object that AceTimer is embedded in.
--
-- cancel all timers registered for the object
function AceTimer:OnEmbedDisable( target )
target:CancelAllTimers()
end
for addon in pairs(AceTimer.embeds) do
AceTimer:Embed(addon)
end
-- ---------------------------------------------------------------------
-- Debug tools (expose copies of internals to test suites)
AceTimer.debug = AceTimer.debug or {}
AceTimer.debug.HZ = HZ
AceTimer.debug.BUCKETS = BUCKETS
-- ---------------------------------------------------------------------
-- Finishing touchups
AceTimer.frame:SetScript("OnUpdate", OnUpdate)
AceTimer.frame:SetScript("OnEvent", OnEvent)
AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
-- In theory, we could hide&show the frame based on there being timers or not.
-- However, this job is fairly expensive, and the chance that there will
-- actually be zero timers running is diminuitive to say the least.
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceTimer-3.0.lua"/>
</Ui>
@@ -0,0 +1,234 @@
--[[ $Id: CallbackHandler-1.0.lua 18 2014-10-16 02:52:20Z mikk $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 6
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs
local tconcat = table.concat
local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local method, ARGS
local function call() method(ARGS) end
local function dispatch(handlers, ...)
local index
index, method = next(handlers)
if not method then return end
local OLD_ARGS = ARGS
ARGS = unpack(arg)
repeat
xpcall(call, function(err) return geterrorhandler()(err) end)
index, method = next(handlers, index)
until not method
ARGS = OLD_ARGS
end
return dispatch
]]
local ARGS, OLD_ARGS = {}, {}
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
code = gsub(gsub(code, "OLD_ARGS", tconcat(OLD_ARGS, ", ")), "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName)
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
Dispatchers[getn(arg) + 1](events[eventname], eventname, unpack(arg))
registry.recurse = oldrecurse
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for eventname,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for self,func in pairs(callbacks) do
events[eventname][self] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, eventname)
first = nil
end
end
end
registry.insertQueue = nil
end
end
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
method = method or eventname
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
local regfunc
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
regfunc = function(...) self[method](self,arg1,unpack(arg)) end
else
regfunc = function(...) self[method](self,unpack(arg)) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
end
if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
regfunc = function(...) method(arg1,unpack(arg)) end
else
regfunc = method
end
end
if events[eventname][self] or registry.recurse<1 then
-- if registry.recurse<1 then
-- we're overwriting an existing entry, or not currently recursing. just set it.
events[eventname][self] = regfunc
-- fire OnUsed callback?
if registry.OnUsed and first then
registry.OnUsed(registry, target, eventname)
end
else
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
registry.insertQueue[eventname][self] = regfunc
end
end
-- Unregister a callback
target[UnregisterName] = function(self, eventname)
if not self or self==target then
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
end
if type(eventname) ~= "string" then
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
end
if rawget(events, eventname) and events[eventname][self] then
events[eventname][self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(events[eventname]) then
registry.OnUnused(registry, target, eventname)
end
end
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
registry.insertQueue[eventname][self] = nil
end
end
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
if UnregisterAllName then
target[UnregisterAllName] = function(...)
if getn(arg)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if getn(arg)==1 and arg1==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
for i=1,getn(arg) do
local self = arg[i]
if registry.insertQueue then
for eventname, callbacks in pairs(registry.insertQueue) do
if callbacks[self] then
callbacks[self] = nil
end
end
end
for eventname, callbacks in pairs(events) do
if callbacks[self] then
callbacks[self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(callbacks) then
registry.OnUnused(registry, target, eventname)
end
end
end
end
end
end
return registry
end
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
-- try to upgrade old implicit embeds since the system is selfcontained and
-- relies on closures to work.
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="CallbackHandler-1.0.lua"/>
</Ui>
@@ -0,0 +1,819 @@
-- LibAnim by Hydra
local Version = 2.01
if (_LibAnim and _LibAnim >= Version) then
return
end
local _G = getfenv()
local cos = cos
local sin = sin
local pairs = pairs
local floor = floor
local getn = getn
local tinsert = tinsert
local tremove = tremove
local strlower = strlower
local Updater = CreateFrame("StatusBar")
local Texture = Updater:CreateTexture()
local Text = Updater:CreateFontString()
local AnimTypes = {}
local UpdateFuncs = {}
local Callbacks = {["onplay"] = {}, ["onpause"] = {}, ["onresume"] = {}, ["onstop"] = {}, ["onreset"] = {}, ["onfinished"] = {}}
-- Update all current animations
local AnimationOnUpdate = function(self, elapsed)
for i = 1, getn(self) do
if self[i] then -- Double check the the index still exists, due to pauses/stops removing them on the fly
self[i]:Update(elapsed, i)
end
end
if (getn(self) == 0) then
self:SetScript("OnUpdate", nil)
end
end
local StartUpdating = function(anim)
tinsert(Updater, anim)
if (not Updater:GetScript("OnUpdate")) then
Updater:SetScript("OnUpdate", AnimationOnUpdate)
end
end
local GetColor = function(p, r1, g1, b1, r2, g2, b2)
return r1 + (r2 - r1) * p, g1 + (g2 - g1) * p, b1 + (b2 - b1) * p
end
local Set = {
["backdrop"] = Updater.SetBackdropColor,
["border"] = Updater.SetBackdropBorderColor,
["statusbar"] = Updater.SetStatusBarColor,
["text"] = Text.SetTextColor,
["texture"] = Texture.SetTexture,
["vertex"] = Texture.SetVertexColor,
}
local Get = {
["backdrop"] = Updater.GetBackdropColor,
["border"] = Updater.GetBackdropBorderColor,
["statusbar"] = Updater.GetStatusBarColor,
["text"] = Text.GetTextColor,
["texture"] = Texture.GetVertexColor,
["vertex"] = Texture.GetVertexColor,
}
local Smoothing = {
["none"] = function(t, b, c, d)
return c * t / d + b
end,
["in"] = function(t, b, c, d)
t = t / d
return c * t * t + b
end,
["out"] = function(t, b, c, d)
t = t / d
return -c * t * (t - 2) + b
end,
["inout"] = function(t, b, c, d)
t = t / (d / 2)
if (t < 1) then
return c / 2 * t * t + b
end
t = t - 1
return -c / 2 * (t * (t - 2) - 1) + b
end,
["bounce"] = function(t, b, c, d)
t = t / d
if (t < (1 / 2.75)) then
return c * (7.5625 * t * t) + b
elseif (t < (2 / 2.75)) then
t = t - (1.5 / 2.75)
return c * (7.5625 * t * t + 0.75) + b
elseif (t < (2.5 / 2.75)) then
t = t - (2.25 / 2.75)
return c * (7.5625 * t * t + 0.9375) + b
else
t = t - (2.625 / 2.75)
return c * (7.5625 * (t) * t + 0.984375) + b
end
end,
["elastic"] = function(t, b, c, d)
local s, p, a = 1.70158, d * .3, c;
if t == 0 then
return b
end
t = t / d
if t == 1 then
return b + c
end
if a < math.abs(c) then
a = c
s = p / 4
else
s = p / (2 * math.pi) * math.asin(c / a)
end
return a * math.pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b
end
}
local AnimMethods = {
All = {
Play = function(self)
if (not self.Paused) then
AnimTypes[self.Type](self)
self:Callback("OnPlay")
else
StartUpdating(self)
self:Callback("OnResume")
end
self.Playing = true
self.Paused = false
self.Stopped = false
end,
IsPlaying = function(self)
return self.Playing
end,
Pause = function(self)
for i = 1, getn(Updater) do
if (Updater[i] == self) then
tremove(Updater, i)
break
end
end
self.Playing = false
self.Paused = true
self.Stopped = false
self:Callback("OnPause")
end,
IsPaused = function(self)
return self.Paused
end,
Stop = function(self, reset)
for i = 1, getn(Updater) do
if (Updater[i] == self) then
tremove(Updater, i)
break
end
end
self.Playing = false
self.Paused = false
self.Stopped = true
if reset then
self:Reset()
self:Callback("OnReset")
else
self:Callback("OnStop")
end
end,
IsStopped = function(self)
return self.Stopped
end,
SetSmoothing = function(self, smoothType)
smoothType = strlower(smoothType)
self.Smoothing = Smoothing[smoothType] and smoothType or "none"
end,
GetSmoothing = function(self)
return self.Smoothing
end,
SetDuration = function(self, duration)
self.Duration = duration or 0
end,
GetDuration = function(self)
return self.Duration
end,
GetProgressByTimer = function(self)
return self.Timer
end,
SetOrder = function(self, order)
self.Order = order or 1
if (order > self.Group.MaxOrder) then
self.Group.MaxOrder = order
end
end,
GetOrder = function(self)
return self.Order
end,
GetParent = function(self)
return self.Parent
end,
SetScript = function(self, handler, func)
handler = strlower(handler)
if (not Callbacks[handler]) then
return
end
Callbacks[handler][self] = func
end,
GetScript = function(self, handler)
handler = strlower(handler)
if (Callbacks[handler] and Callbacks[handler][self]) then
return Callbacks[handler][self]
end
end,
Callback = function(self, handler)
handler = strlower(handler)
if Callbacks[handler][self] then
Callbacks[handler][self](self)
end
end,
},
move = {
SetOffset = function(self, x, y)
self.XSetting = x or 0
self.YSetting = y or 0
end,
GetOffset = function(self)
return self.XSetting, self.YSetting
end,
SetRounded = function(self, flag)
self.IsRounded = flag
end,
GetRounded = function(self)
return self.IsRounded
end,
GetProgress = function(self)
return self.XOffset, self.YOffset
end,
Reset = function(self)
self.Parent:ClearAllPoints()
self.Parent:SetPoint(self.A1, self.P, self.A2, self.StartX, self.StartY)
end,
},
fade = {
SetChange = function(self, alpha)
self.EndAlphaSetting = alpha or 0
end,
GetChange = function(self)
return self.EndAlphaSetting
end,
GetProgress = function(self)
return self.AlphaOffset
end,
Reset = function(self)
self.Parent:SetAlpha(self.StartAlpha)
end,
},
height = {
SetChange = function(self, height)
self.EndHeightSetting = height or 0
end,
GetChange = function(self)
return self.EndHeightSetting
end,
GetProgress = function(self)
return self.HeightOffset
end,
Reset = function(self)
self.Parent:SetHeight(self.StartHeight)
end,
},
width = {
SetChange = function(self, width)
self.EndWidthSetting = width or 0
end,
GetChange = function(self)
return self.EndWidthSetting
end,
GetProgress = function(self)
return self.WidthOffset
end,
Reset = function(self)
self.Parent:SetWidth(self.StartWidth)
end,
},
color = {
SetChange = function(self, r, g, b)
self.EndRSetting = r or 1
self.EndGSetting = g or 1
self.EndBSetting = b or 1
end,
GetChange = function(self)
return self.EndRSetting, self.EndGSetting, self.EndBSetting
end,
SetColorType = function(self, type)
type = strlower(type)
self.ColorType = Set[type] and type or "border"
end,
GetColorType = function(self)
return self.ColorType
end,
GetProgress = function(self)
return self.ColorOffset
end,
Reset = function(self)
Set[self.ColorType](self.Parent, self.StartR, self.StartG, self.StartB)
end,
},
progress = {
SetChange = function(self, value)
self.EndValueSetting = value or 0
end,
GetChange = function(self)
return self.EndValueSetting
end,
GetProgress = function(self)
return self.ValueOffset
end,
Reset = function(self)
self.Parent:SetValue(self.StartValue)
end,
},
number = {
SetChange = function(self, value)
self.EndNumberSetting = value or 0
end,
GetChange = function(self)
return self.EndNumberSetting
end,
SetPrefix = function(self, text)
self.Prefix = text or ""
end,
GetPrefix = function(self)
return self.Prefix
end,
SetPostfix = function(self, text)
self.Postfix = text or ""
end,
GetPostfix = function(self)
return self.Postfix
end,
GetProgress = function(self)
return self.NumberOffset
end,
Reset = function(self)
self.Parent:SetText(self.StartNumer)
end,
},
}
local GroupMethods = {
Play = function(self)
-- Play!
for i = 1, getn(self.Animations) do
if (self.Animations[i].Order == self.Order) then
self.Animations[i]:Play()
end
end
self.Playing = true
self.Paused = false
self.Stopped = false
end,
IsPlaying = function(self)
return self.Playing
end,
Pause = function(self)
-- Only pause current order
for i = 1, getn(self.Animations) do
if (self.Animations[i].Order == self.Order) then
self.Animations[i]:Pause()
end
end
self.Playing = false
self.Paused = true
self.Stopped = false
end,
IsPaused = function(self)
return self.Paused
end,
Stop = function(self)
for i = 1, getn(self.Animations) do
self.Animations[i]:Stop()
end
self.Playing = false
self.Paused = false
self.Stopped = true
end,
IsStopped = function(self)
return self.Stopped
end,
SetLooping = function(self, shouldLoop)
self.Looping = shouldLoop
end,
GetLooping = function(self)
return self.Looping
end,
GetParent = function(self)
return self.Parent
end,
CheckOrder = function(self)
-- Check if we're done all animations at the current order, then proceed to the next order.
local NumAtOrder = 0
local NumDoneAtOrder = 0
for i = 1, getn(self.Animations) do
if (self.Animations[i].Order == self.Order) then
NumAtOrder = NumAtOrder + 1
if (not self.Animations[i].Playing) then
NumDoneAtOrder = NumDoneAtOrder + 1
end
end
end
-- All the animations at x order finished, go to next order
if (NumAtOrder == NumDoneAtOrder) then
self.Order = self.Order + 1
-- We exceeded max order, reset to 1 and bail the function, or restart if we're looping
if (self.Order > self.MaxOrder) then
self.Order = 1
if (self.Stopped or not self.Looping) then
self.Playing = false
return
end
end
-- Play!
for i = 1, getn(self.Animations) do
if (self.Animations[i].Order == self.Order) then
self.Animations[i]:Play()
end
end
end
end,
CreateAnimation = function(self, type)
type = strlower(type)
if (not AnimTypes[type]) then
return
end
local Animation = {}
-- General methods
for key, func in pairs(AnimMethods.All) do
Animation[key] = func
end
-- Animation specific methods
if AnimMethods[type] then
for key, func in pairs(AnimMethods[type]) do
Animation[key] = func
end
end
-- Set some attributes and defaults
Animation.Paused = false
Animation.Playing = false
Animation.Stopped = false
Animation.Looping = false
Animation.Type = type
Animation.Group = self
Animation.Parent = self.Parent
Animation.Order = 1
Animation.Duration = 0.3
Animation.Smoothing = "none"
Animation.Update = UpdateFuncs[type]
tinsert(self.Animations, Animation)
return Animation
end,
}
CreateAnimationGroup = function(parent)
local Group = {Animations = {}}
-- Add methods to the group
for key, func in pairs(GroupMethods) do
Group[key] = func
end
Group.Parent = parent
Group.Playing = false
Group.Paused = false
Group.Stopped = false
Group.Order = 1
Group.MaxOrder = 1
return Group
end
-- Movement
UpdateFuncs["move"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
if self.IsRounded then
self.ModTimer = Smoothing[self.Smoothing](self.Timer, 0, self.Duration, self.Duration)
self.XOffset = self.StartX - (-1) * (self.XChange * (1 - cos(90 * self.ModTimer / self.Duration)))
self.YOffset = self.StartY + self.YChange * sin(90 * self.ModTimer / self.Duration)
else
self.XOffset = Smoothing[self.Smoothing](self.Timer, self.StartX, self.XChange, self.Duration)
self.YOffset = Smoothing[self.Smoothing](self.Timer, self.StartY, self.YChange, self.Duration)
end
self.Parent:SetPoint(self.A1, self.P, self.A2, (self.EndX ~= 0 and self.XOffset or self.StartX), (self.EndY ~= 0 and self.YOffset or self.StartY))
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetPoint(self.A1, self.P, self.A2, self.EndX, self.EndY)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["move"] = function(self)
if self:IsPlaying() then
return
end
local A1, P, A2, X, Y = self.Parent:GetPoint()
self.Timer = 0
self.A1 = A1
self.P = P
self.A2 = A2
self.StartX = X
self.EndX = X + self.XSetting or 0
self.StartY = Y
self.EndY = Y + self.YSetting or 0
self.XChange = self.EndX - self.StartX
self.YChange = self.EndY - self.StartY
if self.IsRounded then
if (self.XChange == 0 or self.YChange == 0) then -- Double check if we're valid to be rounded
self.IsRounded = false
else
self.ModTimer = 0
end
end
StartUpdating(self)
end
-- Fade
UpdateFuncs["fade"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.AlphaOffset = Smoothing[self.Smoothing](self.Timer, self.StartAlpha, self.Change, self.Duration)
self.Parent:SetAlpha(self.AlphaOffset)
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetAlpha(self.EndAlpha)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["fade"] = function(self)
if self:IsPlaying() then
return
end
self.Timer = 0
self.StartAlpha = self.Parent:GetAlpha() or 1
self.EndAlpha = self.EndAlphaSetting or 0
self.Change = self.EndAlpha - self.StartAlpha
StartUpdating(self)
end
-- Height
UpdateFuncs["height"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.HeightOffset = Smoothing[self.Smoothing](self.Timer, self.StartHeight, self.HeightChange, self.Duration)
self.Parent:SetHeight(self.HeightOffset)
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetHeight(self.EndHeight)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["height"] = function(self)
if self:IsPlaying() then
return
end
self.Timer = 0
self.StartHeight = self.Parent:GetHeight() or 0
self.EndHeight = self.EndHeightSetting or 0
self.HeightChange = self.EndHeight - self.StartHeight
StartUpdating(self)
end
-- Width
UpdateFuncs["width"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.WidthOffset = Smoothing[self.Smoothing](self.Timer, self.StartWidth, self.WidthChange, self.Duration)
self.Parent:SetWidth(self.WidthOffset)
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetWidth(self.EndWidth)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["width"] = function(self)
if self:IsPlaying() then
return
end
self.Timer = 0
self.StartWidth = self.Parent:GetWidth() or 0
self.EndWidth = self.EndWidthSetting or 0
self.WidthChange = self.EndWidth - self.StartWidth
StartUpdating(self)
end
-- Color
UpdateFuncs["color"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.ColorOffset = Smoothing[self.Smoothing](self.Timer, 0, self.Duration, self.Duration)
Set[self.ColorType](self.Parent, GetColor(self.Timer / self.Duration, self.StartR, self.StartG, self.StartB, self.EndR, self.EndG, self.EndB))
if (self.Timer >= self.Duration) then
tremove(Updater, i)
Set[self.ColorType](self.Parent, self.EndR, self.EndG, self.EndB)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["color"] = function(self)
self.Timer = 0
self.ColorType = self.ColorType or "backdrop"
self.StartR, self.StartG, self.StartB = Get[self.ColorType](self.Parent)
self.EndR = self.EndRSetting or 1
self.EndG = self.EndGSetting or 1
self.EndB = self.EndBSetting or 1
StartUpdating(self)
end
-- Progress
UpdateFuncs["progress"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.ValueOffset = Smoothing[self.Smoothing](self.Timer, self.StartValue, self.ProgressChange, self.Duration)
self.Parent:SetValue(self.ValueOffset)
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetValue(self.EndValue)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["progress"] = function(self)
self.Timer = 0
self.StartValue = self.Parent:GetValue() or 0
self.EndValue = self.EndValueSetting or 0
self.ProgressChange = self.EndValue - self.StartValue
StartUpdating(self)
end
-- Sleep
UpdateFuncs["sleep"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["sleep"] = function(self)
self.Timer = 0
StartUpdating(self)
end
-- Number
UpdateFuncs["number"] = function(self, elapsed, i)
self.Timer = self.Timer + elapsed
self.NumberOffset = Smoothing[self.Smoothing](self.Timer, self.StartNumber, self.NumberChange, self.Duration)
self.Parent:SetText(self.Prefix..floor(self.NumberOffset)..self.Postfix)
if (self.Timer >= self.Duration) then
tremove(Updater, i)
self.Parent:SetText(self.Prefix..floor(self.EndNumber)..self.Postfix)
self.Playing = false
self:Callback("OnFinished")
self.Group:CheckOrder()
end
end
AnimTypes["number"] = function(self)
self.Timer = 0
self.StartNumber = tonumber(self.Parent:GetText()) or 0
self.EndNumber = self.EndNumberSetting or 0
self.NumberChange = self.EndNumberSetting - self.StartNumber
self.Prefix = self.Prefix or ""
self.Postfix = self.Postfix or ""
StartUpdating(self)
end
_G["_LibAnim"] = Version
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibAnim.lua"/>
</Ui>
@@ -0,0 +1,212 @@
--[[
Name: LibBase64-1.0
Author(s): ckknight (ckknight@gmail.com)
Website: http://www.wowace.com/projects/libbase64-1-0/
Description: A library to encode and decode Base64 strings
License: MIT
]]
local LibBase64 = LibStub:NewLibrary("LibBase64-1.0-ElvUI", 1)
if not LibBase64 then
return
end
local _chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
local byteToNum = {}
local numToChar = {}
for i = 1, #_chars do
numToChar[i - 1] = _chars:sub(i, i)
byteToNum[_chars:byte(i)] = i - 1
end
_chars = nil
local A_byte = ("A"):byte()
local Z_byte = ("Z"):byte()
local a_byte = ("a"):byte()
local z_byte = ("z"):byte()
local zero_byte = ("0"):byte()
local nine_byte = ("9"):byte()
local plus_byte = ("+"):byte()
local slash_byte = ("/"):byte()
local equals_byte = ("="):byte()
local whitespace = {
[(" "):byte()] = true,
[("\t"):byte()] = true,
[("\n"):byte()] = true,
[("\r"):byte()] = true,
}
local t = {}
--- Encode a normal bytestring into a Base64-encoded string
-- @param text a bytestring, can be binary data
-- @param maxLineLength This should be a multiple of 4, greater than 0 or nil. If non-nil, it will break up the output into lines no longer than the given number of characters. 76 is recommended.
-- @param lineEnding a string to end each line with. This is "\r\n" by default.
-- @usage LibBase64.Encode("Hello, how are you doing today?") == "SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw=="
-- @return a Base64-encoded string
function LibBase64:Encode(text, maxLineLength, lineEnding)
if type(text) ~= "string" then
error(("Bad argument #1 to `Encode'. Expected %q, got %q"):format("string", type(text)), 2)
end
if maxLineLength == nil then
-- do nothing
elseif type(maxLineLength) ~= "number" then
error(("Bad argument #2 to `Encode'. Expected %q or %q, got %q"):format("number", "nil", type(maxLineLength)), 2)
elseif (maxLineLength % 4) ~= 0 then
error(("Bad argument #2 to `Encode'. Expected a multiple of 4, got %s"):format(maxLineLength), 2)
elseif maxLineLength <= 0 then
error(("Bad argument #2 to `Encode'. Expected a number > 0, got %s"):format(maxLineLength), 2)
end
if lineEnding == nil then
lineEnding = "\r\n"
elseif type(lineEnding) ~= "string" then
error(("Bad argument #3 to `Encode'. Expected %q, got %q"):format("string", type(lineEnding)), 2)
end
local currentLength = 0
for i = 1, #text, 3 do
local a, b, c = text:byte(i, i+2)
local nilNum = 0
if not b then
nilNum = 2
b = 0
c = 0
elseif not c then
nilNum = 1
c = 0
end
local num = a * 2^16 + b * 2^8 + c
local d = num % 2^6
num = (num - d) / 2^6
local c = num % 2^6
num = (num - c) / 2^6
local b = num % 2^6
num = (num - b) / 2^6
local a = num % 2^6
t[#t+1] = numToChar[a]
t[#t+1] = numToChar[b]
t[#t+1] = (nilNum >= 2) and "=" or numToChar[c]
t[#t+1] = (nilNum >= 1) and "=" or numToChar[d]
currentLength = currentLength + 4
if maxLineLength and (currentLength % maxLineLength) == 0 then
t[#t+1] = lineEnding
end
end
local s = table.concat(t)
for i = 1, #t do
t[i] = nil
end
return s
end
local t2 = {}
--- Decode a Base64-encoded string into a bytestring
-- this will raise an error if the data passed in is not a Base64-encoded string
-- this will ignore whitespace, but not invalid characters
-- @param text a Base64-encoded string
-- @usage LibBase64.Encode("SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw==") == "Hello, how are you doing today?"
-- @return a bytestring
function LibBase64:Decode(text)
if type(text) ~= "string" then
error(("Bad argument #1 to `Decode'. Expected %q, got %q"):format("string", type(text)), 2)
end
for i = 1, #text do
local byte = text:byte(i)
if whitespace[byte] or byte == equals_byte then
-- do nothing
else
local num = byteToNum[byte]
if not num then
for i = 1, #t2 do
t2[k] = nil
end
error(("Bad argument #1 to `Decode'. Received an invalid char: %q"):format(text:sub(i, i)), 2)
end
t2[#t2+1] = num
end
end
for i = 1, #t2, 4 do
local a, b, c, d = t2[i], t2[i+1], t2[i+2], t2[i+3]
local nilNum = 0
if not c then
nilNum = 2
c = 0
d = 0
elseif not d then
nilNum = 1
d = 0
end
local num = a * 2^18 + b * 2^12 + c * 2^6 + d
local c = num % 2^8
num = (num - c) / 2^8
local b = num % 2^8
num = (num - b) / 2^8
local a = num % 2^8
t[#t+1] = string.char(a)
if nilNum < 2 then
t[#t+1] = string.char(b)
end
if nilNum < 1 then
t[#t+1] = string.char(c)
end
end
for i = 1, #t2 do
t2[i] = nil
end
local s = table.concat(t)
for i = 1, #t do
t[i] = nil
end
return s
end
function LibBase64:IsBase64(text)
if type(text) ~= "string" then
error(("Bad argument #1 to `IsBase64'. Expected %q, got %q"):format("string", type(text)), 2)
end
if #text % 4 ~= 0 then
return false
end
for i = 1, #text do
local byte = text:byte(i)
if whitespace[byte] or byte == equals_byte then
-- do nothing
else
local num = byteToNum[byte]
if not num then
return false
end
end
end
return true
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibBase64-1.0.lua"/>
</Ui>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibCompress.lua"/>
</Ui>
@@ -0,0 +1,90 @@
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
if not lib then return end
oldminor = oldminor or 0
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
if oldminor < 2 then
lib.domt = {
__metatable = "access denied",
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
}
end
if oldminor < 3 then
lib.domt.__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
end
end
if oldminor < 2 then
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
end
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end
if oldminor < 4 then
local next = pairs(attributestorage)
function lib:pairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return next, attributestorage[dataobj], nil
end
local ipairs_iter = ipairs(attributestorage)
function lib:ipairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
return ipairs_iter, attributestorage[dataobj], 0
end
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibDataBroker-1.1.lua"/>
</Ui>
@@ -0,0 +1,226 @@
local MAJOR, MINOR = "LibElvUIPlugin-1.0", 13
local lib, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
--Cache global variables
--Lua functions
local pairs, tonumber = pairs, tonumber
local format, strsplit = format, strsplit
--WoW API / Variables
local CreateFrame = CreateFrame;
local GetNumPartyMembers, GetNumRaidMembers = GetNumPartyMembers, GetNumRaidMembers
local GetAddOnMetadata = GetAddOnMetadata
local IsAddOnLoaded = IsAddOnLoaded
local SendAddonMessage = SendAddonMessage
--Global variables that we don't cache, list them here for the mikk's Find Globals script
-- GLOBALS: ElvUI
lib.plugins = {}
lib.index = 0
lib.prefix = "ElvUIPluginVC"
-- MULTI Language Support (Default Language: English)
local MSG_OUTDATED = "Your version of %s is out of date (latest is version %s). You can download the latest version from https://github.com/ElvUI-Vanilla/ElvUI/"
local HDR_CONFIG = "Plugins"
local HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - Plugins Loaded (|cff2BC226Green|r means you have current version, |cffFF0000Red|r means out of date)"
local INFO_BY = "by"
local INFO_VERSION = "Version:"
local INFO_NEW = "Newest:"
local LIBRARY = "Library"
if GetLocale() == "deDE" then -- German Translation
MSG_OUTDATED = "Deine Version von %s ist veraltet (akutelle Version ist %s). Du kannst die aktuelle Version von https://github.com/ElvUI-Vanilla/ElvUI/ herunterrladen."
HDR_CONFIG = "Plugins"
HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - Plugins geladen (|cff2BC226Grün|r bedeutet du hast die aktuelle Version, |cffFF0000Rot|r bedeutet es ist veraltet)"
INFO_BY = "von"
INFO_VERSION = "Version:"
INFO_NEW = "Neuste:"
LIBRARY = "Bibliothek"
end
if GetLocale() == "ruRU" then -- Russian Translations
MSG_OUTDATED = "Ваша версия %s устарела (последняя версия %s). Вы можете скачать последнюю версию на https://github.com/ElvUI-Vanilla/ElvUI/"
HDR_CONFIG = "Плагины"
HDR_INFORMATION = "LibElvUIPlugin-1.0.%d - Загруженные плагины (|cff2BC226Зеленый|r означает, что у вас последняя версия, |cffFF0000Красный|r - устаревшая)"
INFO_BY = "от"
INFO_VERSION = "Версия:"
INFO_NEW = "Последняя:"
LIBRARY = "Библиотека"
end
--
-- Plugin table format:
-- { name (string) - The name of the plugin,
-- version (string) - The version of the plugin,
-- optionCallback (string) - The callback to call when ElvUI_Config is loaded
-- }
--
--
-- RegisterPlugin(name,callback)
-- Registers a module with the given name and option callback, pulls version info from metadata
--
function lib:RegisterPlugin(name,callback, isLib)
local plugin = {}
plugin.name = name
plugin.version = name == MAJOR and MINOR or GetAddOnMetadata(name, "Version")
if isLib then plugin.isLib = true; plugin.version = 1 end
plugin.callback = callback
lib.plugins[name] = plugin
local loaded = IsAddOnLoaded("ElvUI_Config")
if not lib.vcframe then
local f = CreateFrame('Frame')
f:RegisterEvent("RAID_ROSTER_UPDATE");
f:RegisterEvent("PARTY_MEMBERS_CHANGED");
f:RegisterEvent("CHAT_MSG_ADDON")
f:SetScript("OnEvent", lib.VersionCheck)
lib.vcframe = f
end
if not loaded then
if not lib.ConfigFrame then
local configFrame = CreateFrame("Frame")
configFrame:RegisterEvent("ADDON_LOADED")
configFrame:SetScript("OnEvent", function(self,event,addon)
if addon == "ElvUI_Config" then
for _, plugin in pairs(lib.plugins) do
if(plugin.callback) then
plugin.callback()
end
end
end
end)
lib.ConfigFrame = configFrame
end
elseif loaded then
-- Need to update plugins list
if name ~= MAJOR then
ElvUI[1].Options.args.plugins.args.plugins.name = lib:GeneratePluginList()
end
callback()
end
return plugin
end
function lib:GetPluginOptions()
ElvUI[1].Options.args.plugins = {
order = -10,
type = "group",
name = HDR_CONFIG,
guiInline = false,
args = {
pluginheader = {
order = 1,
type = "header",
name = format(HDR_INFORMATION, MINOR),
},
plugins = {
order = 2,
type = "description",
name = lib:GeneratePluginList(),
},
}
}
end
function lib:GenerateVersionCheckMessage()
local list = ""
for _, plugin in pairs(lib.plugins) do
if plugin.name ~= MAJOR then
list = list..plugin.name.."="..plugin.version..";"
end
end
return list
end
local function SendPluginVersionCheck(self)
lib:SendPluginVersionCheck(lib:GenerateVersionCheckMessage())
if self["ElvUIPluginSendMSGTimer"] then
self:CancelTimer(self["ElvUIPluginSendMSGTimer"])
self["ElvUIPluginSendMSGTimer"] = nil
end
end
function lib:VersionCheck(event, prefix, message, channel, sender)
if(not ElvUI[1].global.general.versionCheck) then return; end
local E = ElvUI[1]
if event == "CHAT_MSG_ADDON" then
if sender == E.myname or not sender or prefix ~= lib.prefix then return end
if not E["pluginRecievedOutOfDateMessage"] then
for _, p in pairs({strsplit(";",message)}) do
local name, version = p:match("([%w_]+)=([%d%p]+)")
if lib.plugins[name] then
local plugin = lib.plugins[name]
if plugin.version ~= "BETA" and version ~= nil and tonumber(version) ~= nil and plugin.version ~= nil and tonumber(plugin.version) ~= nil and tonumber(version) > tonumber(plugin.version) then
plugin.old = true
plugin.newversion = tonumber(version)
local Pname = GetAddOnMetadata(plugin.name, "Title")
E:Print(format(MSG_OUTDATED,Pname,plugin.newversion))
E["pluginRecievedOutOfDateMessage"] = true
end
end
end
end
else
E.SendPluginVersionCheck = E.SendPluginVersionCheck or SendPluginVersionCheck
E["ElvUIPluginSendMSGTimer"] = E:ScheduleTimer("SendPluginVersionCheck", 2)
end
end
function lib:GeneratePluginList()
local list = ""
local E = ElvUI[1]
for _, plugin in pairs(lib.plugins) do
if plugin.name ~= MAJOR then
local author = GetAddOnMetadata(plugin.name, "Author")
local Pname = GetAddOnMetadata(plugin.name, "Title") or plugin.name
local color = plugin.old and E:RGBToHex(1,0,0) or E:RGBToHex(0,1,0)
list = list..Pname
if author then
list = list.." ".. INFO_BY .." "..author
end
list = list..color.." - "..(plugin.isLib and LIBRARY or INFO_VERSION .." "..plugin.version)
if plugin.old then
list = list.." ("..INFO_NEW .." "..plugin.newversion..")"
end
list = list.."|r\n"
end
end
return list
end
function lib:SendPluginVersionCheck(message)
local plist = {strsplit(";",message)}
local m = ""
local delay = 1
local E = ElvUI[1]
for _, p in pairs(plist) do
if(getn(m..p..";") < 230) then
m = m..p..";"
else
local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers();
if(numRaid > 0) then
E:Delay(delay, SendAddonMessage(lib.prefix, m, "RAID"))
elseif(numParty > 0) then
E:Delay(delay, SendAddonMessage(lib.prefix, m, "PARTY"))
end
m = p..";"
delay = delay + 1
end
end
-- Send the last message
local numParty, numRaid = GetNumPartyMembers(), GetNumRaidMembers();
if(numRaid > 0) then
E:Delay(delay+1, SendAddonMessage(lib.prefix, m, "RAID"))
elseif(numParty > 0) then
E:Delay(delay+1, SendAddonMessage(lib.prefix, m, "PARTY"))
end
end
lib:RegisterPlugin(MAJOR, lib.GetPluginOptions)
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibElvUIPlugin-1.0.lua"/>
</Ui>
@@ -0,0 +1,203 @@
--[[
Copyright 2013 João Cardoso
CustomSearch is distributed under the terms of the GNU General Public License (Version 3).
As a special exception, the copyright holders of this library give you permission to embed it
with independent modules to produce an addon, regardless of the license terms of these
independent modules, and to copy and distribute the resulting software under terms of your
choice, provided that you also meet, for each embedded independent module, the terms and
conditions of the license of that module. Permission is not granted to modify this library.
This library 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 the library. If not, see <http://www.gnu.org/licenses/gpl-3.0.txt>.
This file is part of CustomSearch.
--]]
local Lib = LibStub:NewLibrary('CustomSearch-1.0', 9)
if not Lib then
return
end
--[[ Parsing ]]--
function Lib:Matches(object, search, filters)
if object then
self.filters = filters
self.object = object
return self:MatchAll(search or '')
end
end
function Lib:MatchAll(search)
for phrase in self:Clean(search):gmatch('[^&]+') do
if not self:MatchAny(phrase) then
return
end
end
return true
end
function Lib:MatchAny(search)
for phrase in search:gmatch('[^|]+') do
if self:Match(phrase) then
return true
end
end
end
function Lib:Match(search)
local tag, rest = search:match('^%s*(%S+):(.*)$')
if tag then
tag = '^' .. tag
search = rest
end
local words = search:gmatch('%S+')
local failed
for word in words do
if word == self.OR then
if failed then
failed = false
else
break
end
else
local negate, rest = word:match('^([!~]=*)(.*)$')
if negate or word == self.NOT_MATCH then
word = rest and rest ~= '' and rest or words() or ''
negate = -1
else
negate = 1
end
local operator, rest = word:match('^(=*[<>]=*)(.*)$')
if operator then
word = rest ~= '' and rest or words()
end
local result = self:Filter(tag, operator, word) and 1 or -1
if result * negate ~= 1 then
failed = true
end
end
end
return not failed
end
--[[ Filtering ]]--
function Lib:Filter(tag, operator, search)
if not search then
return true
end
if tag then
for _, filter in pairs(self.filters) do
for _, value in pairs(filter.tags or {}) do
if value:find(tag) then
return self:UseFilter(filter, operator, search)
end
end
end
else
for _, filter in pairs(self.filters) do
if not filter.onlyTags and self:UseFilter(filter, operator, search) then
return true
end
end
end
end
function Lib:UseFilter(filter, operator, search)
local data = {filter:canSearch(operator, search, self.object)}
if data[1] then
return filter:match(self.object, operator, unpack(data))
end
end
--[[ Utilities ]]--
function Lib:Find(search, ...)
for i = 1, select('#', ...) do
local text = select(i, ...)
if text and self:Clean(text):find(search) then
return true
end
end
end
function Lib:Clean(string)
string = string:lower()
string = string:gsub('[%(%)%.%%%+%-%*%?%[%]%^%$]', function(c) return '%'..c end)
for accent, char in pairs(self.ACCENTS) do
string = string:gsub(accent, char)
end
return string
end
function Lib:Compare(op, a, b)
if op then
if op:find('<') then
if op:find('=') then
return a <= b
end
return a < b
end
if op:find('>')then
if op:find('=') then
return a >= b
end
return a > b
end
end
return a == b
end
--[[ Localization ]]--
do
local no = {enUS = 'Not', frFR = 'Pas', deDE = 'Nicht', ruRU = 'Нет'}
local just_or = {enUS = 'Or', frFR = 'Ou', deDE = 'Oder', ruRU = 'Или'}
local accents = {
a = {'à','â','ã','å'},
e = {'è','é','ê','ê','ë'},
i = {'ì', 'í', 'î', 'ï'},
o = {'ó','ò','ô','õ'},
u = {'ù', 'ú', 'û', 'ü'},
c = {'ç'}, n = {'ñ'}
}
Lib.ACCENTS = {}
for char, accents in pairs(accents) do
for _, accent in ipairs(accents) do
Lib.ACCENTS[accent] = char
end
end
Lib.OR = Lib:Clean(just_or[GetLocale()] or "")
Lib.NOT = no[GetLocale()] or NO
Lib.NOT_MATCH = Lib:Clean(Lib.NOT)
setmetatable(Lib, {__call = Lib.Matches})
end
return Lib
@@ -0,0 +1,278 @@
--[[
ItemSearch
An item text search engine of some sort
--]]
local Search = LibStub("CustomSearch-1.0");
local Unfit = LibStub("Unfit-1.0");
local Lib = LibStub:NewLibrary("LibItemSearch-1.2", 11);
if(Lib) then
Lib.Filters = {};
else
return;
end
--[[ User API ]]--
function Lib:Matches(link, search)
return Search(link, search, self.Filters);
end
function Lib:Tooltip(link, search)
return link and self.Filters.tip:match(link, nil, search);
end
function Lib:TooltipPhrase(link, search)
return link and self.Filters.tipPhrases:match(link, nil, search);
end
function Lib:InSet(link, search)
if(IsEquippableItem(link)) then
local id = tonumber(link:match("item:(%-?%d+)"));
return self:BelongsToSet(id, (search or ""):lower());
end
end
--[[ Basics ]]--
Lib.Filters.name = {
tags = {"n", "name"},
canSearch = function(self, operator, search)
return not operator and search;
end,
match = function(self, item, _, search)
local name = item:match("%[(.-)%]");
return Search:Find(search, name);
end
};
Lib.Filters.type = {
tags = {"t", "type", "s", "slot"},
canSearch = function(self, operator, search)
return not operator and search;
end,
match = function(self, item, _, search)
local type, subType, _, equipSlot = select(6, GetItemInfo(item));
return Search:Find(search, type, subType, _G[equipSlot]);
end
};
Lib.Filters.level = {
tags = {"l", "level", "lvl", "ilvl"},
canSearch = function(self, _, search)
return tonumber(search);
end,
match = function(self, link, operator, num)
local lvl = select(4, GetItemInfo(link));
if(lvl) then
return Search:Compare(operator, lvl, num);
end
end
};
Lib.Filters.requiredlevel = {
tags = {"r", "req", "rl", "reql", "reqlvl"},
canSearch = function(self, _, search)
return tonumber(search);
end,
match = function(self, link, operator, num)
local lvl = select(5, GetItemInfo(link));
if(lvl) then
return Search:Compare(operator, lvl, num);
end
end
};
--[[ Quality ]]--
local qualities = {};
for i = 0, #ITEM_QUALITY_COLORS do
qualities[i] = _G["ITEM_QUALITY" .. i .. "_DESC"]:lower();
end
Lib.Filters.quality = {
tags = {"q", "quality"},
canSearch = function(self, _, search)
for i, name in pairs(qualities) do
if(name:find(search)) then
return i;
end
end
end,
match = function(self, link, operator, num)
local quality = select(3, GetItemInfo(link));
return Search:Compare(operator, quality, num);
end,
};
--[[ Usable ]]--
Lib.Filters.usable = {
tags = {},
canSearch = function(self, operator, search)
return not operator and search == "usable";
end,
match = function(self, link)
if(not Unfit:IsItemUnusable(link)) then
local lvl = select(5, GetItemInfo(link));
return lvl and (lvl ~= 0 and lvl <= UnitLevel("player"));
end
end
};
--[[ Tooltip Searches ]]--
local scanner = LibItemSearchTooltipScanner or CreateFrame("GameTooltip", "LibItemSearchTooltipScanner", UIParent, "GameTooltipTemplate");
Lib.Filters.tip = {
tags = {"tt", "tip", "tooltip"},
onlyTags = true,
canSearch = function(self, _, search)
return search;
end,
match = function(self, link, _, search)
if(link:find("item:")) then
scanner:SetOwner(UIParent, "ANCHOR_NONE");
scanner:SetHyperlink(link)
for i = 1, scanner:NumLines() do
if(Search:Find(search, _G[scanner:GetName() .. "TextLeft" .. i]:GetText())) then
return true;
end
end
end
end
};
local escapes = {
["|c%x%x%x%x%x%x%x%x"] = "",
["|r"] = ""
};
local function CleanString(str)
for k, v in pairs(escapes) do
str = str:gsub(k, v);
end
return str;
end
Lib.Filters.tipPhrases = {
canSearch = function(self, _, search)
return self.keywords[search];
end,
match = function(self, link, _, search)
local id = link:match("item:(%d+)");
if(not id) then
return;
end
local cached = self.cache[search][id];
if(cached ~= nil) then
return cached;
end
scanner:SetOwner(UIParent, "ANCHOR_NONE");
scanner:SetHyperlink(link);
local matches = false
for i = 1, scanner:NumLines() do
local text = _G["LibItemSearchTooltipScannerTextLeft" .. i]:GetText();
text = CleanString(text);
if(search == text) then
matches = true;
break;
end
end
self.cache[search][id] = matches;
return matches;
end,
cache = setmetatable({}, {__index = function(t, k) local v = {} t[k] = v return v end}),
keywords = {
[ITEM_SOULBOUND:lower()] = ITEM_BIND_ON_PICKUP,
["bound"] = ITEM_BIND_ON_PICKUP,
["bop"] = ITEM_BIND_ON_PICKUP,
["boe"] = ITEM_BIND_ON_EQUIP,
["bou"] = ITEM_BIND_ON_USE,
["boa"] = ITEM_BIND_TO_ACCOUNT,
[QUESTS_LABEL:lower()] = ITEM_BIND_QUEST
};
};
--[[ Equipment Sets ]]--
if IsAddOnLoaded("ItemRack") then
local sameID = ItemRack.SameID
function Lib:BelongsToSet(id, search)
for name, set in pairs(ItemRackUser.Sets) do
if name:sub(1,1) ~= "" and Search:Find(search, name) then
for _, item in pairs(set.equip) do
if sameID(id, item) then
return true
end
end
end
end
end
elseif IsAddOnLoaded("Wardrobe") then
function Lib:BelongsToSet(id, search)
for _, outfit in ipairs(Wardrobe.CurrentConfig.Outfit) do
local name = outfit.OutfitName
if Search:Find(search, name) or search == "matchall" then
for _, item in pairs(outfit.Item) do
if item.IsSlotUsed == 1 and item.ItemID == id then
return true
end
end
end
end
end
else
function Lib:BelongsToSet(id, search)
for i = 1, GetNumEquipmentSets() do
local name = GetEquipmentSetInfo(i)
if Search:Find(search, name) then
local items = GetEquipmentSetItemIDs(name)
for _, item in pairs(items) do
if id == item then
return true
end
end
end
end
end
end
Lib.Filters.sets = {
tags = {"s", "set"},
canSearch = function(self, operator, search)
return not operator and search
end,
match = function(self, link, _, search)
return Lib:InSet(link, search)
end,
}
@@ -0,0 +1,6 @@
<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/
..\FrameXML\UI.xsd">
<Script file="CustomSearch-1.0\CustomSearch-1.0.lua"/>
<Script file="Unfit-1.0\Unfit-1.0.lua"/>
<Script file="LibItemSearch-1.2.lua"/>
</Ui>
@@ -0,0 +1,116 @@
--[[
Copyright 2011-2016 João Cardoso
Unfit is distributed under the terms of the GNU General Public License (Version 3).
As a special exception, the copyright holders of this library give you permission to embed it
with independent modules to produce an addon, regardless of the license terms of these
independent modules, and to copy and distribute the resulting software under terms of your
choice, provided that you also meet, for each embedded independent module, the terms and
conditions of the license of that module. Permission is not granted to modify this library.
This library 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 the library. If not, see <http://www.gnu.org/licenses/gpl-3.0.txt>.
This file is part of Unfit.
--]]
local Lib = LibStub:NewLibrary('Unfit-1.0', 9)
if not Lib then
return
end
--[[ Data ]]--
do
local _, Class = UnitClass('player')
local Unusable
if Class == 'DEATHKNIGHT' then
Unusable = {
{3, 4, 10, 11, 13, 14, 15, 16},
{7}
}
elseif Class == 'DRUID' then
Unusable = {
{1, 2, 3, 4, 8, 9, 14, 15, 16},
{4, 5, 7},
true
}
elseif Class == 'HUNTER' then
Unusable = {
{5, 6, 16},
{5, 6}
}
elseif Class == 'MAGE' then
Unusable = {
{1, 2, 3, 4, 5, 6, 7, 9, 11, 14, 15},
{3, 4, 5, 7},
true
}
elseif Class == 'PALADIN' then
Unusable = {
{3, 4, 10, 11, 13, 14, 15, 16},
{},
true
}
elseif Class == 'PRIEST' then
Unusable = {
{1, 2, 3, 4, 6, 7, 8, 9, 11, 14, 15},
{3, 4, 5, 7},
true
}
elseif Class == 'ROGUE' then
Unusable = {
{2, 6, 7, 9, 10, 16},
{4, 5, 6}
}
elseif Class == 'SHAMAN' then
Unusable = {
{3, 4, 7, 8, 9, 14, 15, 16},
{5}
}
elseif Class == 'WARLOCK' then
Unusable = {
{1, 2, 3, 4, 5, 6, 7, 9, 11, 14, 15},
{3, 4, 5, 7},
true
}
elseif Class == 'WARRIOR' then
Unusable = {{16}, {}}
else
Unusable = {{}, {}}
end
for class = 1, 2 do
local subs = {GetAuctionItemSubClasses(class)}
for i, subclass in ipairs(Unusable[class]) do
Unusable[subs[subclass]] = true
end
Unusable[class] = nil
subs = nil
end
Lib.unusable = Unusable
Lib.cannotDual = Unusable[3]
end
--[[ API ]]--
function Lib:IsItemUnusable(...)
if ... then
local subclass, _, slot = select(7, GetItemInfo(...))
return Lib:IsClassUnusable(subclass, slot)
end
end
function Lib:IsClassUnusable(subclass, slot)
if subclass then
return slot ~= '' and Unusable[subclass] or slot == 'INVTYPE_WEAPONOFFHAND' and Lib.cannotDual
end
end
@@ -0,0 +1,237 @@
--[[
Name: LibSharedMedia-3.0
Revision: $Revision: 62 $
Author: Elkano (elkano@gmx.de)
Inspired By: SurfaceLib by Haste/Otravi (troeks@gmail.com)
Website: http://www.wowace.com/projects/libsharedmedia-3-0/
Description: Shared handling of media data (fonts, sounds, textures, ...) between addons.
Dependencies: LibStub, CallbackHandler-1.0
License: LGPL v2.1
]]
local MAJOR, MINOR = "LibSharedMedia-3.0", 2040001 -- 2.4.3 / increase manually on changes
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
local _G = getfenv(0)
local pairs = _G.pairs
local type = _G.type
local band = _G.bit.band
local table_insert = _G.table.insert
local table_sort = _G.table.sort
local locale = GetLocale()
local locale_is_western
local LOCALE_MASK = 0
lib.LOCALE_BIT_koKR = 1
lib.LOCALE_BIT_ruRU = 2
lib.LOCALE_BIT_zhCN = 4
lib.LOCALE_BIT_zhTW = 8
lib.LOCALE_BIT_western = 128
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
lib.callbacks = lib.callbacks or CallbackHandler:New(lib)
lib.DefaultMedia = lib.DefaultMedia or {}
lib.MediaList = lib.MediaList or {}
lib.MediaTable = lib.MediaTable or {}
lib.MediaType = lib.MediaType or {}
lib.OverrideMedia = lib.OverrideMedia or {}
local defaultMedia = lib.DefaultMedia
local mediaList = lib.MediaList
local mediaTable = lib.MediaTable
local overrideMedia = lib.OverrideMedia
-- create mediatype constants
lib.MediaType.BACKGROUND = "background" -- background textures
lib.MediaType.BORDER = "border" -- border textures
lib.MediaType.FONT = "font" -- fonts
lib.MediaType.STATUSBAR = "statusbar" -- statusbar textures
lib.MediaType.SOUND = "sound" -- sound files
-- populate lib with default Blizzard data
-- BACKGROUND
if not lib.MediaTable.background then lib.MediaTable.background = {} end
lib.MediaTable.background["None"] = [[]]
lib.MediaTable.background["Blizzard Dialog Background"] = [[Interface\DialogFrame\UI-DialogBox-Background]]
lib.MediaTable.background["Blizzard Dialog Background Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Background]]
lib.MediaTable.background["Blizzard Low Health"] = [[Interface\FullScreenTextures\LowHealth]]
lib.MediaTable.background["Blizzard Out of Control"] = [[Interface\FullScreenTextures\OutOfControl]]
lib.MediaTable.background["Blizzard Tabard Background"] = [[Interface\TabardFrame\TabardFrameBackground]]
lib.MediaTable.background["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Background]]
lib.MediaTable.background["Solid"] = [[Interface\Buttons\WHITE8X8]]
lib.DefaultMedia.background = "None"
-- BORDER
if not lib.MediaTable.border then lib.MediaTable.border = {} end
lib.MediaTable.border["None"] = [[]]
lib.MediaTable.border["Blizzard Chat Bubble"] = [[Interface\Tooltips\ChatBubble-Backdrop]]
lib.MediaTable.border["Blizzard Dialog"] = [[Interface\DialogFrame\UI-DialogBox-Border]]
lib.MediaTable.border["Blizzard Dialog Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Border]]
lib.MediaTable.border["Blizzard Party"] = [[Interface\CHARACTERFRAME\UI-Party-Border]]
lib.MediaTable.border["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Border]]
lib.DefaultMedia.border = "None"
-- FONT
if not lib.MediaTable.font then lib.MediaTable.font = {} end
local SML_MT_font = lib.MediaTable.font
if locale == "koKR" then
LOCALE_MASK = lib.LOCALE_BIT_koKR
--
SML_MT_font["굵은 글꼴"] = [[Fonts\2002B.TTF]]
SML_MT_font["기본 글꼴"] = [[Fonts\2002.TTF]]
SML_MT_font["데미지 글꼴"] = [[Fonts\K_Damage.TTF]]
SML_MT_font["퀘스트 글꼴"] = [[Fonts\K_Pagetext.TTF]]
--
lib.DefaultMedia["font"] = "기본 글꼴" -- someone from koKR please adjust if needed
--
elseif locale == "zhCN" then
LOCALE_MASK = lib.LOCALE_BIT_zhCN
--
SML_MT_font["伤害数字"] = [[Fonts\ZYKai_C.ttf]]
SML_MT_font["默认"] = [[Fonts\ZYKai_T.ttf]]
SML_MT_font["聊天"] = [[Fonts\ZYHei.ttf]]
--
lib.DefaultMedia["font"] = "默认" -- someone from zhCN please adjust if needed
--
elseif locale == "zhTW" then
LOCALE_MASK = lib.LOCALE_BIT_zhTW
--
SML_MT_font["提示訊息"] = [[Fonts\bHEI00M.ttf]]
SML_MT_font["聊天"] = [[Fonts\bHEI01B.ttf]]
SML_MT_font["傷害數字"] = [[Fonts\bKAI00M.ttf]]
SML_MT_font["預設"] = [[Fonts\bLEI00D.ttf]]
--
lib.DefaultMedia["font"] = "預設" -- someone from zhTW please adjust if needed
elseif locale == "ruRU" then
LOCALE_MASK = lib.LOCALE_BIT_ruRU
--
SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
SML_MT_font["Nimrod MT"] = [[Fonts\NIM_____.ttf]]
SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
lib.DefaultMedia.font = "Arial Narrow"
--
else
LOCALE_MASK = lib.LOCALE_BIT_western
locale_is_western = true
--
SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
--
lib.DefaultMedia.font = "Friz Quadrata TT"
--
end
-- STATUSBAR
if not lib.MediaTable.statusbar then lib.MediaTable.statusbar = {} end
lib.MediaTable.statusbar["Blizzard"] = [[Interface\TargetingFrame\UI-StatusBar]]
lib.DefaultMedia.statusbar = "Blizzard"
-- SOUND
if not lib.MediaTable.sound then lib.MediaTable.sound = {} end
lib.MediaTable.sound["None"] = [[Interface\Quiet.ogg]] -- Relies on the fact that PlaySound[File] doesn't error on non-existing input.
lib.DefaultMedia.sound = "None"
local function rebuildMediaList(mediatype)
local mtable = mediaTable[mediatype]
if not mtable then return end
if not mediaList[mediatype] then mediaList[mediatype] = {} end
local mlist = mediaList[mediatype]
-- list can only get larger, so simply overwrite it
local i = 0
for k in pairs(mtable) do
i = i + 1
mlist[i] = k
end
table_sort(mlist)
end
function lib:Register(mediatype, key, data, langmask)
if type(mediatype) ~= "string" then
error(MAJOR..":Register(mediatype, key, data, langmask) - mediatype must be string, got "..type(mediatype))
end
if type(key) ~= "string" then
error(MAJOR..":Register(mediatype, key, data, langmask) - key must be string, got "..type(key))
end
mediatype = string.lower(mediatype)
if mediatype == lib.MediaType.FONT and ((langmask and band(langmask, LOCALE_MASK) == 0) or not (langmask or locale_is_western)) then return false end
if mediatype == lib.MediaType.SOUND and type(data) == "string" then
local path = data
-- Only wav, ogg and mp3 are valid sounds.
if not string.find(path, ".ogg", nil, true) and not string.find(path, ".mp3", nil, true) and not string.find(path, ".wav", nil, true) then
return false
end
end
if not mediaTable[mediatype] then mediaTable[mediatype] = {} end
local mtable = mediaTable[mediatype]
if mtable[key] then return false end
mtable[key] = data
rebuildMediaList(mediatype)
self.callbacks:Fire("LibSharedMedia_Registered", mediatype, key)
return true
end
function lib:Fetch(mediatype, key, noDefault)
local mtt = mediaTable[mediatype]
local overridekey = overrideMedia[mediatype]
local result = mtt and ((overridekey and mtt[overridekey] or mtt[key]) or (not noDefault and defaultMedia[mediatype] and mtt[defaultMedia[mediatype]])) or nil
return result ~= "" and result or nil
end
function lib:IsValid(mediatype, key)
return mediaTable[mediatype] and (not key or mediaTable[mediatype][key]) and true or false
end
function lib:HashTable(mediatype)
return mediaTable[mediatype]
end
function lib:List(mediatype)
if not mediaTable[mediatype] then
return nil
end
if not mediaList[mediatype] then
rebuildMediaList(mediatype)
end
return mediaList[mediatype]
end
function lib:GetGlobal(mediatype)
return overrideMedia[mediatype]
end
function lib:SetGlobal(mediatype, key)
if not mediaTable[mediatype] then
return false
end
overrideMedia[mediatype] = (key and mediaTable[mediatype][key]) and key or nil
self.callbacks:Fire("LibSharedMedia_SetGlobal", mediatype, overrideMedia[mediatype])
return true
end
function lib:GetDefault(mediatype)
return defaultMedia[mediatype]
end
function lib:SetDefault(mediatype, key)
if mediaTable[mediatype] and mediaTable[mediatype][key] and not defaultMedia[mediatype] then
defaultMedia[mediatype] = key
return true
else
return false
end
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibSharedMedia-3.0.lua"/>
</Ui>
@@ -0,0 +1,280 @@
--[[---------------------------------------------------------------------------------
General Library providing an alternate StartMoving() that allows you to
specify a number of frames to snap-to when moving the frame around
Example Usage:
<OnLoad>
this:RegisterForDrag("LeftButton")
</OnLoad>
<OnDragStart>
StickyFrames:StartMoving(this, {WatchDogFrame_player, WatchDogFrame_target, WatchDogFrame_party1, WatchDogFrame_party2, WatchDogFrame_party3, WatchDogFrame_party4},3,3,3,3)
</OnDragStart>
<OnDragStop>
StickyFrames:StopMoving(this)
StickyFrames:AnchorFrame(this)
</OnDragStop>
------------------------------------------------------------------------------------
This is a modified version by Elv for ElvUI
------------------------------------------------------------------------------------]]
local MAJOR, MINOR = "LibSimpleSticky-1.0", 2
local StickyFrames, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not StickyFrames then return end
--[[---------------------------------------------------------------------------------
Class declaration, along with a temporary table to hold any existing OnUpdate
scripts.
------------------------------------------------------------------------------------]]
StickyFrames.scripts = StickyFrames.scripts or {}
StickyFrames.rangeX = 15
StickyFrames.rangeY = 15
StickyFrames.sticky = StickyFrames.sticky or {}
--[[---------------------------------------------------------------------------------
StickyFrames:StartMoving() - Sets a custom OnUpdate for the frame so it follows
the mouse and snaps to the frames you specify
frame: The frame we want to move. Is typically "this"
frameList: A integer indexed list of frames that the given frame should try to
stick to. These don't have to have anything special done to them,
and they don't really even need to exist. You can inclue the
moving frame in this list, it will be ignored. This helps you
if you have a number of frames, just make ONE list to pass.
{WatchDogFrame_player, WatchDogFrame_party1, .. WatchDogFrame_party4}
left: If your frame has a tranparent border around the entire frame
(think backdrops with borders). This can be used to fine tune the
edges when you're stickying groups. Refers to any offset on the
LEFT edge of the frame being moved.
top: same
right: same
bottom: same
------------------------------------------------------------------------------------]]
function StickyFrames:StartMoving(frame, frameList, left, top, right, bottom)
local x,y = GetCursorPosition()
local aX,aY = frame:GetCenter()
local aS = frame:GetEffectiveScale()
aX,aY = aX*aS,aY*aS
local xoffset,yoffset = (aX - x),(aY - y)
self.scripts[frame] = frame:GetScript("OnUpdate")
frame:SetScript("OnUpdate", self:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom))
end
--[[---------------------------------------------------------------------------------
This stops the OnUpdate, leaving the frame at its last position. This will
leave it anchored to UIParent. You can call StickyFrames:AnchorFrame() to
anchor it back "TOPLEFT" , "TOPLEFT" to the parent.
------------------------------------------------------------------------------------]]
function StickyFrames:StopMoving(frame)
frame:SetScript("OnUpdate", self.scripts[frame])
self.scripts[frame] = nil
if StickyFrames.sticky[frame] then
local sticky = StickyFrames.sticky[frame]
StickyFrames.sticky[frame] = nil
return true, sticky
else
return false, nil
end
end
--[[---------------------------------------------------------------------------------
This can be called in conjunction with StickyFrames:StopMoving() to anchor the
frame right back to the parent, so you can manipulate its children as a group
(This is useful in WatchDog)
------------------------------------------------------------------------------------]]
function StickyFrames:AnchorFrame(frame)
local xA,yA = frame:GetCenter()
local parent = frame:GetParent() or UIParent
local xP,yP = parent:GetCenter()
local sA,sP = frame:GetEffectiveScale(), parent:GetEffectiveScale()
xP,yP = (xP*sP) / sA, (yP*sP) / sA
local xo,yo = (xP - xA)*-1, (yP - yA)*-1
frame:ClearAllPoints()
frame:SetPoint("CENTER", parent, "CENTER", xo, yo)
end
--[[---------------------------------------------------------------------------------
Internal Functions -- Do not call these.
------------------------------------------------------------------------------------]]
--[[---------------------------------------------------------------------------------
Returns an anonymous OnUpdate function for the frame in question. Need
to provide the frame, frameList along with the x and y offset (difference between
where the mouse picked up the frame, and the insets (left,top,right,bottom) in the
case of borders, etc.w
------------------------------------------------------------------------------------]]
function StickyFrames:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom)
return function()
local x,y = GetCursorPosition()
local s = frame:GetEffectiveScale()
local sticky = nil
x,y = x/s,y/s
frame:ClearAllPoints()
frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x+xoffset, y+yoffset)
StickyFrames.sticky[frame] = nil
for i = 1, table.getn(frameList) do
local v = frameList[i]
if frame ~= v and frame ~= v:GetParent() and not IsShiftKeyDown() and v:IsVisible() then
if self:SnapFrame(frame, v, left, top, right, bottom) then
StickyFrames.sticky[frame] = v
break
end
end
end
end
end
--[[---------------------------------------------------------------------------------
Internal debug function.
------------------------------------------------------------------------------------]]
function StickyFrames:debug(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cffffff00StickyFrames: |r"..tostring(msg))
end
--[[---------------------------------------------------------------------------------
This is called when finding an overlap between two sticky frame. If frameA is near
a sticky edge of frameB, then it will snap to that edge and return true. If there
is no sticky edge collision, will return false so we can test other frames for
stickyness.
------------------------------------------------------------------------------------]]
function StickyFrames:SnapFrame(frameA, frameB, left, top, right, bottom)
local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
local xA, yA = frameA:GetCenter()
local xB, yB = frameB:GetCenter()
local hA, hB = frameA:GetHeight() / 2, ((frameB:GetHeight() * sB) / sA) / 2
local wA, wB = frameA:GetWidth() / 2, ((frameB:GetWidth() * sB) / sA) / 2
local newX, newY = xA, yA
if not left then left = 0 end
if not top then top = 0 end
if not right then right = 0 end
if not bottom then bottom = 0 end
-- Lets translate B's coords into A's scale
if not xB or not yB or not sB or not sA or not sB then return end
xB, yB = (xB*sB) / sA, (yB*sB) / sA
local stickyAx, stickyAy = wA * 0.75, hA * 0.75
local stickyBx, stickyBy = wB * 0.75, hB * 0.75
-- Grab the edges of each frame, for easier comparison
local lA, tA, rA, bA = frameA:GetLeft(), frameA:GetTop(), frameA:GetRight(), frameA:GetBottom()
local lB, tB, rB, bB = frameB:GetLeft(), frameB:GetTop(), frameB:GetRight(), frameB:GetBottom()
local snap = nil
-- Translate into A's scale
lB, tB, rB, bB = (lB * sB) / sA, (tB * sB) / sA, (rB * sB) / sA, (bB * sB) / sA
if (bA <= tB and bB <= tA) then
-- Horizontal Centers
if xA <= (xB + StickyFrames.rangeX) and xA >= (xB - StickyFrames.rangeX) then
newX = xB
snap = true
end
-- Interior Left
if lA <= (lB + StickyFrames.rangeX) and lA >= (lB - StickyFrames.rangeX) then
newX = lB + wA
if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
newX = newX + 4
end
snap = true
end
-- Interior Right
if rA <= (rB + StickyFrames.rangeX) and rA >= (rB - StickyFrames.rangeX) then
newX = rB - wA
if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
newX = newX - 4
end
snap = true
end
-- Exterior Left to Right
if lA <= (rB + StickyFrames.rangeX) and lA >= (rB - StickyFrames.rangeX) then
newX = rB + (wA - left)
snap = true
end
-- Exterior Right to Left
if rA <= (lB + StickyFrames.rangeX) and rA >= (lB - StickyFrames.rangeX) then
newX = lB - (wA - right)
snap = true
end
end
if (lA <= rB and lB <= rA) then
-- Vertical Centers
if yA <= (yB + StickyFrames.rangeY) and yA >= (yB - StickyFrames.rangeY) then
newY = yB
snap = true
end
-- Interior Top
if tA <= (tB + StickyFrames.rangeY) and tA >= (tB - StickyFrames.rangeY) then
newY = tB - hA
if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
newY = newY - 4
end
snap = true
end
-- Interior Bottom
if bA <= (bB + StickyFrames.rangeY) and bA >= (bB - StickyFrames.rangeY) then
newY = bB + hA
if frameB == UIParent or frameB == WorldFrame or frameB == ElvUIParent then
newY = newY + 4
end
snap = true
end
-- Exterior Top to Bottom
if tA <= (bB + StickyFrames.rangeY + bottom) and tA >= (bB - StickyFrames.rangeY + bottom) then
newY = bB - (hA - top)
snap = true
end
-- Exterior Bottom to Top
if bA <= (tB + StickyFrames.rangeY - top) and bA >= (tB - StickyFrames.rangeY - top) then
newY = tB + (hA - bottom)
snap = true
end
end
if snap then
frameA:ClearAllPoints()
frameA:SetPoint("CENTER", UIParent, "BOTTOMLEFT", newX, newY)
return true
end
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibSimpleSticky.lua"/>
</Ui>
@@ -0,0 +1,33 @@
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local _G = getfenv()
local strfind, strfmt = string.find, string.format
local LibStub = _G[LIBSTUB_MAJOR]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or { libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
local _,_,num = strfind(minor, "(%d+)")
minor = assert(tonumber(num), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(strfmt("Cannot find a library instance of %q.", tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="LibStub.lua"/>
</Ui>
@@ -0,0 +1,47 @@
--$Id: LibEasyMenu.lua 19 2017-07-02 13:34:55Z arith $
-- Simplified Menu Display System
-- This is a basic system for displaying a menu from a structure table.
--
-- See UIDropDownMenu.lua for the menuList details.
--
-- Args:
-- menuList - menu table
-- menuFrame - the UI frame to populate
-- anchor - where to anchor the frame (e.g. CURSOR)
-- x - x offset
-- y - y offset
-- displayMode - border type
-- autoHideDelay - how long until the menu disappears
--
--
-- ----------------------------------------------------------------------------
-- Localized Lua globals.
-- ----------------------------------------------------------------------------
local _G = getfenv(0)
-- ----------------------------------------------------------------------------
local MAJOR_VERSION = "LibEasyMenu-1.04.7030024484"
local MINOR_VERSION = 90000 + 19
local LibStub = _G.LibStub
if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
local Lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
if not Lib then return end
function L_EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay )
if ( displayMode == "MENU" ) then
menuFrame.displayMode = displayMode;
end
L_UIDropDownMenu_Initialize(menuFrame, L_EasyMenu_Initialize, displayMode, nil, menuList);
L_ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList, nil, autoHideDelay);
end
function L_EasyMenu_Initialize( frame, level, menuList )
for index = 1, getn(menuList) do
local value = menuList[index]
if (value.text) then
value.index = index;
L_UIDropDownMenu_AddButton( value, level );
end
end
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
<!-- $Id: LibUIDropDownMenu.xml 13 2017-05-25 04:26:27Z arith $ -->
<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/
..\FrameXML\UI.xsd">
<Script file="LibUIDropDownMenu.lua"/>
<Include file="LibUIDropDownMenuTemplates.xml"/>
<Script file="LibEasyMenu.lua"/>
<Button name="L_DropDownList1" toplevel="true" frameStrata="FULLSCREEN_DIALOG" inherits="L_UIDropDownListTemplate" hidden="true" id="1">
<Size>
<AbsDimension x="180" y="10"/>
</Size>
<Scripts>
<OnLoad>
local fontName, fontHeight, fontFlags = getglobal("L_DropDownList1Button1NormalText"):GetFont();
L_UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = fontHeight;
tinsert(UIMenus, "L_DropDownList1"); --Allow closing with escape
</OnLoad>
</Scripts>
</Button>
<Button name="L_DropDownList2" toplevel="true" frameStrata="FULLSCREEN_DIALOG" inherits="L_UIDropDownListTemplate" hidden="true" id="2">
<Size>
<AbsDimension x="180" y="10"/>
</Size>
<Scripts>
<OnLoad>
tinsert(UIMenus, "L_DropDownList2"); --Allow closing with escape
</OnLoad>
</Scripts>
</Button>
</Ui>
@@ -0,0 +1,438 @@
<!-- $Id: LibUIDropDownMenuTemplates.xml 19 2017-07-02 13:34:55Z arith $ -->
<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/
..\FrameXML\UI.xsd">
<Button name="L_UIDropDownMenuButtonTemplate" virtual="true">
<Size x="100" y="16"/>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentHighlight" file="Interface\QuestFrame\UI-QuestTitleHighlight" alphaMode="ADD" setAllPoints="true" hidden="true"/>
</Layer>
<Layer level="ARTWORK">
<Texture name="$parentCheck" file="Interface\Buttons\UI-CheckBox-Check">
<Size x="16" y="16"/>
<Anchors>
<Anchor point="LEFT">
<Offset x="0" y="0"/>
</Anchor>
</Anchors>
<TexCoords left="0" right="0.5" top="0.5" bottom="1.0"/>
</Texture>
<Texture name="$parentUnCheck" file="Interface\Buttons\UI-CheckBox-Check">
<Size x="16" y="16"/>
<Anchors>
<Anchor point="LEFT">
<Offset x="0" y="0"/>
</Anchor>
</Anchors>
<TexCoords left="0.5" right="1.0" top="0.5" bottom="1.0"/>
</Texture>
<Texture name="$parentIcon" hidden="true">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="RIGHT">
<Offset x="0" y="0"/>
</Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="$parentColorSwatch" hidden="true">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="RIGHT">
<Offset>
<AbsDimension x="-6" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentSwatchBg">
<Size>
<AbsDimension x="14" y="14"/>
</Size>
<Anchors>
<Anchor point="CENTER">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Color r="1.0" g="1.0" b="1.0"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnClick>
securecall("CloseMenus");
L_UIDropDownMenuButton_OpenColorPicker(this:GetParent());
</OnClick>
<OnEnter>
L_CloseDropDownMenus(this:GetParent():GetParent():GetID() + 1);
getglobal(this:GetName().."SwatchBg"):SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
L_UIDropDownMenu_StopCounting(this:GetParent():GetParent());
</OnEnter>
<OnLeave>
getglobal(this:GetName().."SwatchBg"):SetVertexColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
L_UIDropDownMenu_StartCounting(this:GetParent():GetParent());
</OnLeave>
</Scripts>
<NormalTexture name="$parentNormalTexture" file="Interface\ChatFrame\ChatFrameColorSwatch"/>
</Button>
<Button name="$parentExpandArrow" hidden="true">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="RIGHT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
L_ToggleDropDownMenu(this:GetParent():GetParent():GetID() + 1, this:GetParent().value, nil, nil, nil, nil, this:GetParent().menuList, this);
</OnClick>
<OnEnter>
local level = this:GetParent():GetParent():GetID() + 1;
local listFrame = getglobal("L_DropDownList"..level);
if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= this ) then
L_ToggleDropDownMenu(level, this:GetParent().value, nil, nil, nil, nil, this:GetParent().menuList, this);
end
L_UIDropDownMenu_StopCounting(this:GetParent():GetParent());
</OnEnter>
<OnLeave>
L_UIDropDownMenu_StartCounting(this:GetParent():GetParent());
</OnLeave>
</Scripts>
<NormalTexture file="Interface\ChatFrame\ChatFrameExpandArrow"/>
</Button>
<Button name="$parentInvisibleButton" hidden="true" parentKey="invisibleButton">
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="BOTTOMLEFT"/>
<Anchor point="RIGHT" relativeTo="$parentColorSwatch" relativePoint="LEFT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnEnter>
L_UIDropDownMenu_StopCounting(this:GetParent():GetParent());
L_CloseDropDownMenus(this:GetParent():GetParent():GetID() + 1);
local parent = this:GetParent();
if ( parent.tooltipTitle and parent.tooltipWhileDisabled) then
if ( parent.tooltipOnButton ) then
GameTooltip:SetOwner(parent, "ANCHOR_RIGHT");
GameTooltip:AddLine(parent.tooltipTitle, 1.0, 1.0, 1.0);
GameTooltip:AddLine(parent.tooltipText, nil, nil, nil, true);
GameTooltip:Show();
else
GameTooltip_AddNewbieTip(parent, parent.tooltipTitle, 1.0, 1.0, 1.0, parent.tooltipText, 1);
end
end
</OnEnter>
<OnLeave>
L_UIDropDownMenu_StartCounting(this:GetParent():GetParent());
GameTooltip:Hide();
</OnLeave>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnLoad>
this:SetFrameLevel(this:GetParent():GetFrameLevel()+2);
</OnLoad>
<OnClick>
L_UIDropDownMenuButton_OnClick(this, arg1, arg2);
</OnClick>
<OnEnter>
if ( this.hasArrow ) then
local level = this:GetParent():GetID() + 1;
local listFrame = getglobal("L_DropDownList"..level);
if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= this ) then
L_ToggleDropDownMenu(this:GetParent():GetID() + 1, this.value, nil, nil, nil, nil, this.menuList, this);
end
else
L_CloseDropDownMenus(this:GetParent():GetID() + 1);
end
getglobal(this:GetName().."Highlight"):Show();
L_UIDropDownMenu_StopCounting(this:GetParent());
if ( this.tooltipTitle ) then
if ( this.tooltipOnButton ) then
GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
GameTooltip:AddLine(this.tooltipTitle, 1.0, 1.0, 1.0);
GameTooltip:AddLine(this.tooltipText, nil, nil, nil, true);
GameTooltip:Show();
else
GameTooltip_AddNewbieTip(this, this.tooltipTitle, 1.0, 1.0, 1.0, this.tooltipText, 1);
end
end
</OnEnter>
<OnLeave>
getglobal(this:GetName().."Highlight"):Hide();
L_UIDropDownMenu_StartCounting(this:GetParent());
GameTooltip:Hide();
</OnLeave>
<OnEnable>
this.invisibleButton:Hide();
</OnEnable>
<OnDisable>
this.invisibleButton:Show();
</OnDisable>
</Scripts>
<ButtonText name="$parentNormalText">
<Anchors>
<Anchor point="LEFT">
<Offset x="-5" y="0"/>
</Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="GameFontHighlightSmall" justifyH="LEFT"/>
<HighlightFont inherits="GameFontHighlightSmall" justifyH="LEFT"/>
<DisabledFont inherits="GameFontDisableSmall" justifyH="LEFT"/>
</Button>
<Button name="L_UIDropDownListTemplate" hidden="true" frameStrata="DIALOG" enableMouse="true" virtual="true">
<Frames>
<Frame name="$parentBackdrop" setAllPoints="true">
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background-Dark" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="9"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="32"/>
</TileSize>
<EdgeSize>
<AbsValue val="32"/>
</EdgeSize>
</Backdrop>
</Frame>
<Frame name="$parentMenuBackdrop" setAllPoints="true">
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
<EdgeSize>
<AbsValue val="16"/>
</EdgeSize>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<BackgroundInsets>
<AbsInset left="5" right="5" top="5" bottom="4"/>
</BackgroundInsets>
</Backdrop>
<Scripts>
<OnLoad>
this:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
this:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b);
</OnLoad>
</Scripts>
</Frame>
<Button name="$parentButton1" inherits="L_UIDropDownMenuButtonTemplate" id="1"/>
<Button name="$parentButton2" inherits="L_UIDropDownMenuButtonTemplate" id="2"/>
<Button name="$parentButton3" inherits="L_UIDropDownMenuButtonTemplate" id="3"/>
<Button name="$parentButton4" inherits="L_UIDropDownMenuButtonTemplate" id="4"/>
<Button name="$parentButton5" inherits="L_UIDropDownMenuButtonTemplate" id="5"/>
<Button name="$parentButton6" inherits="L_UIDropDownMenuButtonTemplate" id="6"/>
<Button name="$parentButton7" inherits="L_UIDropDownMenuButtonTemplate" id="7"/>
<Button name="$parentButton8" inherits="L_UIDropDownMenuButtonTemplate" id="8"/>
<Button name="$parentButton9" inherits="L_UIDropDownMenuButtonTemplate" id="9"/>
<Button name="$parentButton10" inherits="L_UIDropDownMenuButtonTemplate" id="10"/>
<Button name="$parentButton11" inherits="L_UIDropDownMenuButtonTemplate" id="11"/>
<Button name="$parentButton12" inherits="L_UIDropDownMenuButtonTemplate" id="12"/>
<Button name="$parentButton13" inherits="L_UIDropDownMenuButtonTemplate" id="13"/>
<Button name="$parentButton14" inherits="L_UIDropDownMenuButtonTemplate" id="14"/>
<Button name="$parentButton15" inherits="L_UIDropDownMenuButtonTemplate" id="15"/>
<Button name="$parentButton16" inherits="L_UIDropDownMenuButtonTemplate" id="16"/>
<Button name="$parentButton17" inherits="L_UIDropDownMenuButtonTemplate" id="17"/>
<Button name="$parentButton18" inherits="L_UIDropDownMenuButtonTemplate" id="18"/>
<Button name="$parentButton19" inherits="L_UIDropDownMenuButtonTemplate" id="19"/>
<Button name="$parentButton20" inherits="L_UIDropDownMenuButtonTemplate" id="20"/>
<Button name="$parentButton21" inherits="L_UIDropDownMenuButtonTemplate" id="21"/>
<Button name="$parentButton22" inherits="L_UIDropDownMenuButtonTemplate" id="22"/>
<Button name="$parentButton23" inherits="L_UIDropDownMenuButtonTemplate" id="23"/>
<Button name="$parentButton24" inherits="L_UIDropDownMenuButtonTemplate" id="24"/>
<Button name="$parentButton25" inherits="L_UIDropDownMenuButtonTemplate" id="25"/>
<Button name="$parentButton26" inherits="L_UIDropDownMenuButtonTemplate" id="26"/>
<Button name="$parentButton27" inherits="L_UIDropDownMenuButtonTemplate" id="27"/>
<Button name="$parentButton28" inherits="L_UIDropDownMenuButtonTemplate" id="28"/>
<Button name="$parentButton29" inherits="L_UIDropDownMenuButtonTemplate" id="29"/>
<Button name="$parentButton30" inherits="L_UIDropDownMenuButtonTemplate" id="30"/>
<Button name="$parentButton31" inherits="L_UIDropDownMenuButtonTemplate" id="31"/>
<Button name="$parentButton32" inherits="L_UIDropDownMenuButtonTemplate" id="32"/>
</Frames>
<Scripts>
<OnClick>
this:Hide();
</OnClick>
<OnEnter>
L_UIDropDownMenu_StopCounting(this, arg1);
</OnEnter>
<OnLeave>
L_UIDropDownMenu_StartCounting(this, arg1);
</OnLeave>
<OnUpdate>
L_UIDropDownMenu_OnUpdate(this, arg1);
</OnUpdate>
<OnShow>
for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do
if (not this.noResize) then
getglobal(this:GetName().."Button"..i):SetWidth(this.maxWidth);
end
end
if (not this.noResize) then
this:SetWidth(this.maxWidth+25);
end
this.showTimer = nil;
if ( this:GetID() > 1 ) then
this.parent = getglobal("L_DropDownList"..(this:GetID() - 1));
end
</OnShow>
<OnHide>
L_UIDropDownMenu_OnHide(this);
</OnHide>
</Scripts>
</Button>
<Frame name="L_UIDropDownMenuTemplate" virtual="true">
<Size>
<AbsDimension x="40" y="32"/>
</Size>
<Layers>
<Layer level="ARTWORK">
<Texture name="$parentLeft" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
<Size>
<AbsDimension x="25" y="64"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="0" y="17"/>
</Offset>
</Anchor>
</Anchors>
<TexCoords left="0" right="0.1953125" top="0" bottom="1"/>
</Texture>
<Texture name="$parentMiddle" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
<Size>
<AbsDimension x="115" y="64"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"/>
</Anchors>
<TexCoords left="0.1953125" right="0.8046875" top="0" bottom="1"/>
</Texture>
<Texture name="$parentRight" file="Interface\Glues\CharacterCreate\CharacterCreate-LabelFrame">
<Size>
<AbsDimension x="25" y="64"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentMiddle" relativePoint="RIGHT"/>
</Anchors>
<TexCoords left="0.8046875" right="1" top="0" bottom="1"/>
</Texture>
<FontString parentKey="Text" name="$parentText" inherits="GameFontHighlightSmall" wordwrap="false" justifyH="RIGHT">
<Size>
<AbsDimension x="0" y="10"/>
</Size>
<Anchors>
<Anchor point="RIGHT" relativeTo="$parentRight">
<Offset>
<AbsDimension x="-43" y="2"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
<Layer level="OVERLAY">
<Texture parentKey="Icon" name="$parentIcon" hidden="true">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="LEFT">
<Offset x="30" y="2"/>
</Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button parentKey="Button" name="$parentButton" motionScriptsWhileDisabled="true" >
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parentRight">
<Offset>
<AbsDimension x="-16" y="-18"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnEnter>
local parent = this:GetParent();
local myscript = parent:GetScript("OnEnter");
if(myscript ~= nil) then
myscript(parent);
end
</OnEnter>
<OnLeave>
local parent = this:GetParent();
local myscript = parent:GetScript("OnLeave");
if(myscript ~= nil) then
myscript(parent);
end
</OnLeave>
<OnClick>
L_ToggleDropDownMenu(nil, nil, this:GetParent());
PlaySound(PlaySoundKitID and "igMainMenuOptionCheckBoxOn" or SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
</OnClick>
</Scripts>
<NormalTexture name="$parentNormalTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Up">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="RIGHT"/>
</Anchors>
</NormalTexture>
<PushedTexture name="$parentPushedTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Down">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="RIGHT"/>
</Anchors>
</PushedTexture>
<DisabledTexture name="$parentDisabledTexture" file="Interface\ChatFrame\UI-ChatIcon-ScrollDown-Disabled">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="RIGHT"/>
</Anchors>
</DisabledTexture>
<HighlightTexture name="$parentHighlightTexture" file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="RIGHT"/>
</Anchors>
</HighlightTexture>
</Button>
</Frames>
<Scripts>
<OnHide>
L_CloseDropDownMenus();
</OnHide>
</Scripts>
</Frame>
</Ui>
@@ -0,0 +1,25 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Include file="LibStub\LibStub.xml"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="AceCore-3.0\AceCore-3.0.xml"/>
<Include file="AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="AceDB-3.0\AceDB-3.0.xml"/>
<Include file="AceLocale-3.0\AceLocale-3.0.xml"/>
<Include file="AceComm-3.0\AceComm-3.0.xml"/>
<Include file="AceSerializer-3.0\AceSerializer-3.0.xml"/>
<Include file="AceTimer-3.0\AceTimer-3.0.xml"/>
<Include file="AceHook-3.0\AceHook-3.0.xml"/>
<Include file="LibSharedMedia-3.0\LibSharedMedia-3.0.xml"/>
<Include file="LibSimpleSticky\LibSimpleSticky.xml"/>
<Include file="LibDataBroker\LibDataBroker-1.1.xml"/>
<Include file="LibElvUIPlugin-1.0\LibElvUIPlugin-1.0.xml"/>
<!--
<Include file="UTF8\UTF8.xml"/>
<Include file="LibCompress\LibCompress.xml"/>
<Include file="LibBase64-1.0\LibBase64-1.0.xml"/>
-->
<Include file="LibAnim\LibAnim.xml"/>
<Include file="LibUIDropDownMenu\LibUIDropDownMenu.xml"/>
</Ui>
@@ -0,0 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="utf8.lua"/>
<Script file="utf8data.lua"/>
</Ui>
+318
View File
@@ -0,0 +1,318 @@
-- $Id: utf8.lua 179 2009-04-03 18:10:03Z pasta $
--
-- Provides UTF-8 aware string functions implemented in pure lua:
-- * string.utf8len(s)
-- * string.utf8sub(s, i, j)
-- * string.utf8reverse(s)
--
-- If utf8data.lua (containing the lower<->upper case mappings) is loaded, these
-- additional functions are available:
-- * string.utf8upper(s)
-- * string.utf8lower(s)
--
-- All functions behave as their non UTF-8 aware counterparts with the exception
-- that UTF-8 characters are used instead of bytes for all units.
--[[
Copyright (c) 2006-2007, Kyle Smith
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--]]
-- ABNF from RFC 3629
--
-- UTF8-octets = *( UTF8-char )
-- UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
-- UTF8-1 = %x00-7F
-- UTF8-2 = %xC2-DF UTF8-tail
-- UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
-- %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
-- UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
-- %xF4 %x80-8F 2( UTF8-tail )
-- UTF8-tail = %x80-BF
--
local strbyte, strlen, strsub, type = string.byte, string.len, string.sub, type
-- returns the number of bytes used by the UTF-8 character at byte i in s
-- also doubles as a UTF-8 character validator
local function utf8charbytes(s, i)
-- argument defaults
i = i or 1
-- argument checking
if type(s) ~= "string" then
error("bad argument #1 to 'utf8charbytes' (string expected, got ".. type(s).. ")")
end
if type(i) ~= "number" then
error("bad argument #2 to 'utf8charbytes' (number expected, got ".. type(i).. ")")
end
local c = strbyte(s, i)
-- determine bytes needed for character, based on RFC 3629
-- validate byte 1
if c > 0 and c <= 127 then
-- UTF8-1
return 1
elseif c >= 194 and c <= 223 then
-- UTF8-2
local c2 = strbyte(s, i + 1)
if not c2 then
error("UTF-8 string terminated early")
end
-- validate byte 2
if c2 < 128 or c2 > 191 then
error("Invalid UTF-8 character")
end
return 2
elseif c >= 224 and c <= 239 then
-- UTF8-3
local c2 = strbyte(s, i + 1)
local c3 = strbyte(s, i + 2)
if not c2 or not c3 then
error("UTF-8 string terminated early")
end
-- validate byte 2
if c == 224 and (c2 < 160 or c2 > 191) then
error("Invalid UTF-8 character")
elseif c == 237 and (c2 < 128 or c2 > 159) then
error("Invalid UTF-8 character")
elseif c2 < 128 or c2 > 191 then
error("Invalid UTF-8 character")
end
-- validate byte 3
if c3 < 128 or c3 > 191 then
error("Invalid UTF-8 character")
end
return 3
elseif c >= 240 and c <= 244 then
-- UTF8-4
local c2 = strbyte(s, i + 1)
local c3 = strbyte(s, i + 2)
local c4 = strbyte(s, i + 3)
if not c2 or not c3 or not c4 then
error("UTF-8 string terminated early")
end
-- validate byte 2
if c == 240 and (c2 < 144 or c2 > 191) then
error("Invalid UTF-8 character")
elseif c == 244 and (c2 < 128 or c2 > 143) then
error("Invalid UTF-8 character")
elseif c2 < 128 or c2 > 191 then
error("Invalid UTF-8 character")
end
-- validate byte 3
if c3 < 128 or c3 > 191 then
error("Invalid UTF-8 character")
end
-- validate byte 4
if c4 < 128 or c4 > 191 then
error("Invalid UTF-8 character")
end
return 4
else
error("Invalid UTF-8 character")
end
end
-- returns the number of characters in a UTF-8 string
local function utf8len(s)
-- argument checking
if type(s) ~= "string" then
error("bad argument #1 to 'utf8len' (string expected, got ".. type(s).. ")")
end
local pos = 1
local bytes = strlen(s)
local len = 0
while pos <= bytes do
len = len + 1
pos = pos + utf8charbytes(s, pos)
end
return len
end
-- install in the string library
if not string.utf8len then
string.utf8len = utf8len
end
-- functions identically to string.sub except that i and j are UTF-8 characters
-- instead of bytes
local function utf8sub(s, i, j)
-- argument defaults
j = j or -1
-- argument checking
if type(s) ~= "string" then
error("bad argument #1 to 'utf8sub' (string expected, got ".. type(s).. ")")
end
if type(i) ~= "number" then
error("bad argument #2 to 'utf8sub' (number expected, got ".. type(i).. ")")
end
if type(j) ~= "number" then
error("bad argument #3 to 'utf8sub' (number expected, got ".. type(j).. ")")
end
local pos = 1
local bytes = strlen(s)
local len = 0
-- only set l if i or j is negative
local l = (i >= 0 and j >= 0) or utf8len(s)
local startChar = (i >= 0) and i or l + i + 1
local endChar = (j >= 0) and j or l + j + 1
-- can't have start before end!
if startChar > endChar then
return ""
end
-- byte offsets to pass to string.sub
local startByte, endByte = 1, bytes
while pos <= bytes do
len = len + 1
if len == startChar then
startByte = pos
end
pos = pos + utf8charbytes(s, pos)
if len == endChar then
endByte = pos - 1
break
end
end
return strsub(s, startByte, endByte)
end
-- install in the string library
if not string.utf8sub then
string.utf8sub = utf8sub
end
-- replace UTF-8 characters based on a mapping table
local function utf8replace(s, mapping)
-- argument checking
if type(s) ~= "string" then
error("bad argument #1 to 'utf8replace' (string expected, got ".. type(s).. ")")
end
if type(mapping) ~= "table" then
error("bad argument #2 to 'utf8replace' (table expected, got ".. type(mapping).. ")")
end
local pos = 1
local bytes = strlen(s)
local charbytes
local newstr = ""
while pos <= bytes do
charbytes = utf8charbytes(s, pos)
local c = strsub(s, pos, pos + charbytes - 1)
newstr = newstr .. (mapping[c] or c)
pos = pos + charbytes
end
return newstr
end
-- identical to string.upper except it knows about unicode simple case conversions
local function utf8upper(s)
return utf8replace(s, utf8_lc_uc)
end
-- install in the string library
if not string.utf8upper and utf8_lc_uc then
string.utf8upper = utf8upper
end
-- identical to string.lower except it knows about unicode simple case conversions
local function utf8lower(s)
return utf8replace(s, utf8_uc_lc)
end
-- install in the string library
if not string.utf8lower and utf8_uc_lc then
string.utf8lower = utf8lower
end
-- identical to string.reverse except that it supports UTF-8
local function utf8reverse(s)
-- argument checking
if type(s) ~= "string" then
error("bad argument #1 to 'utf8reverse' (string expected, got ".. type(s).. ")")
end
local bytes = strlen(s)
local pos = bytes
local charbytes
local newstr = ""
local c
while pos > 0 do
c = strbyte(s, pos)
while c >= 128 and c <= 191 do
pos = pos - 1
c = strbyte(pos)
end
charbytes = utf8charbytes(s, pos)
newstr = newstr .. strsub(s, pos, pos + charbytes - 1)
pos = pos - 1
end
return newstr
end
-- install in the string library
if not string.utf8reverse then
string.utf8reverse = utf8reverse
end
File diff suppressed because it is too large Load Diff
+346
View File
@@ -0,0 +1,346 @@
-- Chinese localization file for zhCN.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "zhCN")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "插件 %s 不相容于 ElvUI 的 %s 模组, 请停用不相容的插件, 或停用模组."
--*_MSG locales
L["LOGIN_MSG"] = "欢迎使用 %sElvUI|r %s%s|r 版, 请输入/ec进入设定介面. 如需技术支持,请至至 https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "绑定"
L["Key"] = ""
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "无绑定设定"
L["Remove Bar %d Action Page"] = "移除第%d动作条"
L["Trigger"] = "触发器"
--Bags
L["Bank"] = "银行"
L["Hold Control + Right Click:"] = "按住 Ctrl 并按鼠标右键:"
L["Hold Shift + Drag:"] = "按住 Shift 并拖动:"
L["Purchase Bags"] = "购买背包"
L["Reset Position"] = "重设位置"
L["Sort Bags"] = "背包整理"
L["Temporary Move"] = "移动背包"
L["Toggle Bags"] = "背包开关"
L["Toggle Key"] = true;
L["Vendor Grays"] = "出售灰色物品"
--Chat
L["AFK"] = "离开" --Also used in datatexts and tooltip
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "忙碌" --Also used in datatexts and tooltip
L["G"] = "公会"
L["Invalid Target"] = "无效的目标"
L["O"] = "干部"
L["P"] = "队伍"
L["PL"] = "队长"
L["R"] = "团队"
L["RL"] = "团队队长"
L["RW"] = "团队警告"
L["says"] = ""
L["whispers"] = "密语"
L["yells"] = "大喊"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(按住Shift) 内存占用"
L["Avoidance Breakdown"] = "免伤统计"
L["Character: "] = "角色: "
L["Chest"] = ""
L["Combat"] = "战斗"
L["Combat Time"] = true;
L["Coords"] = "坐标"
L["copperabbrev"] = "|cffeda55f铜|r"
L["Deficit:"] = "赤字:"
L["DPS"] = "伤害输出"
L["Earned:"] = "赚取:"
L["Friends List"] = "好友列表"
L["Friends"] = "好友" --Also in Skins
L["Gold"] = ""
L["goldabbrev"] = "|cffffd700金|r"
L["Hit"] = "命中"
L["Hold Shift + Right Click:"] = "按住Shift + 右键点击"
L["Home Latency:"] = "本机延迟:"
L["HP"] = "生命值"
L["HPS"] = "治疗输出"
L["lvl"] = "等级"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "等级减伤: "
L["No Guild"] = "没有公会"
L["Profit:"] = "利润:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "重置数据: 按住 Shift + 右键点击"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "已有进度的副本"
L["Server: "] = "服务器: "
L["Session:"] = "本次登陆:"
L["silverabbrev"] = "|cffc7c7cf银|r"
L["SP"] = "法术强度"
L["Spell/Heal Power"] = "法术/治疗强度"
L["Spent:"] = "花费:"
L["Stats For:"] = "统计:"
L["System"] = "系统信息"
L["Total CPU:"] = "CPU占用"
L["Total Memory:"] = "总内存:"
L["Total: "] = "合计: "
L["Unhittable:"] = "未命中:"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s 尝试调用保护函数 '%s'."
L["No locals to dump"] = "没有本地文件"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 试图与你分享过滤器配置. 你是否接受?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 试图与你分享配置文件 %s. 你是否接受?"
L["Data From: %s"] = "数据来源: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "过滤器配置下载于 %s, 你是否现在变更?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "天啊! 太奇葩了! 下载消失了! 就像在风中放了一个屁... 再试一次吧!"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "配置文件从 %s 下载完成, 但是配置文件 %s 已存在. 请更改名称, 否则它会覆盖你的现有配置文件."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "配置文件从 %s 下载完成, 你是否加载配置文件 %s?"
L["Profile request sent. Waiting for response from player."] = "已发送文件请求. 等待对方响应."
L["Request was denied by user."] = "请求被对方拒绝."
L["Your profile was successfully recieved by the player."] = "你的配置文件已被其他玩家成功接收."
--Install
L["Aura Bars & Icons"] = "光环条与图标"
L["Auras Set"] = "光环样式设置"
L["Auras"] = "光环"
L["Caster DPS"] = "法系输出"
L["Chat Set"] = "对话设定"
L["Chat"] = "聊天框"
L["Choose a theme layout you wish to use for your initial setup."] = "为你的个人设置选择一个你喜欢的皮肤主题."
L["Classic"] = "经典"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "点击下面的按钮调整聊天框、单位框架的尺寸, 以及移动动作条位置"
L["Config Mode:"] = "设置模式:"
L["CVars Set"] = "参数设定"
L["CVars"] = "参数"
L["Dark"] = "黑暗"
L["Disable"] = "禁用"
L["ElvUI Installation"] = "安装 ElvUI"
L["Finished"] = "完成"
L["Grid Size:"] = "网格尺寸:"
L["Healer"] = "治疗"
L["High Resolution"] = "高分辨率"
L["high"] = ""
L["Icons Only"] = "图标"
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "如果你有不想显示的图标或光环条, 你可以简单的通过按住Shift右键点击使它隐藏."
L["Importance: |cff07D400High|r"] = "重要度: |cff07D400高|r"
L["Importance: |cffD3CF00Medium|r"] = "重要性: |cffD3CF00中|r"
L["Importance: |cffFF0000Low|r"] = "重要性:|cffFF0000低|r"
L["Installation Complete"] = "安装完成"
L["Layout Set"] = "界面布局设置"
L["Layout"] = "界面布局"
L["Lock"] = "锁定"
L["Low Resolution"] = "低分辨率"
L["low"] = ""
L["Nudge"] = "微调"
L["Physical DPS"] = "物理输出"
L["Please click the button below so you can setup variables and ReloadUI."] = "请按下方按钮设定变数并重载介面."
L["Please click the button below to setup your CVars."] = "请按下方按钮设定参数."
L["Please press the continue button to go onto the next step."] = "请按继续按钮到下一步"
L["Resolution Style Set"] = "分辨率样式设置"
L["Resolution"] = "分辨率"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "选择你想要在ElvUI的单位框体里使用何种光环系统. 选择光环条和图标将同时使用光环条和图标, 选择图标来仅仅显示图标."
L["Setup Chat"] = "设定聊天框"
L["Setup CVars"] = "设定参数"
L["Skip Process"] = "略过"
L["Sticky Frames"] = "框架依附"
L["Tank"] = "坦克"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "对话窗口与 WOW 原始对话窗口的操作方式相同, 你可以拖拉、移动分页或重新命名分页.请按下方按钮以设定对话窗口."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "若要进入内建设定选单, 请输入 /ec, 或者按一下小地图旁的 C 按钮.若要略过安装程序, 请按下方按钮."
L["Theme Set"] = "主题设置"
L["Theme Setup"] = "主题安装"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "此安装程序有助你了解 ElvUI 部份功能, 并可协助你预先设定 UI."
L["This is completely optional."] = "这是可选项."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "此安装步骤将会设定聊天框的名称、位置和颜色."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "此安装步骤将会设定 WOW 预设选项, 建议你执行此步骤, 以确保功能均可正常运作."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "这个分辨率不需要你改动任何设置以适应你的屏幕."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "这个分辨率需要你改变一些设置才能适应你的屏幕."
L["This will change the layout of your unitframes and actionbars."] = "这将会改变你单位框架和动作条的构架."
L["Trade"] = "拾取/交易"
L["Welcome to ElvUI version %s!"] = "欢迎使用 ElvUI 版本 %s!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "你已经完成安装过程. 如果你需要技术支持请访问 https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "你可以在游戏内的设定选项内更改ElvUI的字体、颜色等设定."
L["You can now choose what layout you wish to use based on your combat role."] = "你现在可以根据你的战斗角色选择合适的布局."
L["You may need to further alter these settings depending how low you resolution is."] = "根据你的分辨率你可能需要改动这些设置."
L["Your current resolution is %s, this is considered a %s resolution."] = "你当前的分辨率是 %s, 这被认为是个 %s 分辨率."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 以上 |cff%02x%02x%02x%s|r]"
L["Bars"] = ""
L["Calendar"] = "日历"
L["Can't Roll"] = "无法需求此装备"
L["Disband Group"] = "解散队伍"
L["Empty Slot"] = "空拾取位"
L["Enable"] = "启用"
L["Experience"] = "经验/声望条"
L["Farm Mode"] = true;
L["Fishy Loot"] = "贪婪"
L["Left Click:"] = "鼠标左键:"
L["Raid Menu"] = "团队菜单"
L["Remaining:"] = "剩余:"
L["Rested:"] = "休息:"
L["Right Click:"] = "鼠标右键:"
L["Show BG Texts"] = "显示战场资讯文字"
L["Toggle Chat Frame"] = "开关聊天框架"
L["Toggle Configuration"] = "设置开关"
L["XP:"] = "经验:"
L["You don't have permission to mark targets."] = "你没有标记目标的权限"
--Movers
L["Arena Frames"] = "竞技场框架"
L["Bag Mover (Grow Down)"] = "背包框架(向下)"
L["Bag Mover (Grow Up)"] = "背包框架(向上)"
L["Bag Mover"] = "背包框架"
L["Bags"] = "背包" --Also in DataTexts
L["Bank Mover (Grow Down)"] = "银行框架(向下)"
L["Bank Mover (Grow Up)"] = "银行框架(向上)"
L["Bar "] = "动作条 " --Also in ActionBars
L["BNet Frame"] = "战网提示信息"
L["Boss Frames"] = "首领框架"
L["Classbar"] = "职业特有条"
L["Experience Bar"] = "经验条"
L["Focus Castbar"] = "焦点目标施法条"
L["Focus Frame"] = "焦点目标框架"
L["FocusTarget Frame"] = "焦点目标的目标框架"
L["GM Ticket Frame"] = "GM对话框"
L["Left Chat"] = "左侧对话框"
L["Loot / Alert Frames"] = "拾取/提醒框"
L["Loot Frame"] = "拾取框架"
L["MA Frames"] = "主助理框"
L["Micro Bar"] = "微型系统菜单" --Also in ActionBars
L["Minimap"] = "小地图"
L["MirrorTimer"] = "镜像计时器"
L["MT Frames"] = "主坦克框"
L["Party Frames"] = "队伍框架"
L["Pet Bar"] = "宠物动作条" --Also in ActionBars
L["Pet Castbar"] = "宠物施法条"
L["Pet Frame"] = "宠物框架"
L["PetTarget Frame"] = "宠物目标框架"
L["Player Buffs"] = "玩家增益"
L["Player Castbar"] = "玩家施法条"
L["Player Debuffs"] = "玩家减益"
L["Player Frame"] = "玩家框架"
L["Player Powerbar"] = "玩家能量条"
L["PvP"] = true;
L["Raid Frames"] = "团队框架"
L["Raid Pet Frames"] = "团队宠物框架"
L["Raid-40 Frames"] = "40人团队框架"
L["Reputation Bar"] = "声望条"
L["Right Chat"] = "右侧对话框"
L["Stance Bar"] = "姿态条" --Also in ActionBars
L["Target Castbar"] = "目标施法条"
L["Target Frame"] = "目标框架"
L["Target Powerbar"] = "目标能量条"
L["TargetTarget Frame"] = "目标的目标框架"
L["TargetTargetTarget Frame"] = "目标的目标的目标框架"
L["Time Manager Frame"] = true;
L["Tooltip"] = "鼠标提示"
L["Vehicle Seat Frame"] = "载具座位框"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = "ElvUI插件安装"
L["In Progress"] = "正在进行中"
L["List of installations in queue:"] = "即将安装的列表:"
L["Pending"] = "等待中"
L["Steps"] = "步骤"
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00绑定到 |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s 个框架锚点冲突, 请移动buff或者debuff锚点让他们彼此不依附.暂时强制debuff依附到主框架."
L["All keybindings cleared for |cff00ff00%s|r."] = "取消 |cff00ff00%s|r 所有绑定的快捷键."
L["Already Running.. Bailing Out!"] = "正在运行!"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "战场信息暂时隐藏, 你可以通过输入/bgstats 或右键点击小地图旁「C」按钮显示."
L["Battleground datatexts will now show again if you are inside a battleground."] = "当你处于战场时战场信息将再次显示."
L["Binds Discarded"] = "取消绑定"
L["Binds Saved"] = "储存绑定"
L["Confused.. Try Again!"] = "请再试一次!"
L["No gray items to delete."] = "没有要删除的灰色物品"
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "法术'%s'已经被添加到单位框架的光环过滤器中."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "这个设置引起一个互相矛盾的锚点, '%s' 被依附于他自身. 请检查你的锚点设置. 设置 '%s' 依附到 '%s'."
L["Vendored gray items for:"] = "已出售灰色物品:"
L["You don't have enough money to repair."] = "没有足够的资金来修复."
L["You must be at a vendor."] = "你必需以商人为目标."
L["Your items have been repaired for: "] = "装备已修复: "
L["Your items have been repaired using guild bank funds for: "] = "物品已使用公会银行资金修复: "
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000LUA错误已接收, 你可以在脱离战斗后检查.|r"
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "你所做的改动只会影响到使用这个插件的本角色, 你需要重新加载界面才能使改动生效."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = "确定要对所有ElvUI元素使用这个字体?"
L["Are you sure you want to delete all your gray items?"] = "确定需要摧毁你的灰色物品?"
L["Are you sure you want to disband the group?"] = "确定要解散队伍?"
L["Are you sure you want to reset all the settings on this profile?"] = "确定需要重置这个配置文件中的所有设置?"
L["Are you sure you want to reset every mover back to it's default position?"] = "确定需要重置所有框架至默认位置?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "由于大量的改动导致光环系统需要一个新的安装过程. 这是可选的, 最后一步将设置你的光环样式. 点击「完成」将不再提示. 如果由于某些原因反复提示, 请重新开启游戏."
L["Can't buy anymore slots!"] = "银行背包栏位已达最大值"
L["Disable Warning"] = "停用警告"
L["Discard"] = "取消"
L["Do you enjoy the new ElvUI?"] = "你喜欢新的ElvUI么?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "你发誓在你没停用其他插件前不会到技术支持询问某些功能失效吗?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI已过期5个或者更多的版本。你可以在 https://github.com/ElvUI-WotLK/ElvUI/ 下载到最新的版本"
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = true;
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI需要进行数据库优化, 请耐性等待."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "移动鼠标到动作条或技能书按钮上绑定快捷键. 按ESC或鼠标右键取消目前快捷键"
L["I Swear"] = "我承诺"
L["No, Revert Changes!"] = "不, 撤销修改!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "你不能同时使用Elvui和Tukui, 请选择一个禁用."
L["One or more of the changes you have made require a ReloadUI."] = "已变更一或多个设定, 需重载界面."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "你所做的改动可能会影响到使用这个插件的所有角色, 你需要重新加载界面才能使改动生效."
L["Save"] = "储存"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "你尝试导入的配置文件已经存在.请选择一个新的名字或者确认覆盖存在的配置文件."
L["Type /hellokitty to revert to old settings."] = "输入/hellokitty以撤销到原来的设定"
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "使用治疗布局时建议你下载 Clique 插件,从而拥有点击施法功能"
L["Yes, Keep Changes!"] = "是的, 保存修改!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "你选择了细边框主题选项,你必须完成安装程序来移除任何图像错误"
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "你改变了界面缩放比例, 然而ElvUI的自动缩放选项是开启的.点击接受以关闭ElvUI的自动缩放."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "你导入的设置可能需要重载界面才能生效.确认重载?"
L["You must purchase a bank slot first!"] = "你必需购买一个银行背包栏位"
--Tooltip
L["Count"] = "计数"
L["Item Level:"] = "物品等级:"
L["Talent Specialization:"] = "天赋专精:"
L["Targeted By:"] = "同目标的有:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "你可以通过按ESC键 -> 按键设置, 滚动到ElvUI设置下方设置一个快速标记的快捷键."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI可以根据你所使用的天赋自动套用不同的设置档. 你可以在配置文件中使用此功能."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "如需技术支援请至 https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "如果你不慎移除了对话框, 你可以重新安装一次重置他们."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "如果你遇到问题, ElvUI会尝试禁用你除了ElvUI之外的插件. 请记住你不能用不同的插件实现同一功能."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "你可以通过 /focus 命令设置焦点目标."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "你可以通过按住Shift拖动技能条中的按键. 你可以在 Blizzard 的动作条设置中更改按键."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "你可以通过右键点击对话框标签栏设置你需要在对话框内显示的频道."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "你可以通过鼠标滑过对话框右上角点击复制图标打开对话复制窗口."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "你可以通过按住Shift并将鼠标滑过目标看到目标的装备等级, 这将显示在你的鼠标提示框内."
L["You can set your keybinds quickly by typing /kb."] = "你可以通过输入 /kb 快速绑定按键."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "你可以通过鼠标中键点击小地图或在动作条设置内选择打开微型系统栏."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "使用 /resetui 命令可以重置你的所有框架位置. 你也可以通过命令 /resetui <框架名称> 单独重置某个框架.\n例如: /resetui Player Frame"
--UnitFrames
L["Dead"] = "死亡"
L["Ghost"] = "鬼魂"
L["Offline"] = "离线"
+346
View File
@@ -0,0 +1,346 @@
-- English localization file for enUS and enGB.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
local L = AceLocale:NewLocale("ElvUI", "enUS", true, true);
if not L then return; end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
--*_MSG locales
L["LOGIN_MSG"] = "Welcome to %sElvUI|r version %s%s|r, type /ec to access the in-game configuration menu. If you are in need of technical support you can visit us at https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = true;
L["Key"] = true;
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = true;
L["Remove Bar %d Action Page"] = true;
L["Trigger"] = true;
--Bags
L["Bank"] = true;
L["Hold Control + Right Click:"] = true;
L["Hold Shift + Drag:"] = true;
L["Purchase Bags"] = true;
L["Reset Position"] = true;
L["Sort Bags"] = true;
L["Temporary Move"] = true;
L["Toggle Bags"] = true;
L["Toggle Key"] = true;
L["Vendor Grays"] = true;
--Chat
L["AFK"] = true; --Also used in datatexts
L["BG"] = true;
L["BGL"] = true;
L["DND"] = true; --Also used in datatexts
L["G"] = true;
L["Invalid Target"] = true;
L["O"] = true;
L["P"] = true;
L["PL"] = true;
L["R"] = true;
L["RL"] = true;
L["RW"] = true;
L["says"] = true;
L["whispers"] = true;
L["yells"] = true;
--DataTexts
L["(Hold Shift) Memory Usage"] = true;
L["Avoidance Breakdown"] = true;
L["Character: "] = true;
L["Chest"] = true;
L["Combat"] = true;
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
L["Deficit:"] = true;
L["DPS"] = true;
L["Earned:"] = true;
L["Friends List"] = true;
L["Friends"] = true; --Also in Skins
L["Gold"] = true;
L["goldabbrev"] = "|cffffd700g|r" --Also used in Bags
L["Hit"] = true;
L["Hold Shift + Right Click:"] = true;
L["Home Latency:"] = true;
L["HP"] = true;
L["HPS"] = true;
L["lvl"] = true;
L["Miss Chance"] = true;
L["Mitigation By Level: "] = true;
L["No Guild"] = true;
L["Profit:"] = true;
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = true;
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = true;
L["Server: "] = true;
L["Session:"] = true;
L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
L["SP"] = true;
L["Spell/Heal Power"] = true;
L["Spent:"] = true;
L["Stats For:"] = true;
L["System"] = true;
L["Total CPU:"] = true;
L["Total Memory:"] = true;
L["Total: "] = true;
L["Unhittable:"] = true;
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = true;
L["No locals to dump"] = true;
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = true;
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = true;
L["Data From: %s"] = true;
L["Filter download complete from %s, would you like to apply changes now?"] = true;
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = true;
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = true;
L["Profile download complete from %s, would you like to load the profile %s now?"] = true;
L["Profile request sent. Waiting for response from player."] = true;
L["Request was denied by user."] = true;
L["Your profile was successfully recieved by the player."] = true;
--Install
L["Aura Bars & Icons"] = true;
L["Auras Set"] = true;
L["Auras"] = true;
L["Caster DPS"] = true;
L["Chat Set"] = true;
L["Chat"] = true;
L["Choose a theme layout you wish to use for your initial setup."] = true;
L["Classic"] = true;
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = true;
L["Config Mode:"] = true;
L["CVars Set"] = true;
L["CVars"] = true;
L["Dark"] = true;
L["Disable"] = true;
L["ElvUI Installation"] = true;
L["Finished"] = true;
L["Grid Size:"] = true;
L["Healer"] = true;
L["High Resolution"] = true;
L["high"] = true;
L["Icons Only"] = true; --Also used in Bags
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = true;
L["Importance: |cff07D400High|r"] = true;
L["Importance: |cffD3CF00Medium|r"] = true;
L["Importance: |cffFF0000Low|r"] = true;
L["Installation Complete"] = true;
L["Layout Set"] = true;
L["Layout"] = true;
L["Lock"] = true;
L["Low Resolution"] = true;
L["low"] = true;
L["Nudge"] = true;
L["Physical DPS"] = true;
L["Please click the button below so you can setup variables and ReloadUI."] = true;
L["Please click the button below to setup your CVars."] = true;
L["Please press the continue button to go onto the next step."] = true;
L["Resolution Style Set"] = true;
L["Resolution"] = true;
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = true;
L["Setup Chat"] = true;
L["Setup CVars"] = true;
L["Skip Process"] = true;
L["Sticky Frames"] = true;
L["Tank"] = true;
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = true;
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = true;
L["Theme Set"] = true;
L["Theme Setup"] = true;
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = true;
L["This is completely optional."] = true;
L["This part of the installation process sets up your chat windows names, positions and colors."] = true;
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = true;
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = true;
L["This resolution requires that you change some settings to get everything to fit on your screen."] = true;
L["This will change the layout of your unitframes and actionbars."] = true;
L["Trade"] = true;
L["Welcome to ElvUI version %s!"] = true;
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = true;
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = true;
L["You can now choose what layout you wish to use based on your combat role."] = true;
L["You may need to further alter these settings depending how low you resolution is."] = true;
L["Your current resolution is %s, this is considered a %s resolution."] = true;
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
L["Bars"] = true; --Also used in UnitFrames
L["Calendar"] = true;
L["Can't Roll"] = true;
L["Disband Group"] = true;
L["Empty Slot"] = true;
L["Enable"] = true; --Doesn't fit a section since it's used a lot of places
L["Experience"] = true;
L["Farm Mode"] = true;
L["Fishy Loot"] = true;
L["Left Click:"] = true; --layout\layout.lua
L["Raid Menu"] = true;
L["Remaining:"] = true;
L["Rested:"] = true;
L["Right Click:"] = true; --layout\layout.lua
L["Show BG Texts"] = true; --layout\layout.lua
L["Toggle Chat Frame"] = true; --layout\layout.lua
L["Toggle Configuration"] = true; --layout\layout.lua
L["XP:"] = true;
L["You don't have permission to mark targets."] = true;
--Movers
L["Arena Frames"] = true; --Also used in UnitFrames
L["Bag Mover (Grow Down)"] = true;
L["Bag Mover (Grow Up)"] = true;
L["Bag Mover"] = true;
L["Bags"] = true; --Also in DataTexts
L["Bank Mover (Grow Down)"] = true;
L["Bank Mover (Grow Up)"] = true;
L["Bar "] = true; --Also in ActionBars
L["BNet Frame"] = true;
L["Boss Frames"] = true; --Also used in UnitFrames
L["Classbar"] = true; --Also used in UnitFrames
L["Experience Bar"] = true;
L["Focus Castbar"] = true;
L["Focus Frame"] = true; --Also used in UnitFrames
L["FocusTarget Frame"] = true; --Also used in UnitFrames
L["GM Ticket Frame"] = true;
L["Left Chat"] = true;
L["Loot / Alert Frames"] = true;
L["Loot Frame"] = true;
L["MA Frames"] = true;
L["Micro Bar"] = true; --Also in ActionBars
L["Minimap"] = true;
L["MirrorTimer"] = true;
L["MT Frames"] = true;
L["Party Frames"] = true; --Also used in UnitFrames
L["Pet Bar"] = true; --Also in ActionBars
L["Pet Castbar"] = true;
L["Pet Frame"] = true; --Also used in UnitFrames
L["PetTarget Frame"] = true; --Also used in UnitFrames
L["Player Buffs"] = true;
L["Player Castbar"] = true;
L["Player Debuffs"] = true;
L["Player Frame"] = true; --Also used in UnitFrames
L["Player Powerbar"] = true;
L["PvP"] = true;
L["Raid Frames"] = true;
L["Raid Pet Frames"] = true;
L["Raid-40 Frames"] = true;
L["Reputation Bar"] = true;
L["Right Chat"] = true;
L["Stance Bar"] = true; --Also in ActionBars
L["Target Castbar"] = true;
L["Target Frame"] = true; --Also used in UnitFrames
L["Target Powerbar"] = true;
L["TargetTarget Frame"] = true; --Also used in UnitFrames
L["TargetTargetTarget Frame"] = true; --Also used in UnitFrames
L["Time Manager Frame"] = true;
L["Tooltip"] = true;
L["Vehicle Seat Frame"] = true;
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = true;
L["In Progress"] = true;
L["List of installations in queue:"] = true;
L["Pending"] = true;
L["Steps"] = true;
--Prints
L[" |cff00ff00bound to |r"] = true;
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = true;
L["All keybindings cleared for |cff00ff00%s|r."] = true;
L["Already Running.. Bailing Out!"] = true;
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = true;
L["Battleground datatexts will now show again if you are inside a battleground."] = true;
L["Binds Discarded"] = true;
L["Binds Saved"] = true;
L["Confused.. Try Again!"] = true;
L["No gray items to delete."] = true;
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = true;
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
L["Vendored gray items for:"] = true;
L["You don't have enough money to repair."] = true;
L["You must be at a vendor."] = true;
L["Your items have been repaired for: "] = true;
L["Your items have been repaired using guild bank funds for: "] = true;
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = true;
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = true;
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
L["Are you sure you want to delete all your gray items?"] = true;
L["Are you sure you want to disband the group?"] = true;
L["Are you sure you want to reset all the settings on this profile?"] = true;
L["Are you sure you want to reset every mover back to it's default position?"] = true;
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = true;
L["Can't buy anymore slots!"] = true;
L["Disable Warning"] = true;
L["Discard"] = true;
L["Do you enjoy the new ElvUI?"] = true;
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = true;
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = true;
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = true;
L["ElvUI needs to perform database optimizations please be patient."] = true;
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = true;
L["I Swear"] = true;
L["No, Revert Changes!"] = true;
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = true;
L["One or more of the changes you have made require a ReloadUI."] = true;
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = true;
L["Save"] = true;
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
L["Type /hellokitty to revert to old settings."] = true;
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = true;
L["Yes, Keep Changes!"] = true;
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = true;
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
L["You must purchase a bank slot first!"] = true;
--Tooltip
L["Count"] = true;
L["Item Level:"] = true;
L["Talent Specialization:"] = true;
L["Targeted By:"] = true;
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = true;
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = true;
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = true;
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = true;
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = true;
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = true;
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = true;
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = true;
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = true;
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = true;
L["You can set your keybinds quickly by typing /kb."] = true;
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = true;
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = true;
--UnitFrames
L["Dead"] = true;
L["Ghost"] = true;
L["Offline"] = true;
+346
View File
@@ -0,0 +1,346 @@
-- French localization file for frFR.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0");
local L = AceLocale:NewLocale("ElvUI", "frFR");
if not L then return; end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "L'addon %s n'est pas compatible avec le module %s d'ElvUI. Merci de sélectionner soit l'addon ou le module d'ElvUI pour le désactiver."
--*_MSG locales
L["LOGIN_MSG"] = "Bienvenue sur %sElvUI|r version %s%s|r, tapez /ec afin d'accéder au menu de configuration en jeu. Si vous avez besoin d'un support technique, vous pouvez nous rejoindre sur https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "Raccourcis"
L["Key"] = "Touche"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Suppr"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "Aucune assignation"
L["Remove Bar %d Action Page"] = "Retirer la pagination de la barre d'action"
L["Trigger"] = "Déclencheur"
--Bags
L["Bank"] = "Banque"
L["Hold Control + Right Click:"] = "Contrôle enfoncé + Clique droit"
L["Hold Shift + Drag:"] = "Majuscule enfoncée + Déplacer"
L["Purchase Bags"] = "Acheter des sacs"
L["Reset Position"] = "Réinitialiser la position"
L["Sort Bags"] = "Trier les sacs"
L["Temporary Move"] = "Déplacer temporairement"
L["Toggle Bags"] = "Afficher les sacs"
L["Toggle Key"] = true;
L["Vendor Grays"] = "Vendre les objets gris"
--Chat
L["AFK"] = "ABS" --Also used in datatexts and tooltip
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "NPD" --Also used in datatexts and tooltip
L["G"] = "G"
L["Invalid Target"] = "Cible incorrecte"
L["O"] = "O"
L["P"] = "Gr"
L["PL"] = "CdG"
L["R"] = "R"
L["RL"] = "RL"
L["RW"] = "RW"
L["says"] = "dit"
L["whispers"] = "chuchote"
L["yells"] = "crie"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(Maintenir MAJ) Utilisation de la Mémoire."
L["Avoidance Breakdown"] = "Répartition de l'évitement"
L["Character: "] = "Personnage: "
L["Chest"] = "Torse"
L["Combat"] = "Combat"
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
L["Deficit:"] = "Déficit:"
L["DPS"] = "DPS"
L["Earned:"] = "Gagné:"
L["Friends List"] = "Liste d'amis"
L["Friends"] = "Amis" --Also in Skins
L["Gold"] = true;
L["goldabbrev"] = "|cffffd700g|r" --Also used in Bags
L["Hit"] = "Toucher"
L["Hold Shift + Right Click:"] = "Maintenir Majuscule + Clic droit"
L["Home Latency:"] = "Latence du Domicile:"
L["HP"] = "PdS"
L["HPS"] = "HPS"
L["lvl"] = "niveau"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "Réduction par niveau: "
L["No Guild"] = "Pas de Guilde"
L["Profit:"] = "Profit:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "RAZ des données: MAJ + Clic droit"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "Raid(s) Sauvegardé(s)"
L["Server: "] = "Serveur: "
L["Session:"] = "Session:"
L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
L["SP"] = "PdS"
L["Spell/Heal Power"] = true;
L["Spent:"] = "Dépensé: "
L["Stats For:"] = "Stats pour:"
L["System"] = true;
L["Total CPU:"] = "Charge du CPU:"
L["Total Memory:"] = "Mémoire totale:"
L["Total: "] = "Total: "
L["Unhittable:"] = "Intouchable:"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s a essayé d'appeler la fonction protégée '%s'."
L["No locals to dump"] = "Aucunes données à vider"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s tente de partager ses filtres avec vous. Voulez-vous accepter la demande?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s tente de partager le profil %s avec vous. Voulez-vous accepter la demande?"
L["Data From: %s"] = "Donnée de: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "Téléchargement du filtre de %s complet, voulez-vous appliquer les changements maintenant ?" --Need review
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Seigneur ! C'est un miracle ! Le téléchargement s'est envolé et a disparu comme un pet dans le vent! Essayez encore !"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Téléchargement du profil de %s complet, mais le profil de % existe déjà. Changez le nom ou il écrasera le profil existant."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "Téléchargement du profil de %s complet, voulez-vous charger le profil %s maintenant?"
L["Profile request sent. Waiting for response from player."] = "Requête du profil envoyé. En attente de la réponse du joueur."
L["Request was denied by user."] = "La requête a été refusée par l'utilisateur."
L["Your profile was successfully recieved by the player."] = "Votre profil a été reçu avec succès par le joueur."
--Install
L["Aura Bars & Icons"] = "Barres d'Auras & Icônes"
L["Auras Set"] = "Configuration des Auras"
L["Auras"] = "Auras"
L["Caster DPS"] = "DPS Distance"
L["Chat Set"] = "Chat configuré"
L["Chat"] = "Discussion"
L["Choose a theme layout you wish to use for your initial setup."] = "Choisissez un modèle de thème que vous souhaitez utiliser pour votre configuration initiale."
L["Classic"] = "Classique"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Cliquez sur le bouton ci-dessous pour redimensionner vos fenêtres de chat, vos cadres d'unités et repositionner vos barres d'actions."
L["Config Mode:"] = "Mode Configuration:"
L["CVars Set"] = "CVars configurés"
L["CVars"] = "CVars"
L["Dark"] = "Sombre"
L["Disable"] = "Désactiver"
L["ElvUI Installation"] = "Installation d'ElvUI"
L["Finished"] = "Terminé"
L["Grid Size:"] = "Taille de la Grille:"
L["Healer"] = "Soigneur"
L["High Resolution"] = "Haute Résolution"
L["high"] = "Haute"
L["Icons Only"] = "Icônes seulement" --Also used in Bags
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Si vous avez une icône ou une barre d'aura que vous ne souhaitez pas afficher il suffit de maintenir la touche MAJ enfoncée et d'effectuer un clic droit sur l'icône correspondante pour la faire disparaitre."
L["Importance: |cff07D400High|r"] = "Importance: |cff07D400Haute|r"
L["Importance: |cffD3CF00Medium|r"] = "Importance: |cffD3CF00Moyenne|r"
L["Importance: |cffFF0000Low|r"] = "Importance: |cffFF0000Faible|r"
L["Installation Complete"] = "Installation terminée"
L["Layout Set"] = "Disposition configurée"
L["Layout"] = "Disposition"
L["Lock"] = "Verrouiller"
L["Low Resolution"] = "Basse résolution"
L["low"] = "Faible"
L["Nudge"] = "Pousser"
L["Physical DPS"] = "DPS Physique"
L["Please click the button below so you can setup variables and ReloadUI."] = "Pour configurer les variables et recharger l'interface, cliquez sur le bouton ci-dessous."
L["Please click the button below to setup your CVars."] = "Pour configurer les CVars, cliquez sur le bouton ci-dessous."
L["Please press the continue button to go onto the next step."] = "Pour passer à l'étape suivante, cliquez sur le bouton Continuer."
L["Resolution Style Set"] = "Paramètre de résolution configuré"
L["Resolution"] = "Résolution"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Sélectionnez le système d`auras que vous voulez utiliser avec les cadres d`unités ElvUI. Sélectionnez Barres d'Auras & Icônes pour utiliser à la fois les barres et les icônes, choisissez Icônes pour voir seulement les icônes."
L["Setup Chat"] = "Configurer le Chat."
L["Setup CVars"] = "Configurer les CVars"
L["Skip Process"] = "Passer cette étape"
L["Sticky Frames"] = "Cadres aimantés"
L["Tank"] = "Tank"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "La fenêtre de chat ElvUI utilise les même fonctions que celle de Blizzard, vous pouvez faire un clique droit sur un onglet pour le déplacer, le renommer, etc."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Le menu de configuration est accessible en tapant la commande /ec ou en cliquant sur le bouton 'C' sur la Mini-carte. Cliquez sur le bouton ci-dessous si vous voulez passer le processus d'installation."
L["Theme Set"] = "Thème configuré"
L["Theme Setup"] = "Configuration du thème"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Ce programme d'installation vous aidera à découvrir quelques fonctionnalités qu'ElvUI offre et préparera également votre interface à son utilisation."
L["This is completely optional."] = "Ceci est totalement optionnel."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "Cette partie du processus d'installation configure les noms, positions et couleurs de vos fenêtres de chat."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Cette partie du processus d'installation paramètrera vos options par défaut de World of Warcraft. Il est recommandé d'effectuer cette étape afin que tout fonctionne correctement."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Cette résolution ne nécessite pas que vous modifiez les paramètres de l'interface utilisateur pour s'adapter à votre écran."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Cette résolution nécessite que vous modifiez les paramètres de l'interface utilisateur pour s'adapter à votre écran."
L["This will change the layout of your unitframes and actionbars."] = "Ceci changera la disposition des cadres d'unités et des barres d'actions."
L["Trade"] = "Échanger"
L["Welcome to ElvUI version %s!"] = "Bienvenue sur la version %s d'ElvUI!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Vous avez maintenant terminé le processus d'installation. Si vous avez besoin d'un support technique, merci de vous rendre sur https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Vous pouvez toujours modifier les polices et les couleurs de n'importe quel élément d'Elvui dans la configuration du jeu."
L["You can now choose what layout you wish to use based on your combat role."] = "Vous pouvez maintenant choisir quelle disposition vous souhaitez utiliser en fonction de votre rôle en combat."
L["You may need to further alter these settings depending how low you resolution is."] = "Vous devrez peut-être encore modifier ces paramètres en fonction d'un changement de résolution."
L["Your current resolution is %s, this is considered a %s resolution."] = "Votre résolution actuelle est %s, elle est donc considérée comme une %s Résolution."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% excès |cff%02x%02x%02x%s|r]"
L["Bars"] = "Barres" --Also used in UnitFrames
L["Calendar"] = "Calendrier"
L["Can't Roll"] = "Ne peut pas jeter les dés"
L["Disband Group"] = "Dissoudre le groupe"
L["Empty Slot"] = true;
L["Enable"] = "Activer" --Doesn't fit a section since it's used a lot of places
L["Experience"] = "Expérience"
L["Farm Mode"] = true;
L["Fishy Loot"] = "Butin de pêche"
L["Left Click:"] = "Clique Gauche:" --layout\layout.lua
L["Raid Menu"] = "Menu Raid"
L["Remaining:"] = "Restant:"
L["Rested:"] = "Reposé:"
L["Right Click:"] = "Clique Droit:" --layout\layout.lua
L["Show BG Texts"] = "Voir les textes de BG" --layout\layout.lua
L["Toggle Chat Frame"] = "Activer la fenêtre de discussion" --layout\layout.lua
L["Toggle Configuration"] = "Afficher la Configuration" --layout\layout.lua
L["XP:"] = "XP:"
L["You don't have permission to mark targets."] = "Vous n'avez pas la permission de marquer les cibles."
--Movers
L["Arena Frames"] = "Cadre d'arène" --Also used in UnitFrames
L["Bag Mover (Grow Down)"] = true;
L["Bag Mover (Grow Up)"] = true;
L["Bag Mover"] = true;
L["Bags"] = "Sacs" --Also in DataTexts
L["Bank Mover (Grow Down)"] = true;
L["Bank Mover (Grow Up)"] = true;
L["Bar "] = "Barre " --Also in ActionBars
L["BNet Frame"] = "Cadre BNet"
L["Boss Frames"] = "Cadre du Boss" --Also used in UnitFrames
L["Classbar"] = "Barre de Classe"
L["Experience Bar"] = "Barre d'expérience"
L["Focus Castbar"] = "Barre d'incantation du Focus"
L["Focus Frame"] = "Cadre Focus" --Also used in UnitFrames
L["FocusTarget Frame"] = "Cadre de la cible de votre Focus" --Also used in UnitFrames
L["GM Ticket Frame"] = "Cadre du ticket MJ"
L["Left Chat"] = "Chat gauche"
L["Loot / Alert Frames"] = "Cadres de butin / Alerte"
L["Loot Frame"] = "Cadre de butin"
L["MA Frames"] = "Cadres de l`assistant principal"
L["Micro Bar"] = "Micro Barre" --Also in ActionBars
L["Minimap"] = "Mini-carte"
L["MirrorTimer"] = "Timer mirroir"
L["MT Frames"] = "Cadres du Tank principal"
L["Party Frames"] = "Cadres de groupe" --Also used in UnitFrames
L["Pet Bar"] = "Barre du familier" --Also in ActionBars
L["Pet Castbar"] = "Barre d'incantation du familier"
L["Pet Frame"] = "Cadre du familier" --Also used in UnitFrames
L["PetTarget Frame"] = "Cadre de la cible du familier" --Also used in UnitFrames
L["Player Buffs"] = "Améliorations du joueur"
L["Player Castbar"] = "Barre d'incantation du joueur"
L["Player Debuffs"] = "Affaiblissements du joueur"
L["Player Frame"] = "Cadre du joueur" --Also used in UnitFrames
L["Player Powerbar"] = "Barre de pouvoir du joueur" -- need review.
L["PvP"] = true;
L["Raid Frames"] = "Cadres de Raid"
L["Raid Pet Frames"] = "Cadres de Raid des Familiers"
L["Raid-40 Frames"] = "Cadres de Raid 40"
L["Reputation Bar"] = "Barre de réputation"
L["Right Chat"] = "Chat de droite"
L["Stance Bar"] = "Barre de posture" --Also in ActionBars
L["Target Castbar"] = "Barre d'incantation de la cible"
L["Target Frame"] = "Cadre de la cible" --Also used in UnitFrames
L["Target Powerbar"] = "Barre de pouvoir de la cible" -- need review.
L["TargetTarget Frame"] = "Cadre de la cible de votre cible" --Also used in UnitFrames
L["TargetTargetTarget Frame"] = "Cadre de la cible de la cible de la cible"
L["Time Manager Frame"] = true;
L["Tooltip"] = "Infobulle"
L["Vehicle Seat Frame"] = "Cadre de siège du véhicule"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = true;
L["In Progress"] = true;
L["List of installations in queue:"] = true;
L["Pending"] = true;
L["Steps"] = true;
--Prints
L[" |cff00ff00bound to |r"] = "|cff00ff00assigné à |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "% du (des) cadre(s) à un point d'ancrage contradictoire(s), merci de changer le point d'ancrage des améliorations ou des affaiblissements de sorte qu'ils ne soient pas attachés les uns aux autres. Forcer les affaiblissements à être attachés au cadre d'unité principale jusqu'à ce qu'ils soient fixés."
L["All keybindings cleared for |cff00ff00%s|r."] = "Tous les raccourcis ont été effacés pour |cff00ff00%s|r."
L["Already Running.. Bailing Out!"] = "Déjà en cours d'exécution, arrêt du processus..."
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Textes d'informations du champ de bataille temporairement masqués, pour les afficher tapez /bgstats ou cliquez droit sur le 'C' près de la mini-carte."
L["Battleground datatexts will now show again if you are inside a battleground."] = "Les textes d'informations du champ de bataille seront à nouveau affichés si vous êtes dans un champ de bataille."
L["Binds Discarded"] = "Raccourcis annulés"
L["Binds Saved"] = "Raccourcis sauvegardés"
L["Confused.. Try Again!"] = "Confus...Essayez à nouveau!"
L["No gray items to delete."] = "Aucun objet gris à détruire."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Le sort '%s' a bien été ajouté à la liste noire des filtres des cadres d'unités."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
L["Vendored gray items for:"] = "Objets gris vendus pour:"
L["You don't have enough money to repair."] = "Vous n'avez pas assez d'argent pour réparer votre équipement."
L["You must be at a vendor."] = "Vous devez être chez un marchand."
L["Your items have been repaired for: "] = "Votre équipement a été réparé pour: "
L["Your items have been repaired using guild bank funds for: "] = "Votre équipement a été réparé avec l'argent de la banque de guilde pour: "
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Erreur Lua reçue. Vous pouvez voir ce message d'erreur quand vous sortirez de combat."
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Un réglage que vous avez modifié ne s'appliquera que pour ce personnage. La modification de ce réglage ne sera pas affecté par un changement de profil. Changer ce réglage requiert de relancer l'interface."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "En acceptant, votre liste de priorités des filtres sera réinitialisée pour les auras des cadres d'unités. Êtes-vous sûr ?"
L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
L["Are you sure you want to delete all your gray items?"] = "Êtes-vous sûr de vouloir détruire tous vos Objets Gris ?"
L["Are you sure you want to disband the group?"] = "Êtes-vous sûr de vouloir dissoudre le groupe ? "
L["Are you sure you want to reset all the settings on this profile?"] = "Êtes-vous sûr de vouloir réinitialiser tous les réglages sur ce profile?"
L["Are you sure you want to reset every mover back to it's default position?"] = "Êtes-vous sûr de vouloir réinitialiser tous les cadres à leur position par défaut ?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "En raison de la confusion générale provoquée par le nouveau système d'aura, j'ai mis en place une nouvelle étape dans le processus d'installation. Cette option est facultative. Si vous aimez la façon dont vos auras sont configurés allez à la dernière étape et cliquez sur Terminé pour ne pas être averti à nouveau. Si, pour une raison quelconque, vous êtes averti de nouveau, relancez complètement le jeu."
L["Can't buy anymore slots!"] = "Impossible d'acheter plus emplacements !"
L["Disable Warning"] = "Désactiver l'alerte"
L["Discard"] = "Annuler"
L["Do you enjoy the new ElvUI?"] = "Aimez-vous le nouveau ElvUI?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Jurez-vous de ne pas poster sur le support technique du forum sur quelque chose qui ne fonctionne pas sans avoir désactivé en premier la combinaison Addon/Module?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI est périmé d'au moins 5 versions. Vous pouvez télécharger la nouvelle version sur https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI est périmé. Vous pouvez télécharger la nouvelle version sur https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI a besoin d'effectuer des optimisations de la base de données, merci de patienter."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Passez votre souris sur n'importe quel bouton d'action ou bouton du grimoire pour lui attribuer un raccourcis. Appuyez sur la touche Échap ou le clique droit pour effacer le raccourci en cours."
L["I Swear"] = "Je le jure"
L["No, Revert Changes!"] = "Non, annuler les changements!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh seigneur, vous avez ElvUI et Tukui d'activé en même temps. Sélectionnez un addon à désactiver."
L["One or more of the changes you have made require a ReloadUI."] = "Une ou plusieurs modifications que vous avez effectuées nécessitent un rechargement de l'interface."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Un ou plusieurs changement(s) que vous avez effectué a une incidence sur tous les personnages qui utilisent cet Addon. Vous devriez recharger l'interface utilisateur pour voir le(s) changement(s) apporté(s)."
L["Save"] = "Sauvegarder"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Le profil que vous essayez d'importer existe déjà. Choisissez un nouveau nom ou acceptez d'écraser le profil existant."
L["Type /hellokitty to revert to old settings."] = "Tapez /hellokitty pour recharger les anciennes configurations"
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Si vous utilisez l'agencement Soigneur, il est hautement recommandé de télécharger l'Addon Clique si vous souhaitez avoir la fonction cliquer-pour-soigner."
L["Yes, Keep Changes!"] = "Oui, garder les changements!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Vous venez de changer l'échelle de votre interface, alors que votre option d'échelle automatique est encore activée dans ElvUI. Cliquer sur accepter si vous voulez désactiver l'option d'échelle automatique."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Vous avez importé des paramètes qui requierent un rechargement de l'interface. Recharger maintenant ?"
L["You must purchase a bank slot first!"] = "Vous devez d'abord acheter un emplacement de banque!"
--Tooltip
L["Count"] = "Nombre:"
L["Item Level:"] = "Niveau d'équipement"
L["Talent Specialization:"] = "Spécialisation des talents"
L["Targeted By:"] = "Ciblé par:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Une fonction marqueur de raid est disponible en appuyant sur Échap -> Raccourcis, défilez en bas d'ElvUI et paramétrez le raccourcis pour le marqueur de raid."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI dispose d'une fonction double spécialisation qui vous permet de charger à la volée des profils différents en fonction de votre spécialisation actuelle."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Pour tout support technique, merci de nous visiter à https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Si vous supprimez accidentellement un cadre de discussion, vous pouvez toujours aller dans le menu de configuration d'ElvUI. Cliquez ensuite sur Installation puis passez à l'étape concernant les fenêtres de discussion pour remettre à zéro les paramètres."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Si vous rencontrez des problèmes avec ElvUI, essayez de désactiver tous vos addons sauf ElvUI. Rappelez-vous que'ElvUi est une interface utilisateur complète et que vous ne pouvez pas exécuter deux addons qui font la même chose."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Le cadre de focus peut être défini en tapant /focus quand vous êtes en train de cibler une unité que vous voulez focus. Il est recommandé de faire une macro pour cela."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Pour déplacer par défaut les capacités des barres d'actions, maintenez MAJ + déplacer. Vous pouvez modifier la touche de modification dans le menu des barres d'actions."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Pour configurer quels canaux de discussions doivent apparaitre dans les fenêtres de Chat, faites un clic droit sur l'onglet de Chat et allez dans les paramètres."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Vous pouvez accéder à une copie du Chat et des fonctions du Chat en survolant avec votre souris le coin haut droit de la fenêtre de discussion. Cliquez ensuite sur le bouton."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Vous pouvez voir le niveau d'objet moyen de n'importe qui en maintenant la touche MAJ enfoncée puis en passant votre souris sur un joueur. Le score apparaitra dans la bulle d'information."
L["You can set your keybinds quickly by typing /kb."] = "Vous pouvez assignez rapidement vos raccourcis en tapant /kb."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Vous pouvez afficher la microbarre en utilisant le bouton central de votre souris sur la minicarte. Vous pouvez aussi l'afficher via les réglages des Barres d'actions"
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "Vous pouvez utiliser la commande /resetui pour réinitialiser l'ensemble de vos cadres. Vous pouvez aussi utiliser la commande /resetui <nom du cadre> pour réinitialiser un cadre spécifique.\nExemple: /resetui Player Frame"
--UnitFrames
L["Dead"] = "Mort"
L["Ghost"] = "Fantôme"
L["Offline"] = "Déconnecté"
+346
View File
@@ -0,0 +1,346 @@
-- German localization file for deDE.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "deDE")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "Das Addon %s ist nicht mit dem ElvUI %s Modul kompatibel. Bitte deaktiviere entweder das Addon oder deaktiviere das ElvUI Modul."
--*_MSG locales
L["LOGIN_MSG"] = "Willkommen zu %sElvUI|r Version %s%s|r, Tippe /ec um das Konfigurationsmenü aufzurufen. Für technische Hilfe, besuche das Supportforum unter https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "Belegung"
L["Key"] = "Taste"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "Keine Belegungen gesetzt."
L["Remove Bar %d Action Page"] = "Entferne Leiste %d Aktion Seite"
L["Trigger"] = "Auslöser"
--Bags
L["Bank"] = true;
L["Hold Control + Right Click:"] = "Halte Steuerung + Rechtsklick:"
L["Hold Shift + Drag:"] = "Halte Shift + Ziehen:"
L["Purchase Bags"] = "Taschen kaufen"
L["Reset Position"] = "Position zurücksetzen"
L["Sort Bags"] = "Taschen sortieren"
L["Temporary Move"] = "Temporäres Bewegen"
L["Toggle Bags"] = "Taschen umschalten"
L["Toggle Key"] = true;
L["Vendor Grays"] = "Graue Gegenstände verkaufen"
--Chat
L["AFK"] = "AFK" --Also used in datatexts and tooltip
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "DND" --Also used in datatexts and tooltip
L["G"] = "G"
L["Invalid Target"] = "Ungültiges Ziel"
L["O"] = "O"
L["P"] = "P"
L["PL"] = "PL"
L["R"] = "R"
L["RL"] = "RL"
L["RW"] = "RW"
L["says"] = "sagen"
L["whispers"] = "flüstern"
L["yells"] = "schreien"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(Shift gedrückt) Speichernutzung"
L["Avoidance Breakdown"] = "Vermeidung Aufgliederung"
L["Character: "] = "Charakter: "
L["Chest"] = "Brust"
L["Combat"] = "Kampf"
L["Combat Time"] = "Kampf Zeit"
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55fc|r" --Also used in Bags
L["Deficit:"] = "Defizit:"
L["DPS"] = "DPS"
L["Earned:"] = "Verdient:"
L["Friends List"] = "Freundesliste"
L["Friends"] = "Freunde" --Also in Skins
L["Gold"] = true;
L["goldabbrev"] = "|cffffd700g|r" --Also used in gold datatext
L["Hit"] = "Hit"
L["Hold Shift + Right Click:"] = "Halte Umschalt + Rechts Klick:"
L["Home Latency:"] = "Standort Latenz"
L["HP"] = "HP"
L["HPS"] = "HPS"
L["lvl"] = "lvl"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "Milderung durch Stufe:"
L["No Guild"] = "Keine Gilde"
L["Profit:"] = "Gewinn:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "Daten zurücksetzen: Halte Shift + Rechtsklick"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "Gespeicherte Schlachtzüge"
L["Server: "] = "Server: "
L["Session:"] = "Sitzung:"
L["silverabbrev"] = "|cffc7c7cfs|r" --Also used in Bags
L["SP"] = "SP"
L["Spell/Heal Power"] = true;
L["Spent:"] = "Ausgegeben:"
L["Stats For:"] = "Stats Für:"
L["System"] = true;
L["Total CPU:"] = "Gesamt CPU:"
L["Total Memory:"] = "Gesamte Speichernutzung:"
L["Total: "] = "Gesamt: "
L["Unhittable:"] = "Unhittable:"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s versucht die geschützte Funktion aufrufen '%s'."
L["No locals to dump"] = "Keine Lokalisierung zum verwerfen"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s möchte seine Filter Einstellungen mit dir teilen. Möchtest du die Anfrage annehmen?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s versucht das Profil %s mit dir zu teilen. Möchtest du die Anfrage annehmen?"
L["Data From: %s"] = "Datei von: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "Filter komplett heruntergeladen von %s, möchtest du die Änderungen nun vornehmen?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Herr! Es ist ein Wunder! Der Download verschwand wie ein Furz im Wind! Versuche es nochmal!"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Profil komplett heruntergeladen von %s, allerdings ist das Profil %s bereits vorhanden. Ändere den Namen oder das bereits existierende Profil wird überschrieben."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "Profil komplett heruntergeladen von %s, möchtest du das Profil %s nun laden?"
L["Profile request sent. Waiting for response from player."] = "Profil Anfrage gesendet. Warte auf die Antwort des Spielers."
L["Request was denied by user."] = "Die Anfrage wurde vom Benutzer abgelehnt."
L["Your profile was successfully recieved by the player."] = "Dein Profil wurde erfolgreich von dem Spieler empfangen."
--Install
L["Aura Bars & Icons"] = "Aurenleiste & Symbole"
L["Auras Set"] = "Auren gesetzt"
L["Auras"] = "Auren"
L["Caster DPS"] = "Fernkampf DD"
L["Chat Set"] = "Chat gesetzt"
L["Chat"] = "Chat"
L["Choose a theme layout you wish to use for your initial setup."] = "Wähle ein Layout, welches du bei deinem ersten Setup verwenden möchtest."
L["Classic"] = "Klassisch"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Klicke auf die Taste unten um die Größe deiner Chatfenster, Einheitenfenster und die Umpositionierung deiner Aktionsleisten durchzuführen."
L["Config Mode:"] = "Konfigurationsmodus:"
L["CVars Set"] = "CVars gesetzt"
L["CVars"] = "CVars"
L["Dark"] = "Dunkel"
L["Disable"] = "Deaktivieren"
L["ElvUI Installation"] = "ElvUI Installation"
L["Finished"] = "Beendet"
L["Grid Size:"] = "Rastergröße:"
L["Healer"] = "Heiler"
L["High Resolution"] = "Hohe Auflösung"
L["high"] = "hoch"
L["Icons Only"] = "Nur Symbole" --Also used in Bags
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Wenn du ein Symbol oder eine Aurenleiste nicht angezeigt haben möchtest, dann halte Shift gedrückt und klicke mit Rechtsklick auf das Symbol um es auszublenden."
L["Importance: |cff07D400High|r"] = "Bedeutung: |cff07D400Hoch|r"
L["Importance: |cffD3CF00Medium|r"] = "Bedeutung: |cffD3CF00Mittel|r"
L["Importance: |cffFF0000Low|r"] = "Bedeutung: |cffD3CF00Niedrig|r"
L["Installation Complete"] = "Installation komplett"
L["Layout Set"] = "Layout gesetzt"
L["Layout"] = "Layout"
L["Lock"] = "Sperren"
L["Low Resolution"] = "Niedrige Auflösung"
L["low"] = "niedrig"
L["Nudge"] = "Stoß"
L["Physical DPS"] = "Physische DPS"
L["Please click the button below so you can setup variables and ReloadUI."] = "Bitte klicke die Taste unten um den Installationsprozess abzuschließen und das Benutzerinterface neu zu laden."
L["Please click the button below to setup your CVars."] = "Klicke 'Installiere CVars' um die CVars einzurichten."
L["Please press the continue button to go onto the next step."] = "Bitte drücke die Weiter-Taste um zum nächsten Schritt zu gelangen."
L["Resolution Style Set"] = "Auflösungsart gesetzt"
L["Resolution"] = "Auflösung"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Wähle für die ElvUI Einheitenfenster ob das Auren-System Aurenleisten und Symbole, oder nur Symbole anzeigt."
L["Setup Chat"] = "Chateinstellungen"
L["Setup CVars"] = "Installiere CVars"
L["Skip Process"] = "Schritt überspringen"
L["Sticky Frames"] = "Anheftende Fenster"
L["Tank"] = "Tank"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Die Chatfensterfunktionen sind die gleichen, wie die Chatfenster von Blizzard. Du kannst auf die Tabs rechtsklicken und sie z.B. neu zu positionieren, umzubenennen, etc. Bitte klicke den Button unten um das Chatfenster einzurichten."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Das ElvUI-Konfigurationsmenü kannst du entweder mit /ec oder durch das Anklicken der 'C' Taste an der Minimap aufrufen. Drücke 'Schritt überspringen' um zum nächsten Schritt zu gelangen."
L["Theme Set"] = "Thema gesetzt"
L["Theme Setup"] = "Thema Setup"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Dieser Installationsprozess wird dir helfen, die Funktionen von ElvUI für deine Benutzeroberfläche besser kennenzulernen."
L["This is completely optional."] = "Das ist komplett Optional."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "Dieser Abschnitt der Installation stellt die Chat Fenster Namen, Positionen und Farben ein."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Dieser Installationsprozess richtet alle wichtigen Cvars deines World of Warcrafts ein, um eine problemlose Nutzung zu ermöglichen."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Diese Auflösung benötigt keine Änderungen um mit der Benutzeroberfläche zu funktionieren."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Diese Auflösung benötigt Änderungen um mit der Benutzeroberfläche zu funktionieren."
L["This will change the layout of your unitframes and actionbars."] = "Dies wird das Layout der Einheitenfenster und Aktionsleisten ändern."
L["Trade"] = "Handel"
L["Welcome to ElvUI version %s!"] = "Willkommen bei ElvUI Version %s!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Du hast den Installationsprozess abgeschlossen. Solltest du technische Hilfe benötigen, besuche uns auf https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Du kannst jederzeit in der Ingame-Konfiguration Schriften und Farben von jedem Element des Interfaces ändern."
L["You can now choose what layout you wish to use based on your combat role."] = "Du kannst nun auf Basis deiner Rolle im Kampf ein Layout wählen."
L["You may need to further alter these settings depending how low you resolution is."] = "Unter Umständen musst du, je nachdem wie niedrig deine Auflösung ist, diese Einstellungen ändern."
L["Your current resolution is %s, this is considered a %s resolution."] = "Deine Aktuelle Auflösung ist %s, diese wird als eine %s Auflösung angesehen."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
L["Bars"] = "Leisten" --Also used in UnitFrames
L["Calendar"] = "Kalender"
L["Can't Roll"] = "Es kann nicht gewürfelt werden."
L["Disband Group"] = "Gruppe auflösen"
L["Empty Slot"] = "Leerer Platz"
L["Enable"] = "Eingeschaltet" --Doesn't fit a section since it's used a lot of places
L["Experience"] = "Erfahrung"
L["Farm Mode"] = true;
L["Fishy Loot"] = "Faule Beute"
L["Left Click:"] = "Linksklick:" --layout\layout.lua
L["Raid Menu"] = "Schlachtzugsmenü"
L["Remaining:"] = "Verbleibend:"
L["Rested:"] = "Ausgeruht:"
L["Right Click:"] = "Rechtsklick:" --layout\layout.lua
L["Show BG Texts"] = "Zeige Schlachtfeldtexte" --layout\layout.lua
L["Toggle Chat Frame"] = "Chatfenster an-/ausschalten" --layout\layout.lua
L["Toggle Configuration"] = "Konfiguration umschalten" --layout\layout.lua
L["XP:"] = "EP:"
L["You don't have permission to mark targets."] = "Du hast keine Rechte um ein Ziel zu markieren."
--Movers
L["Arena Frames"] = "Arena Fenster" --Also used in UnitFrames
L["Bag Mover (Grow Down)"] = "Taschen Anker (Nach unten wachsen)"
L["Bag Mover (Grow Up)"] = "Taschen Anker (Nach oben wachsen)"
L["Bag Mover"] = "Taschen Anker"
L["Bags"] = "Taschen" --Also in DataTexts
L["Bank Mover (Grow Down)"] = "Bank Anker (Nach unten wachsen)"
L["Bank Mover (Grow Up)"] = "Bank Anker (Nach oben wachsen)"
L["Bar "] = "Leiste " --Also in ActionBars
L["BNet Frame"] = "BNet-Fenster"
L["Boss Frames"] = "Boss Fenster" --Also used in UnitFrames
L["Classbar"] = "Klassenleiste"
L["Experience Bar"] = "Erfahrungsleiste"
L["Focus Castbar"] = "Fokus Zauberbalken"
L["Focus Frame"] = "Fokusfenster" --Also used in UnitFrames
L["FocusTarget Frame"] = "Fokus-Ziel Fenster" --Also used in UnitFrames
L["GM Ticket Frame"] = "GM-Ticket-Fenster"
L["Left Chat"] = "Linker Chat"
L["Loot / Alert Frames"] = "Beute-/Alarmfenster"
L["Loot Frame"] = "Beute-Fenster"
L["MA Frames"] = "MA-Fenster"
L["Micro Bar"] = "Mikroleiste" --Also in ActionBars
L["Minimap"] = "Minimap"
L["MirrorTimer"] = "Spiegel Zeitgeber"
L["MT Frames"] = "MT-Fenster"
L["Party Frames"] = "Gruppenfenster" --Also used in UnitFrames
L["Pet Bar"] = "Begleisterleiste" --Also in ActionBars
L["Pet Castbar"] = "Begleiter Zauberleiste"
L["Pet Frame"] = "Begleiterfenster" --Also used in UnitFrames
L["PetTarget Frame"] = "Begleiter-Ziel Fenster" --Also used in UnitFrames
L["Player Buffs"] = "Spieler Buffs"
L["Player Castbar"] = "Spieler Zauberbalken"
L["Player Debuffs"] = "Spieler Debuffs"
L["Player Frame"] = "Spielerfenster" --Also used in UnitFrames
L["Player Powerbar"] = "Spieler Kraftleiste"
L["PvP"] = true;
L["Raid Frames"] = "Schlachtzugsfenster" --Also used in UnitFrames
L["Raid Pet Frames"] = "Schlachtzugspets-Fenster"
L["Raid-40 Frames"] = "40er Schlachtzugsfenster" --Also used in UnitFrames
L["Reputation Bar"] = "Rufleiste"
L["Right Chat"] = "Rechter Chat"
L["Stance Bar"] = "Haltungsleiste" --Also in ActionBars
L["Target Castbar"] = "Ziel Zauberbalken"
L["Target Frame"] = "Zielfenster" --Also used in UnitFrames
L["Target Powerbar"] = "Ziel Kraftleiste"
L["TargetTarget Frame"] = "Ziel des Ziels Fenster" --Also used in UnitFrames
L["TargetTargetTarget Frame"] = "Ziel des Ziels des Ziels Fenster"
L["Time Manager Frame"] = true;
L["Tooltip"] = "Tooltip"
L["Vehicle Seat Frame"] = "Fahrzeugfenster"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = true;
L["In Progress"] = "In Bearbeitung"
L["List of installations in queue:"] = "Liste von Installationen in Warteschlange:"
L["Pending"] = "Ausstehend"
L["Steps"] = "Schritte"
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00gebunden zu |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "Es liegt ein Konflikt bei den Ankerpunkten des Rahmens %s vor. Bitte ändere entweder den Ankerpunkt des Stärkungs- oder Schwächungszaubers, damit diese nicht länger mit einander verbunden sind. Verbinde die Schwächungszauber mit dem Hauptrahmen, damit dieses Problem behoben wird."
L["All keybindings cleared for |cff00ff00%s|r."] = "Alle Tastaturbelegungen gelöscht für |cff00ff00%s|r."
L["Already Running.. Bailing Out!"] = "Bereits ausgeführt.. Warte ab!"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Schlachtfeld-Infotexte sind kurzzeitig versteckt, um sie wieder anzuzeigen tippe /bgstats oder rechtsklicke auf das 'C' Symbol nahe der Minimap."
L["Battleground datatexts will now show again if you are inside a battleground."] = "Schlachtfeld-Infotexte werden wieder angezeigt, solange du dich in einem Schlachtfeld befindest."
L["Binds Discarded"] = "Tastaturbelegungen verworfen"
L["Binds Saved"] = "Tastaturbelegungen gespeichert"
L["Confused.. Try Again!"] = "Verwirrt.. Versuche es erneut!"
L["No gray items to delete."] = "Es sind keine grauen Gegenstände zum Löschen vorhanden."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Der Zauber '%s' wurde zur schwarzen Liste der Einheitenfenster hinzugefügt."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Diese Einstellungen haben einen Konflikt mit einem Ankerpunkt, wo '%s' an sich selbst angehaftet sein soll. Bitte kontrolliere deine Ankerpunkte. Einstellung '%s' angehaftet an '%s'."
L["Vendored gray items for:"] = "Graue Gegenstände verkauft für:"
L["You don't have enough money to repair."] = "Du hast nicht genügend Gold für die Reparatur."
L["You must be at a vendor."] = "Du musst bei einem Händler sein."
L["Your items have been repaired for: "] = "Deine Gegenstände wurden repariert für: "
L["Your items have been repaired using guild bank funds for: "] = "Deine Gegenstände wurden repariert. Die Gildenbank kostete das: "
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Lua Fehler erhalten. Du kannst die Fehlermeldung ansehen, wenn du den Kampf verlässt."
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Eine Einstellung, die du geändert hast, betrifft nur einen Charakter. Diese Einstellung, die du verändert hast, wird die Benutzerprofile unbeeinflusst lassen. Eine Änderung dieser Einstellung erfordert, dass du dein Interface neu laden musst."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "Wenn du aktzeptierst wird die Filter Priorität für alle Einheitenfenster auf Standard zurückgesetzt. Bist du sicher?"
L["Are you sure you want to apply this font to all ElvUI elements?"] = "Bist du sicher, dass du diese Schrifart auf alle ElvUI Elemente anwenden möchtest?"
L["Are you sure you want to delete all your gray items?"] = "Bist du sicher, dass du alle grauen Gegenstände löschen willst?"
L["Are you sure you want to disband the group?"] = "Bist du dir sicher, dass du die Gruppe auflösen willst?"
L["Are you sure you want to reset all the settings on this profile?"] = "Bist du dir sicher dass du alle Einstellungen dieses Profils zurücksetzen willst?"
L["Are you sure you want to reset every mover back to it's default position?"] = "Bist du dir sicher, dass du jeden Beweger an die Standard-Position zurücksetzen möchtest?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Aufgrund der großen Verwirrung, die durch das neue Auren-System verursacht wurde, habe ich einen neuen Schritt zum Installationsprozess hinzugefügt. Dieser ist optional. Wenn du deine Auren so eingestellt lassen willst, wie sie sind, gehe einfach zum letzten Schritt und klicke auf fertig um nicht erneut aufgefordert zu werden. Wirst du, aus welchen Grund auch immer, öfter aufgefordert, starte bitte dein Spiel neu"
L["Can't buy anymore slots!"] = "Kann keine Slots mehr kaufen"
L["Disable Warning"] = "Deaktiviere Warnung"
L["Discard"] = "Verwerfen"
L["Do you enjoy the new ElvUI?"] = "Gefällt dir das neue ElvUI?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Schwörst du, dass du keinen Beitrag im Supportforum posten wirst, ohne vorher alle anderen Addons/Module zu deaktivieren?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI ist seit fünf oder mehr Revisionen nicht aktuell. Du kannst die neuste Version bei https://github.com/ElvUI-WotLK/ElvUI/ herunterladen."
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI ist nicht aktuell. Du kannst die neuste Version bei https://github.com/ElvUI-WotLK/ElvUI/ herunterladen."
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI muss eine Datenbank Optimierung durchführen. Bitte warte eine Moment."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Bewege deine Maus über einen Aktionsbutton oder dein Zauberbuch um ihn mit einem Hotkey zu belegen. Drücke Escape oder rechte Maustaste um die aktuelle Tastenbelegung des Buttons zu löschen."
L["I Swear"] = "Ich schwöre"
L["No, Revert Changes!"] = "Nein, Änderungen verwerfen!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh Gott, du hast ElvUI und Tukui zur gleichen Zeit aktiviert. Wähle ein Addon um es zu deaktivieren."
L["One or more of the changes you have made require a ReloadUI."] = "Eine oder mehrere Einstellungen, die du vorgenommen hast, benötigen ein Neuladen des Benutzerinterfaces um in Effekt zu treten."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Eine oder mehrere Änderungen, die du getroffen hast, betrifft alle Charaktere die dieses Addon benutzen. Du musst das Benutzerinterface neu laden um die Änderungen, die du durchgeführt hast, zu sehen."
L["Save"] = "Speichern"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Das Profil, dass du versuchst zu importieren existiert bereits. Wähle einen neuen Namen oder aktzeptiere dass das vorhandene Profile überschrieben wird."
L["Type /hellokitty to revert to old settings."] = "Tippe /hellokitty um die alten Einstellungen zu verwenden."
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Wenn du das Heiler Layout benutzt ist es sehr empfohlen das Addon Clique zu downloaden wenn du die Klick-zum-Heilen Funktion haben willst."
L["Yes, Keep Changes!"] = "Ja, Änderungen behalten!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Du hast die Dünnen Rahmen Einstellungen geändert. Du musst die Installation komplett abschließen um grafische Fehler zu vermeiden."
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Du hast die Skalierung des benutzerinterfaces geändert, während du die automatische Skalierung in ElvUI aktiv hast. Drücke Annehmen um die automatische Skalierung zu deaktivieren."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Du hast Einstellungen importiert die wahrscheinlich ein Neuladen des UI erfordern. Jetzt neu laden?"
L["You must purchase a bank slot first!"] = "Du musst erst ein Bankfach kaufen!"
--Tooltip
L["Count"] = "Zähler"
L["Item Level:"] = "Itemlevel"
L["Talent Specialization:"] = "Talentspezialisierung"
L["Targeted By:"] = "Ziel von:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Ein Feature für Schlachtzugsmarkierung ist verfügbar, wenn du Escape drückst und Tastaturbelegung wählst, scrolle anschließend bis unter die Kategorie ElvUI und wähle eine Tastenbelegung für die Schlachtzugsmarkierung."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI hat ein Feature für Dualspezialisierungen, welches dich abhängig von deiner momentanen Spezialisierung verschiedene Profile laden lässt. Dieses Feature kannst du im Abschnitt Profil aktivieren."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Für technische Hilfe besuche uns unter https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Wenn du ausversehen das Chatfenster entfernen solltest, kannst du ganz einfach in die Ingame-Konfiguration gehen und den Installationsprozess erneut aufrufen. Drücke Installieren und gehe zu den Chateinstellungen und setze diese zurück."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Wenn du Probleme mit ElvUI hast, deaktiviere alle Addons außer ElvUI. Denke auch daran, dass ElvUI die komplette Benutzeroberfläche ersetzt, d.h. du kannst kein Addon verwenden, welches die gleichen Funktionen wie ElvUI nutzt."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Du kannst, während du ein Ziel hast, das Fokusfenster durch die Eingabe von /fokus setzen. Es wird empfohlen ein Makro dafür zu nutzen."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Um Fähigkeiten auf der Aktionsleiste zu verschieben nutze Shift und bewege zeitgleich die Maus. Du kannst die Modifier-Taste im Aktionsleistenmenü umstellen."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Um einzustellen welcher Kanal im welchem Chatfenster angezeigt werden soll, klicke rechts auf das Chattab und gehe auf Einstellungen."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Du kannst die Funktionen Chat Kopieren und Chatmenü aufrufen, wenn du die Maus in die obere rechte Ecke des Chatfensters bewegst und links-/rechtsklickst."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Du kannst die durchschnittliche Gegenstandsstufe von jemanden sehen, wenn du bei gedrückter Shift-Taste mit der Maus über ihn fährst. Die Gegenstandsstufe wird dann im Tooltip angezeigt."
L["You can set your keybinds quickly by typing /kb."] = "Du kannst deine Tastaturbelegung schnell ändern, wenn du /kb eintippst."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Du kannst die Mikroleiste durch mittleren Mausklick auf der Minimap aufrufen oder auch die tatsächliche Mikroleiste in den Aktionsleisten Optionen aktivieren."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "Du kannst durch benutzen von /resetui alle Ankerpunkte zurücksetzen. Du kannst das Kommando auch benutzen um spezielle Anker zurückzusetzen, /resetui <Anker Name>.\nBeispiel: /resetui Player Frame"
--UnitFrames
L["Dead"] = "Tot"
L["Ghost"] = "Geist"
L["Offline"] = "Offline"
+346
View File
@@ -0,0 +1,346 @@
-- Korean localization file for koKR.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "koKR")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "%s 애드온의 기능이 ElvUI의 %s 모듈과 상충됩니다. 그 애드온을 쓰지 않거나 ElvUI의 기능을 사용해제하세요."
--*_MSG locales
L["LOGIN_MSG"] = "%sElvUI|r 버전 %s%s|r 을 사용해 주셔서 감사합니다. /ec 를 입력하면 설정창을 열 수 있습니다. 궁금한 점이나 기술지원은 https://github.com/ElvUI-WotLK/ElvUI 에서 해결하세요"
--ActionBars
L["Binding"] = " "
L["Key"] = "단축키"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "W▼"
L["KEY_MOUSEWHEELUP"] = "W▲"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "P▼"
L["KEY_PAGEUP"] = "P▲"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "Spc"
L["No bindings set."] = "설정한 단축키가 없습니다."
L["Remove Bar %d Action Page"] = "Blizzard %d번 행동단축바 숨기기"
L["Trigger"] = "묶음을 펼치고 각 주문에 지정하세요."
--Bags
L["Bank"] = "은행"
L["Hold Control + Right Click:"] = "Shift 우클릭:"
L["Hold Shift + Drag:"] = "Shift 드래그:"
L["Purchase Bags"] = "가방 슬롯 구입"
L["Reset Position"] = "위치 초기화"
L["Sort Bags"] = "가방 정렬"
L["Temporary Move"] = "임시 이동"
L["Toggle Bags"] = "가방슬롯 보기"
L["Toggle Key"] = true;
L["Vendor Grays"] = "잡동사니 자동판매"
--Chat
L["AFK"] = "자리비움"
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "다른 용무중"
L["G"] = "길드"
L["Invalid Target"] = "잘못된 대상"
L["O"] = "관리자"
L["P"] = "파티"
L["PL"] = "파장"
L["R"] = "공대"
L["RL"] = "공장"
L["RW"] = "경보"
L["says"] = "일반"
L["whispers"] = ""
L["yells"] = "외침"
--DataTexts
L["(Hold Shift) Memory Usage"] = "Shift: 메모리 사용량"
L["Avoidance Breakdown"] = "방어율 목록"
L["Character: "] = "캐릭터:"
L["Chest"] = "가슴"
L["Combat"] = "전투"
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:33:48:1:16|t" --"|cffeda55f●|r"
L["Deficit:"] = "손해:"
L["DPS"] = "DPS"
L["Earned:"] = "수입:"
L["Friends List"] = "친구 목록"
L["Friends"] = "친구"
L["Gold"] = true;
L["goldabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:1:16:1:16|t" --"|cffffd700●|r"
L["Hit"] = "적중도"
L["Hold Shift + Right Click:"] = true;
L["Home Latency:"] = "지연 시간:"
L["HP"] = "주문력"
L["HPS"] = "HPS"
L["lvl"] = "레벨"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "레벨별 데미지 경감률"
L["No Guild"] = "길드 없음"
L["Profit:"] = "이익:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "기록 리셋: Shift + 우클릭"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "귀속된 던전"
L["Server: "] = "서버:"
L["Session:"] = "현재 접속:"
L["silverabbrev"] = "|TInterface\\MoneyFrame\\UI-MoneyIcons:0:0:1:0:64:16:17:32:1:16|t" --"|cffc7c7cf●|r"
L["SP"] = "주문력"
L["Spell/Heal Power"] = true;
L["Spent:"] = "지출:"
L["Stats For:"] = "점수:"
L["System"] = true;
L["Total CPU:"] = "전체 CPU 사용량:"
L["Total Memory:"] = "전체 메모리:"
L["Total: "] = "합계:"
L["Unhittable:"] = "100% 방어행동까지"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s 기능이 사용할 수 없는 %s 함수를 사용하려 합니다."
L["No locals to dump"] = true; --Currently not used
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 유저가 필터설정을 전송하려 합니다. 받으시겠습니까?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 유저가 ElvUI 설정을 전송하려 합니다. 받으시겠습니까?"
L["Data From: %s"] = "%s 유저에게서 데이터 받는중..."
L["Filter download complete from %s, would you like to apply changes now?"] = "%s 유저에게서 필터 설정 다운로드가 완료되었습니다. 변경사항을 적용할까요?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "데이터를 받는 중 혼선이 생겼습니다. 다시 시도해주세요."
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "%s 유저에게서 ElvUI 설정 다운로드가 완료되었습니다. 하지만 건네받은 프로필 이름이 이미 존재합니다. 프로필이름을 바꾸지 않으면 기존의 것에 덮어씌웁니다."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "%s 유저에게서 ElvUI 설정 다운로드가 완료되었습니다. 건네받은 설정을 지금 불러올까요?"
L["Profile request sent. Waiting for response from player."] = "상대에게서 전송여부를 확인받고 있습니다."
L["Request was denied by user."] = "상대방이 전송을 거절했습니다."
L["Your profile was successfully recieved by the player."] = "상대에게 데이터를 성공적으로 전송했습니다."
--Install
L["Aura Bars & Icons"] = "바 & 아이콘 표시"
L["Auras Set"] = "오라설정 적용"
L["Auras"] = "오라 설정"
L["Caster DPS"] = "원거리 딜러"
L["Chat Set"] = "대화창 설정"
L["Chat"] = "대화창"
L["Choose a theme layout you wish to use for your initial setup."] = "UI의 전체적인 분위기를 선택하세요."
L["Classic"] = "클래식"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "원하는 해상도로 설정을 강제 적용하고자 한다면 아래에서 원하는 해상도를 선택하세요."
L["Config Mode:"] = "표시할 프레임 계열:"
L["CVars Set"] = "CVars 설정"
L["CVars"] = "게임 인터페이스 설정(CVars)"
L["Dark"] = "어두운 느낌"
L["Disable"] = "비활성화"
L["ElvUI Installation"] = "ElvUI 설치"
L["Finished"] = "마침"
L["Grid Size:"] = "격자 크기 :"
L["Healer"] = "힐러"
L["High Resolution"] = "고해상도 세팅"
L["high"] = ""
L["Icons Only"] = "아이콘만 표시"
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "표시하고 싶지 않은 버프/디버프가 보이면 아이콘을 Shift 우클릭하세요. 차단 목록에 등록되어 보이지 않게 됩니다."
L["Importance: |cff07D400High|r"] = "중요도: |cff07D400높음|r"
L["Importance: |cffD3CF00Medium|r"] = "중요도: |cffD3CF00보통|r"
L["Importance: |cffFF0000Low|r"] = "중요도 : |cffFF0000낮음|r"
L["Installation Complete"] = "설치 완료"
L["Layout Set"] = "레이아웃 설정"
L["Layout"] = "레이아웃"
L["Lock"] = "잠금"
L["Low Resolution"] = "저해상도 세팅"
L["low"] = ""
L["Nudge"] = "미세조정"
L["Physical DPS"] = "근접 딜러"
L["Please click the button below so you can setup variables and ReloadUI."] = "아래 버튼을 누르면 설치를 마무리하고 UI를 재시작합니다."
L["Please click the button below to setup your CVars."] = "ElvUI의 게임 인터페이스 설정을 적용하려면 아래 버튼을 클릭하세요."
L["Please press the continue button to go onto the next step."] = "|cff2eb7e4[계속]|r 버튼으로 설치를 진행하세요."
L["Resolution Style Set"] = "해상도 스타일 설정"
L["Resolution"] = "해상도"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "ElvUI 유닛프레임에서 표시할 오라(버프,디버프)의 형태를 선택하세요."
L["Setup Chat"] = "대화창 설치"
L["Setup CVars"] = "인터페이스 설정 적용"
L["Skip Process"] = "건너뛰기"
L["Sticky Frames"] = "자석"
L["Tank"] = "탱커"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "보편적인 설정을 적용할 뿐이므로, 마음대로 채널표시나 색상을 변경할 수 있습니다.|n아래 버튼을 클릭하면 채팅창 설정을 적용합니다."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "게임 내 설정창은 채팅창에 /ec를 입력하시거나 미니맵 옆의 C버튼을 클릭하면 열립니다. 그냥 사용하고자 한다면 아래의 |cff2eb7e4[건너뛰기]|r 버튼을 누르세요."
L["Theme Set"] = "테마 적용"
L["Theme Setup"] = "테마 설정"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "이 설치과정을 통해 ElvUI를 좀 더 자신에게 맞게 설정하고|n몇가지 기능에 대해 알 수 있습니다."
L["This is completely optional."] = "이것은 선택 사항입니다."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "채팅창 설정을 변경합니다. 간단한 채널설정, 색상설정 등이 포함되어 있습니다.|n자신만의 채널 설정, 색상 등을 유지하고 싶으면 설치하지 마세요."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "WoW의 기본 인터페이스 설정을 ElvUI에 적합하게 변경합니다. 애드온 사용에 있어 유용하니 적용할 것을 추천합니다."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "현재 해상도에 알맞게 UI가 배치될 것이니 설정을 변경할 필요는 없습니다."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "해상도에 알맞는 UI 배치를 적용하려면 몇가지 설정을 변경할 필요가 있습니다."
L["This will change the layout of your unitframes and actionbars."] = "역할에 따라서 유닛프레임과 행동단축바의 레이아웃이 알맞게 바뀝니다."
L["Trade"] = "거래"
L["Welcome to ElvUI version %s!"] = "ElvUI 버전 %s에 오신 것을 환영합니다!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "설치 과정이 끝났습니다.|n궁금한 점 해결이나 기술지원이 필요하면 |cff2eb7e4https://github.com/ElvUI-WotLK/ElvUI|r 를 방문하세요."
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "ElvUI에서 표시하는 폰트나 색상은 설정에서 언제든지 바꿀 수 있습니다."
L["You can now choose what layout you wish to use based on your combat role."] = "게임 안에서 주로 플레이하는 전문화 역할을 선택하세요."
L["You may need to further alter these settings depending how low you resolution is."] = "당신의 해상도가 얼마나 낮은지에 따라 설정을 더 조절해야할 수도 있습니다."
L["Your current resolution is %s, this is considered a %s resolution."] = "현재 사용중인 해상도는 |cff2eb7e4%s|r 이며, |cff2eb7e4%s해상도|r 입니다."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 정도 |cff%02x%02x%02x%s|r보다 많음]"
L["Bars"] = ""
L["Calendar"] = "달력"
L["Can't Roll"] = "주사위를 굴릴 수 없습니다."
L["Disband Group"] = "그룹 해산"
L["Empty Slot"] = true;
L["Enable"] = "사용"
L["Experience"] = "경험치"
L["Farm Mode"] = true;
L["Fishy Loot"] = "낚시 전리품"
L["Left Click:"] = "왼 클릭 :"
L["Raid Menu"] = "공대 도구"
L["Remaining:"] = "다음 레벨까지: "
L["Rested:"] = "휴식 경험치:"
L["Right Click:"] = "우클릭:"
L["Show BG Texts"] = "전장전용 정보문자 표시"
L["Toggle Chat Frame"] = "패널 표시 전환"
L["Toggle Configuration"] = "ElvUI 설정창 열기"
L["XP:"] = "경험치:"
L["You don't have permission to mark targets."] = "레이드 아이콘을 지정할 권한이 없습니다."
--Movers
L["Arena Frames"] = "투기장 프레임"
L["Bag Mover (Grow Down)"] = true;
L["Bag Mover (Grow Up)"] = true;
L["Bag Mover"] = true;
L["Bags"] = "가방"
L["Bank Mover (Grow Down)"] = true;
L["Bank Mover (Grow Up)"] = true;
L["Bar "] = ""
L["BNet Frame"] = "배틀넷 알림"
L["Boss Frames"] = "보스 프레임"
L["Classbar"] = "직업바"
L["Experience Bar"] = "경험치 바"
L["Focus Castbar"] = "주시대상 시전바"
L["Focus Frame"] = "주시대상 프레임"
L["FocusTarget Frame"] = "주시대상의 대상 프레임"
L["GM Ticket Frame"] = "GM요청 번호표"
L["Left Chat"] = "좌측 패널"
L["Loot / Alert Frames"] = "획득/알림 창"
L["Loot Frame"] = "전리품 프레임"
L["MA Frames"] = "지원공격 전담 프레임"
L["Micro Bar"] = "메뉴모음 바"
L["Minimap"] = "미니맵"
L["MirrorTimer"] = true;
L["MT Frames"] = "방어전담 프레임"
L["Party Frames"] = "파티 프레임"
L["Pet Bar"] = "소환수 바"
L["Pet Castbar"] = "소환수 시전바"
L["Pet Frame"] = "소환수 프레임"
L["PetTarget Frame"] = "소환수 대상 프레임"
L["Player Buffs"] = "플레이어 버프"
L["Player Castbar"] = "플레이어 시전바"
L["Player Debuffs"] = "플레이어 디버프"
L["Player Frame"] = "플레이어 프레임"
L["Player Powerbar"] = true;
L["PvP"] = true;
L["Raid Frames"] = "레이드 프레임"
L["Raid Pet Frames"] = "레이드 소환수 프레임"
L["Raid-40 Frames"] = "레이드 프레임(40인)"
L["Reputation Bar"] = "평판 바"
L["Right Chat"] = "우측 패널"
L["Stance Bar"] = "태세 바"
L["Target Castbar"] = "대상 시전바"
L["Target Frame"] = "대상 프레임"
L["Target Powerbar"] = true;
L["TargetTarget Frame"] = "대상의대상 프레임"
L["TargetTargetTarget Frame"] = "대상의대상의대상 프레임"
L["Time Manager Frame"] = true;
L["Tooltip"] = "툴팁"
L["Vehicle Seat Frame"] = "차량 좌석 프레임"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = true;
L["In Progress"] = true;
L["List of installations in queue:"] = true;
L["Pending"] = true;
L["Steps"] = true;
--Prints
L[" |cff00ff00bound to |r"] = " 키로 다음의 행동을 실행합니다: |cff2eb7e4"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s 의 위치 기준 프레임이 상충되고 있습니다. 서로가 서로의 위치를 참조하지 않게 버프나 디버프 중 하나의 위치를 바꿔주세요. 수정되기 전까지 강제로 유닛프레임이 기준으로 됩니다. "
L["All keybindings cleared for |cff00ff00%s|r."] = "|cff00ff00%s|r 버튼에 설정된 모든 단축키 설정이 해제되었습니다."
L["Already Running.. Bailing Out!"] = "이미 실행중입니다. 잠시만 기다려 주세요."
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "전장전용 정보문자를 일시적으로 표시하지 않습니다. 다시 보고 싶으면 |cffceff00/bgstats|r 나 미니맵에 있는 C 버튼을 우클릭하세요."
L["Battleground datatexts will now show again if you are inside a battleground."] = "전장전용 정보문자를 다시 표시합니다."
L["Binds Discarded"] = "방금 한 단축키 지정 작업을 저장하지 않고 취소했습니다."
L["Binds Saved"] = "단축키가 저장되었습니다."
L["Confused.. Try Again!"] = "작업에 혼선이 있었습니다. 다시 시도해 주세요."
L["No gray items to delete."] = "잡동사니가 없습니다."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "%s 주문이 차단 목록에 등록되었습니다."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
L["Vendored gray items for:"] = "모든 잡동사니를 팔았습니다:"
L["You don't have enough money to repair."] = "수리 비용이 부족합니다."
L["You must be at a vendor."] = "상인을 만나야 가능합니다."
L["Your items have been repaired for: "] = "자동으로 수리하고 비용을 지불했습니다:"
L["Your items have been repaired using guild bank funds for: "] = "길드자금으로 수리하고 비용을 지불했습니다:"
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "Lua 에러가 발생하였습니다. 전투가 끝난 후에 내역을 표시하겠습니다."
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "이 설정은 캐릭터별로 따로 저장되므로|n프로필에 영향을 주지도, 받지도 않습니다.|n|n설정 적용을 위해 리로드 하시겠습니까?"
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
L["Are you sure you want to delete all your gray items?"] = "모든 잡동사니를 버리겠습니까?"
L["Are you sure you want to disband the group?"] = "현재 그룹을 해산하시겠습니까?"
L["Are you sure you want to reset all the settings on this profile?"] = "현재 사용중인 프로필을 초기화 하시겠습니까?"
L["Are you sure you want to reset every mover back to it's default position?"] = "모든 프레임을 기본 위치로 초기화 하시겠습니까?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "새로운 오라시스템을 혼란스러워 하는 분들이 많아 설치과정에 관련 페이지를 추가했습니다. 해도 되고 안해도 됩니다. 이미 스스로 오라시스템을 구축했으면 그냥 설치를 마지막까지 넘겨 종료하세요."
L["Can't buy anymore slots!"] = "더 이상 가방 칸을 늘릴 수 없습니다."
L["Disable Warning"] = "비활성화 경고"
L["Discard"] = "작업 취소"
L["Do you enjoy the new ElvUI?"] = "만우절 기능이었습니다! 이대로 쓰실래요?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "두 애드온을 병행하여 생기는 문제를 스스로 감수하며 관련 질문글을 올리지 마세요."
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "현재 사용하는 ElvUI가 5버전 이상 뒤쳐진 버전입니다. https://github.com/ElvUI-WotLK/ElvUI/ 에서 새 버전을 다운로드 받으세요."
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI가 오래된 버전입니다. https://github.com/ElvUI-WotLK/ElvUI/ 에서 새 버전을 다운로드 받으세요."
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI의 데이터베이스를 조정할 필요가 있습니다. 잠시 기다려주세요."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "행동단축바나 주문책의 스킬에 마우스오버 후 키를 누르면 단축키로 지정합니다. 단축키를 지정한 곳을 우클릭 하거나 ESC를 누르면 해제합니다."
L["I Swear"] = "알겠습니다."
L["No, Revert Changes!"] = "예전으로 돌려주세요"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "ElvUI 와 TukUI 를 동시에 사용하려 하고 있습니다. 하나만 선택해 주세요."
L["One or more of the changes you have made require a ReloadUI."] = "변경 사항을 적용하려면 애드온을 리로드 해야합니다."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "이 설정은 모든 캐릭터에게 동일하게 적용됩니다.|n|n설정 적용을 위해 리로드 하시겠습니까?"
L["Save"] = "저장"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
L["Type /hellokitty to revert to old settings."] = "/hellokitty 를 입력해서 예전 세팅으로 돌릴 수 있습니다."
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "힐러 레이아웃을 사용할 거라면 Clique 애드온을 같이 써 클릭캐스팅 기능을 이용할 것을 강력히 추천합니다."
L["Yes, Keep Changes!"] = "네! 이대로 할래요!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Thin Border Theme 선택을 바꾸었습니다. 설치과정을 끝까지 밟아 그래픽 관련 버그를 미연에 방지하는 걸 추천합니다."
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "UI 배율이 변경되었지만 ElvUI의 UI크기 자동조절 기능이 켜져있습니다. UI크기 자동조절 기능을 끄고 싶다면 '수락'을 누르세요."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
L["You must purchase a bank slot first!"] = "우선 은행가방 칸을 구입해야됩니다!"
--Tooltip
L["Count"] = "갯수"
L["Item Level:"] = "템렙:"
L["Talent Specialization:"] = "특성:"
L["Targeted By:"] = "선택됨:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "단축키 설정의 맨 아래에 있는 ElvUI 부분에서 |cff2eb7e4[Raid Marker]|r 기능을 사용하면 대상에게 징표를 간단히 찍을 수 있습니다."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "각 전문화별로 ElvUI 설정을 따로 지정할 수 있습니다. 설정의 프로필 항목에 |cff2eb7e4[이중 프로필 사용]|r 기능을 확인하세요."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "궁금한 사항이나 기술지원은 |cff2eb7e4https://github.com/ElvUI-WotLK/ElvUI|r에서 해결하세요."
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "ElvUI 에서 지원하는 대부분의 기능은 |cff2eb7e4/ec|r 에서 조정이 가능합니다. 하고 싶은 조절 기능이 없다면 직접 lua수정으로 고쳐야 합니다."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "ElvUI에서 지원하는 기능과 겹치는 다른 애드온을 쓰고 싶으면 ElvUI 설정에서 해당 기능을 사용 체크해제 해야합니다. (예: Bartender, Dominos)"
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "ElvUI의 특정 기능만 따로 독립애드온으로 분리하는 것은 불가능합니다."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "기본적으로 단축바에서 스킬을 뺄려면 |cff2eb7e4Shift 키를 누른 상태에서 드래그|r해야 합니다. 수정키는 /ec -> 행동단축바 항목에서 바꿀 수 있습니다."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "채팅창에 표시할 채널은 채팅탭을 우클릭하면 뜨는 메뉴의 설정에서 변경할 수 있습니다."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "채팅창 우측상단의 문서 아이콘을 클릭하면 대화 내역을 복사할 수 있습니다. 우클릭하면 채팅에 관련된 메뉴가 나옵니다."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "/ec -> 툴팁 항목에서 |cff2eb7e4[특성/아이템레벨 표시]|r 기능을 체크하고 Shift를 누른 상태로 마우스를 대면 그 유저의 템렙과 특성을 툴팁에 표시합니다."
L["You can set your keybinds quickly by typing /kb."] = "|cff2eb7e4/kb|r 를 입력하면 간편하게 단축키를 설정할 수 있는 기능이 실행됩니다."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "미니맵을 휠버튼클릭 하거나 행동단축바 설정으로 각종 메뉴버튼을 볼 수 있습니다."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "|cff2eb7e4/resetui|r 입력으로 움직였던 모든 프레임의 위치를 초기화할 수 있습니다. |cff2eb7e4 /resetui 프레임이름|r 으로 특정 프레임만 초기화도 가능합니다."
--UnitFrames
L["Dead"] = true;
L["Ghost"] = "유령"
L["Offline"] = "오프라인"
@@ -0,0 +1,11 @@
<UI xmlns="http://www.blizzard.com/wow/UI/">
<Script file="English_UI.lua"/>
<Script file="French_UI.lua"/>
<Script file="Russian_UI.lua"/>
<Script file="German_UI.lua"/>
<Script file="Taiwanese_UI.lua"/>
<Script file="Spanish_UI.lua"/>
<Script file="Korean_UI.lua"/>
<Script file="Chinese_UI.lua"/>
<Script file="Portuguese_UI.lua"/>
</UI>
+346
View File
@@ -0,0 +1,346 @@
-- Portuguese localization file for ptBR.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "ptBR")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
--*_MSG locales
L["LOGIN_MSG"] = "Bem vindo à versão %s%s|r da %sElvUI|r, escreva /ec para acessar o menu de configuração em jogo. Se precisar de suporte técnico visite-nos no site https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "Ligações"
L["Key"] = "Tecla"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "Sem atalhos definidos"
L["Remove Bar %d Action Page"] = "Remover paginação de ação da barra %d."
L["Trigger"] = "Gatilho"
--Bags
L["Bank"] = true;
L["Hold Control + Right Click:"] = "Segurar Control + Clique Direito:"
L["Hold Shift + Drag:"] = "Segurar Shift + Arrastar:"
L["Purchase Bags"] = true;
L["Reset Position"] = "Redefinir Posição"
L["Sort Bags"] = "Organizar Bolsas"
L["Temporary Move"] = "Mover Temporariamente"
L["Toggle Bags"] = "Mostrar/Ocultar Bolsas"
L["Toggle Key"] = true;
L["Vendor Grays"] = "Vender Itens Cinzentos"
--Chat
L["AFK"] = "LDT"
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "NP"
L["G"] = "G"
L["Invalid Target"] = "Alvo inválido"
L["O"] = "O"
L["P"] = "P"
L["PL"] = "PL"
L["R"] = "R"
L["RL"] = "RL"
L["RW"] = "AR"
L["says"] = "diz"
L["whispers"] = "sussurra"
L["yells"] = "grita"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(Segurar Shift) Memória em Uso"
L["Avoidance Breakdown"] = "Separação de Anulação"
L["Character: "] = "Personagem: "
L["Chest"] = "Torso"
L["Combat"] = true;
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55fc|r"
L["Deficit:"] = "Défice:"
L["DPS"] = "DPS"
L["Earned:"] = "Ganho:"
L["Friends List"] = "Lista de Amigos"
L["Friends"] = "Amigos"
L["Gold"] = true;
L["goldabbrev"] = "|cffffd700g|r"
L["Hit"] = "Acerto"
L["Hold Shift + Right Click:"] = true;
L["Home Latency:"] = "Latência de Casa:"
L["HP"] = "PV"
L["HPS"] = "PVS"
L["lvl"] = "nível"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "Mitigação por nível"
L["No Guild"] = "Sem Guilda"
L["Profit:"] = "Lucro:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "Redefinir Dados: Segurar Shifr + Clique Direito"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "Raide(s) Salva(s)"
L["Server: "] = "Servidor: "
L["Session:"] = "Sessão:"
L["silverabbrev"] = "|cffc7c7cfs|r"
L["SP"] = "PM"
L["Spell/Heal Power"] = true;
L["Spent:"] = "Gasto:"
L["Stats For:"] = "Estatísticas para:"
L["System"] = true;
L["Total CPU:"] = "CPU Total:"
L["Total Memory:"] = "Memória Total:"
L["Total: "] = "Total: "
L["Unhittable:"] = "Inacertável"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s tentou chamar a função protegida '%s'."
L["No locals to dump"] = "Sem locais para despejar"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s está tentando compartilhar os filtros dele com você. Gostaria de aceitar o pedido?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s está tentando compartilhar o perfil %s com você. Gostaria de aceitar o pedido?"
L["Data From: %s"] = "Dados De: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "Baixa de filtros de %s completada, gostaria de aplicar as alterações agora?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Senhor! É um milagre! O Download sumiu como um peido no vento! Tente novamente!"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Baixa de perfil completada de %s, mas o perfil %s já existe. Altere o nome ou ele irá sobrescrever o perfil existente."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "Baixa de perfil completada de %s, gostaria de carregar o perfil %s agora?"
L["Profile request sent. Waiting for response from player."] = "Pedido de perfil enviado. Aguardando a resposta do jogador."
L["Request was denied by user."] = "Pedido negado pelo usuário."
L["Your profile was successfully recieved by the player."] = "Seu perfil foi recebido com sucesso pelo jogador."
--Install
L["Aura Bars & Icons"] = true;
L["Auras Set"] = "Auras configuradas"
L["Auras"] = true;
L["Caster DPS"] = "DPS Lançador"
L["Chat Set"] = "Bate-Papo configurado"
L["Chat"] = "Bate-papo"
L["Choose a theme layout you wish to use for your initial setup."] = "Escolha o tema de layout que deseje usar inicialmente."
L["Classic"] = "Clássico"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Clique no botão abaixo para redimensionar os seus quadros de bate-papo, quadros de unidades, e reposicionar as suas barras de ações."
L["Config Mode:"] = "Modo de configuração"
L["CVars Set"] = "CVars configuradas"
L["CVars"] = "CVars"
L["Dark"] = "Escuro"
L["Disable"] = "Desativar"
L["ElvUI Installation"] = "Instalação do ElvUI"
L["Finished"] = "Terminado"
L["Grid Size:"] = "Tamanho da Grade"
L["Healer"] = "Curandeiro"
L["High Resolution"] = "Alta Resolução"
L["high"] = "alto"
L["Icons Only"] = "Apenas Ícones"
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Se existir um ícone ou uma barra de aura que você não queira ver exibida simplesmente mantenha pressionada a tecla Shift e clique no ícone com o botão direito para que o ícone/barra de aura desapareça."
L["Importance: |cff07D400High|r"] = "Importância: |cff07D400Alta|r"
L["Importance: |cffD3CF00Medium|r"] = "Importância: |cffD3CF00Média|r"
L["Importance: |cffFF0000Low|r"] = "Importância: |cffFF0000Baixa|r"
L["Installation Complete"] = "Instalação Completa"
L["Layout Set"] = "Definições do Layout"
L["Layout"] = "Layout"
L["Lock"] = "Travar"
L["Low Resolution"] = "Baixa Resolução"
L["low"] = "baixo"
L["Nudge"] = "Ajuste fino"
L["Physical DPS"] = "DPS Físico"
L["Please click the button below so you can setup variables and ReloadUI."] = "Por favor, clique no botão abaixo para que possa configurar as variáveis e Recarregar a IU."
L["Please click the button below to setup your CVars."] = "Por favor, clique no botão abaixo para configurar as suas Cvars."
L["Please press the continue button to go onto the next step."] = "Por favor, pressione o botão Continuar para passar à próxima etapa."
L["Resolution Style Set"] = "Estilo de Resolução defenido"
L["Resolution"] = "Resolução"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = true;
L["Setup Chat"] = "Configurar Bate-papo"
L["Setup CVars"] = "Configurar CVars"
L["Skip Process"] = "Pular Processo"
L["Sticky Frames"] = "Quadros Pegadiços"
L["Tank"] = "Tanque"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "As janelas de bate-papo funcionam da mesma forma das da Blizzard, você pode usar o botão direito nas guias para os arrastar, mudar o nome, etc. Por favor clique no botão abaixo para configurar as suas janelas de bate-papo"
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "O modo configuração em jogo pode ser acessado escrevendo o comando /ec ou clicando no botão 'C' no minimapa. Pressione o botão abaixo se desejar pular o processo de instalação"
L["Theme Set"] = "Tema configurado"
L["Theme Setup"] = "Configuração do Tema"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Este processo de instalação vai mostrar-lhe algumas das opções que a ElvUI tem para oferecer e também vai preparar a sua interface para ser usada."
L["This is completely optional."] = "Isto é completamente opcional."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "Esta parte da instalação é para definir os nomes, posições e cores das suas janelas de bate-papo."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Esta parte da instalação serve para definir as suas opcões padrão do WoW, é recomendado fazer isto para que tudo funcione corretamente."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Esta resolução não exige que altere as definições para que a interface caiba no seu ecrã (monitor)."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Esta resolução requer que altere algumas definições para que tudo caiba no seu ecrã (monitor)."
L["This will change the layout of your unitframes and actionbars."] = true;
L["Trade"] = "Comércio"
L["Welcome to ElvUI version %s!"] = "Bem-vindo à versão %s da ElvUI!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "O processo de instalação está agora terminado. Se precisar de suporte técnico por favor visite-nos no site https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "As cores e fontes da ElvUI podem ser mudadas em qualquer momento no modo de configuração demtro do jogo."
L["You can now choose what layout you wish to use based on your combat role."] = "Pode agora escolher o layout que pretende usar baseado no seu papel."
L["You may need to further alter these settings depending how low you resolution is."] = "Poderá ter de alterar estas definições dependendo de quão baixa for a sua resolução."
L["Your current resolution is %s, this is considered a %s resolution."] = "A sua resolução actual é %s, esta é considerada uma resolução %s."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
L["Bars"] = "Barras"
L["Calendar"] = "Calendário"
L["Can't Roll"] = "Não pode rolar"
L["Disband Group"] = "Dissolver Grupo"
L["Empty Slot"] = true;
L["Enable"] = "Ativar"
L["Experience"] = "Experiência"
L["Farm Mode"] = true;
L["Fishy Loot"] = "Saque de Peixes"
L["Left Click:"] = "Clique Esquerdo:"
L["Raid Menu"] = "Menu de Raide"
L["Remaining:"] = "Restante:"
L["Rested:"] = "Descansado:"
L["Right Click:"] = "Clique Direito:"
L["Show BG Texts"] = "Mostrar Textos do CB"
L["Toggle Chat Frame"] = "Mostrar/Ocultar Bat-papo"
L["Toggle Configuration"] = "Mostrar/Ocultar Modo de Configuração"
L["XP:"] = "XP:"
L["You don't have permission to mark targets."] = "Você não tem permissão para marcar alvos."
--Movers
L["Arena Frames"] = "Quadros de Arenas"
L["Bag Mover (Grow Down)"] = true;
L["Bag Mover (Grow Up)"] = true;
L["Bag Mover"] = true;
L["Bags"] = "Bolsas"
L["Bank Mover (Grow Down)"] = true;
L["Bank Mover (Grow Up)"] = true;
L["Bar "] = "Barra "
L["BNet Frame"] = "Quadro do Bnet"
L["Boss Frames"] = "Quadros dos Chefes"
L["Classbar"] = "Barra da Classe"
L["Experience Bar"] = "Barra de Experiência"
L["Focus Castbar"] = "Barra de Lançamento do Foco"
L["Focus Frame"] = "Quadro do Foco"
L["FocusTarget Frame"] = "Quadro do Alvo do Foco"
L["GM Ticket Frame"] = "Quadro de Consulta com GM"
L["Left Chat"] = "Bate-papo esquerdo"
L["Loot / Alert Frames"] = "Quadro de Saque / Alerta"
L["Loot Frame"] = true;
L["MA Frames"] = "Quadro do Assistente Principal"
L["Micro Bar"] = "Micro Barra"
L["Minimap"] = "Minimapa"
L["MirrorTimer"] = true;
L["MT Frames"] = "Quadro do Tank Principal"
L["Party Frames"] = "Quadros de Grupo"
L["Pet Bar"] = "Barra do Ajudante"
L["Pet Castbar"] = true;
L["Pet Frame"] = "Quadro do Ajudante"
L["PetTarget Frame"] = "Quadro do Alvo do Ajudante"
L["Player Buffs"] = true;
L["Player Castbar"] = "Barra de lançamento do Jogador"
L["Player Debuffs"] = true;
L["Player Frame"] = "Quadro do Jogador"
L["Player Powerbar"] = true;
L["PvP"] = true;
L["Raid Frames"] = true;
L["Raid Pet Frames"] = true;
L["Raid-40 Frames"] = true;
L["Reputation Bar"] = "Barra de Reputação"
L["Right Chat"] = "Bate-papo direito"
L["Stance Bar"] = "Barra de Postura"
L["Target Castbar"] = "Barra de lançamento do Alvo"
L["Target Frame"] = "Quadro do Alvo"
L["Target Powerbar"] = true;
L["TargetTarget Frame"] = "Quadro do Alvo do Alvo"
L["TargetTargetTarget Frame"] = true;
L["Time Manager Frame"] = true;
L["Tooltip"] = "Tooltip"
L["Vehicle Seat Frame"] = "Quadro de Assento de Veículo"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = true;
L["In Progress"] = true;
L["List of installations in queue:"] = true;
L["Pending"] = true;
L["Steps"] = true;
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00Ligado a |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "%s quadro(s) tem um ponto de fixação em conflito, por favor mude o ponto de fixação do quadro de bônus ou de penalidades para que eles não fiquem ligados uns aos outros. Forçando as penalidades a ficarem anexadas ao quadro principal até que sejam consertados."
L["All keybindings cleared for |cff00ff00%s|r."] = "Todos os atalhos livres para"
L["Already Running.. Bailing Out!"] = "Já está executando... Cancelando a ordenação!"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Os textos Informativos dos Campos de Batalha estão temporáriamente ocultos, para serem mostrados digite /bgstats ou clique direito no ícone 'C' perto do minimapa."
L["Battleground datatexts will now show again if you are inside a battleground."] = "Os textos Informativos irão agora ser mostrados se estiver dentro de um Campo de Batalha."
L["Binds Discarded"] = "Ligações Descartadas"
L["Binds Saved"] = "Ligações Salvas"
L["Confused.. Try Again!"] = "Confuso... Tente novamente!"
L["No gray items to delete."] = "Nenhum item cinzento para destruir."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "O feitiço '%s' foi adicionado à Lista Negra dos filtros das auras de unidades."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = true;
L["Vendored gray items for:"] = "Vendeu os itens cinzentos por:"
L["You don't have enough money to repair."] = "Você não tem dinheiro suficiente para reparar."
L["You must be at a vendor."] = "Tem de estar num vendedor."
L["Your items have been repaired for: "] = "Seus itens foram reparadas por: "
L["Your items have been repaired using guild bank funds for: "] = "Seus itens foram reparados usando fundos do banco da guilda por: "
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Erro Lua recebido. Pode ver a mensagem de erro quando sair de combate"
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "A definição que você alterou afetará apenas este personagem. Esta definição que você alterou não será afetada por mudanças de perfil. Alterar esta difinição requer que você recarregue a sua interface."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
L["Are you sure you want to delete all your gray items?"] = "Tem a certeza de que deseja destruir todos os seus itens cinzentos?"
L["Are you sure you want to disband the group?"] = "Tem a certeza de que quer dissolver o grupo?"
L["Are you sure you want to reset all the settings on this profile?"] = "Tem certeza que quer redefinir todas as configurações desse perfil?"
L["Are you sure you want to reset every mover back to it's default position?"] = "Tem a certeza de que deseja restaurar todos os movedores de volta para a sua posição padrão?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Devido à grande confusão causada pelo novo sistema de auras foi implementado um novo passo no processo de instalação. Este passo é opcional, se você gosta da maneira que as suas auras estão configuradas vá para o último passo e clique em Terminado para não ser solicitado a configurar este passo novamente. Se por algum motivo for repetidamente solicitado a fazê-lo, por favor reinicie o seu jogo."
L["Can't buy anymore slots!"] = "Não é possível comprar mais espaços!"
L["Disable Warning"] = "Desativar Aviso"
L["Discard"] = "Descartar"
L["Do you enjoy the new ElvUI?"] = true;
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Você jura não postar no suporte técnico sobre alguma coisa não funcionando sem antes desabilitar a combinação addon/módulo?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = true;
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = true;
L["ElvUI needs to perform database optimizations please be patient."] = true;
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Paire com o seu rato (mouse) sobre qualquer botão de ação ou botão do grimório para fazer uma Ligação. Pressione a tecla Escape ou clique com o botão direito para limpar o atalho atual."
L["I Swear"] = "Eu Juro"
L["No, Revert Changes!"] = true;
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh senhor, você está com os addons ElvUI e Tuki ativos ao mesmo tempo. Selecione um para desativar."
L["One or more of the changes you have made require a ReloadUI."] = "Uma ou mais das alterações que fez requerem que recarregue a IU."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Uma ou mais das alterações que fez afetará todos os personagens que usam este addon. Você terá que recarregar a interface para ver as alterações que fez."
L["Save"] = "Salvar"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = true;
L["Type /hellokitty to revert to old settings."] = true;
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Ao usar o leioute de curandeiro é altamente recomendado que você baixe o addon Clique se quiser ter a função de clicar-para-curar."
L["Yes, Keep Changes!"] = true;
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = true;
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Você mudou a Escala da sua IU, no entanto ainda tem a opção de dimensionamento automático ativa na ElvUI. Pressione Aceitar se gostaria de desativar a opção de dimensionamento automático."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = true;
L["You must purchase a bank slot first!"] = "Você deve comprar um espaço no banco primeiro!"
--Tooltip
L["Count"] = "Contar"
L["Item Level:"] = true;
L["Talent Specialization:"] = true;
L["Targeted By:"] = "Sendo Alvo de:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "A opção Marcas de Raide está disponivel pressionando Escape -> Teclas de Atalho, rolando tudo para o fundo debaixo de ElvUI e definindo uma tecla de atalho para o Raid Marker."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "A ElvUI contém o modo de duas especializações, que permite que carregue perfis diferentes baseado na sua especialização atual rapidamente. Você pode ativar esta opção na guia Perfis."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Para suporte técnico visite-nos no site https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Se acidentalmente remover um quadro de conversação você pode sempre ir ao menu de configuração em jogo, pressionar instalar, ir até a etapa de bate-papo e os restaurar."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Se estiver a ter problemas com a ElvUI tente desativar todos os addons exceto a ElvUI, lembre-se que a ElvUI é um addon de substituição de interface completo, e não se consegue executar dois addons que fazem a mesma coisa."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "A unidade de Foco pode ser definida escrevendo /focus quando voce tem no alvo a unidade que quer tal. É recomendado que faça uma macro para este efeito."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Para mover habilidades nas barras de ação (modo padrão) mantenha pressionado Shift enquanto arrasta. Você pode mudar a tecla no menu de opções das barras de ações."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Para configurar que canais aparecem em cada quadro de conversação, clique com o botão direito no guia do bate-papo e vá a configurações."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Você pode acessar ao 'copiar bate-papo' e ao menu de funções do bate-papo passando com o rato (mouse) no canto superior direito do painel e clicando botão esquerdo/direito no botão que irá aparecer."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Você pode ver o nivel médio de itens que outra pessoa tem mantendo shift pressionado e passando com o rato (mouse) por cima deles. Deverá aparecer na tooltip."
L["You can set your keybinds quickly by typing /kb."] = "Você pode definir os seus atalhos rapidamente escrevendo /kb."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Você pode ativar a micro barra clicando no minimapa com o seu botão do meio do rato (mouse), pode também conseguir isto ativando a verdadeira micro barra nas definições das barras de ações."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "Você pode usar o comando /resetui para restaurar todos os movedores. Pode usar este comando também para restaurar um movedor especifico escrevendo /resetui <nome do movedor> \nExemplo: /resetui Player Frame"
--UnitFrames
L["Dead"] = true;
L["Ghost"] = "Fantasma"
L["Offline"] = "Desconectado"
+346
View File
@@ -0,0 +1,346 @@
-- Russian localization file for ruRU.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "ruRU")
if not L then return; end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "Аддон %s не совместим с модулем %s ElvUI. Пожалуйста, выберите отключить ли несовместимый аддон или модуль."
--*_MSG locales
L["LOGIN_MSG"] = "Добро пожаловать в %sElvUI|r версии %s%s|r, наберите /ec для доступа в меню настроек. Если Вам нужна техническая поддержка, посетите https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "Назначение"
L["Key"] = "Клавиша"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "Нет назначений"
L["Remove Bar %d Action Page"] = "Удалить панель %d из списка переключаемых"
L["Trigger"] = "Триггер"
--Bags
L["Bank"] = "Банк"
L["Hold Control + Right Click:"] = "Зажать Control + ПКМ:"
L["Hold Shift + Drag:"] = "Зажать shift и перетаскивать:"
L["Purchase Bags"] = "Приобрести слот"
L["Reset Position"] = "Сбросить позицию"
L["Sort Bags"] = "Сортировать"
L["Temporary Move"] = "Временное перемещение"
L["Toggle Bags"] = "Показать сумки"
L["Toggle Key"] = "Показать ключи"
L["Vendor Grays"] = "Продавать серые предметы"
--Chat
L["AFK"] = "АФК" --Also used in datatexts and tooltip
L["BG"] = "ПБ"
L["BGL"] = "Лидер ПБ"
L["DND"] = "ДНД" --Also used in datatexts and tooltip
L["G"] = "Г"
L["Invalid Target"] = "Неверная цель"
L["O"] = "Оф"
L["P"] = "Гр"
L["PL"] = "Лидер гр."
L["R"] = "Р"
L["RL"] = "РЛ"
L["RW"] = "Объявление"
L["says"] = "говорит"
L["whispers"] = "шепчет"
L["yells"] = "кричит"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(Зажать Shift) Использование памяти"
L["Avoidance Breakdown"] = "Распределение защиты"
L["Character: "] = "Персонаж: "
L["Chest"] = "Грудь"
L["Combat"] = "Бой"
L["Combat Time"] = "В бою"
L["Coords"] = "Коорд."
L["copperabbrev"] = "|cffeda55fм|r" --Also used in Bags
L["Deficit:"] = "Убыток:"
L["DPS"] = "УВС"
L["Earned:"] = "Заработано"
L["Friends List"] = "Список друзей"
L["Friends"] = "Друзья" --Also in Skins
L["Gold"] = "Золото"
L["goldabbrev"] = "|cffffd700з|r" --Also used in Bags
L["Hit"] = "Метк."
L["Hold Shift + Right Click:"] = "Shift + ПКМ:"
L["Home Latency:"] = "Локальная задержка: "
L["HP"] = "+ Исцел."
L["HPS"] = "ИВС"
L["lvl"] = "ур."
L["Miss Chance"] = "Вероятность промаха"
L["Mitigation By Level: "] = "Снижение на уровне: "
L["No Guild"] = "Нет гильдии"
L["Profit:"] = "Прибыль:"
L["Reload UI"] = "Перезагрузка"
L["Reset Data: Hold Shift + Right Click"] = "Сбросить данные: Shift + ПКМ"
L["Right Click: Reset CPU Usage"] = "ПКМ: Сбросить использование процессора"
L["Saved Raid(s)"] = "Сохраненные рейды"
L["Server: "] = "На сервере:"
L["Session:"] = "За сеанс:"
L["silverabbrev"] = "|cffc7c7cfс|r" --Also used in Bags
L["SP"] = "+ Закл."
L["Spell/Heal Power"] = "Сила заклинаний"
L["Spent:"] = "Потрачено:"
L["Stats For:"] = "Статистика для:"
L["System"] = "Система"
L["Total CPU:"] = "Использование процессора:"
L["Total Memory:"] = "Всего памяти:"
L["Total: "] = "Всего: "
L["Unhittable:"] = "Полная защита от ударов"
L["Wintergrasp"] = "Озеро Ледяных Оков"
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s tried to call the protected function '%s'."
L["No locals to dump"] = "No locals to dump"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s хочет передать Вам свои фильтры. Желаете ли Вы принять их?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s хочет передать Вам профиль %s. Желаете ли Вы принять его?"
L["Data From: %s"] = "Данные от: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "Завершена загрузка фильтров от %s. Желаете применить изменения сейчас?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "Чтоб его! Загрузка была... да всплыла. Попробуйте еще раз!"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Загрузка профиля от %s завершена, но профиль %s уже существует. Измените его название или он перезапишет уже существующий профиль."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "Загрузка профиля от %s завершена, хотите загрузить профиль %s сейчас?"
L["Profile request sent. Waiting for response from player."] = "Запрос на передачу профиля отправлен. Ждите, пожалуйста, ответа."
L["Request was denied by user."] = "Запрос отклонен пользователем."
L["Your profile was successfully recieved by the player."] = "Ваш профиль успешно получен целью. Ура, товарищи!"
--Install
L["Aura Bars & Icons"] = "Полосы аур и иконки"
L["Auras Set"] = "Ауры установлены"
L["Auras"] = "Ауры"
L["Caster DPS"] = "Заклинатель"
L["Chat Set"] = "Чат настроен"
L["Chat"] = "Чат"
L["Choose a theme layout you wish to use for your initial setup."] = "Выберите тему, которую Вы хотите использовать."
L["Classic"] = "Классическая"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Нажмите кнопку ниже для изменения размеров вашего чата, рамок юнитов и перемещения ваших панелей действий."
L["Config Mode:"] = "Режим настройки:"
L["CVars Set"] = "Настройки сброшены"
L["CVars"] = "Настройки игры"
L["Dark"] = "Темная"
L["Disable"] = "Выключить"
L["ElvUI Installation"] = "Установка ElvUI"
L["Finished"] = "Завершить"
L["Grid Size:"] = "Размер сетки"
L["Healer"] = "Лекарь"
L["High Resolution"] = "Высокое разрешение"
L["high"] = "высоким"
L["Icons Only"] = "Только иконки" --Also used in Bags
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Если Вы видите иконку или полосу аур, которую Вы не хотите отображать, просто зажмите shift и кликните на иконке правой кнопкой, чтобы она исчезла."
L["Importance: |cff07D400High|r"] = "Важность: |cff07D400Высокая|r"
L["Importance: |cffD3CF00Medium|r"] = "Важность: |cffD3CF00Средняя|r"
L["Importance: |cffFF0000Low|r"] = "Важность: |cffFF0000Низкая|r"
L["Installation Complete"] = "Установка завершена"
L["Layout Set"] = "Расположение установлено"
L["Layout"] = "Расположение"
L["Lock"] = "Закрепить"
L["Low Resolution"] = "Низкое разрешение"
L["low"] = "низким"
L["Nudge"] = "Сдвиг"
L["Physical DPS"] = "Физический урон"
L["Please click the button below so you can setup variables and ReloadUI."] = "Пожалуйста, нажмите кнопку ниже для установки переменных и перезагрузки интерфейса."
L["Please click the button below to setup your CVars."] = "Пожалуйста, нажмите кнопку ниже для сброса настроек."
L["Please press the continue button to go onto the next step."] = "Пожалуйста, нажмите кнопку 'Продолжить' для перехода к следующему шагу"
L["Resolution Style Set"] = "Разрешение установлено"
L["Resolution"] = "Разрешение"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Выберите тип системы аур, который Вы хотите использовать на рамках юнитов ElvUI. 'Полосы аур и иконки' включит и полосы и иконки, выберите 'Только иконки', чтобы видеть только их."
L["Setup Chat"] = "Настроить чат"
L["Setup CVars"] = "Сбросить настройки"
L["Skip Process"] = "Пропустить установку"
L["Sticky Frames"] = "Клейкие фреймы"
L["Tank"] = "Танк"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Окна чата работают так же, как и в стандартном чате Blizzard. Вы можете нажать правую кнопку мыши на вкладках для перемещения, переименования и тд. Пожалуйста, нажмите кнопку ниже для настройки чата."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "Меню настроек можно вызвать командой /ес или кнопкой 'С' на миникарте. Нажмите кнопку ниже, если Вы хотите прервать процесс установки."
L["Theme Set"] = "Тема установлена"
L["Theme Setup"] = "Тема"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "Этот процесс установки поможет Вам узнать о некоторых функциях ElvUI и подготовить Ваш интерфейс к использованию."
L["This is completely optional."] = "Это действие абсолютно не обязательно."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "Эта часть установки настроит названия, позиции и цвета вкладок чата."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Эта часть установки сбросит настройки World of Warcraft на конфигурацию по умолчанию. Рекомендуется выполнить этот шаг для надлежащей работы интерфейса."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Для соответствия интерфейса вашему экрану не требуется изменения настроек."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Для соответствия интерфейса вашему экрану требуется изменение некоторых настроек."
L["This will change the layout of your unitframes and actionbars."] = "Это изменит расположение ваших рамок юнитов, рейда и панелей команд."
L["Trade"] = "Торговля"
L["Welcome to ElvUI version %s!"] = "Добро пожаловать в ElvUI версии %s!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Вы завершили процесс установки. Если Вам требуется техническая поддержка, посетите https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Вы всегда можете изменить шрифты и цвета любого элемента ElvUI из меню конфигурации. Классическая и пиксельная темы не отличаются для русского клиента."
L["You can now choose what layout you wish to use based on your combat role."] = "Вы можете выбрать используемое расположение, основываясь на Вашей роли."
L["You may need to further alter these settings depending how low you resolution is."] = "Вам может понадобиться дальнейшее изменение этих настроек в зависимости от того, насколько низким является ваше разрешение."
L["Your current resolution is %s, this is considered a %s resolution."] = "Ваше текущее разрешение - %s, это считается %s разрешением."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [на %.0f%% опережаем |cff%02x%02x%02x%s|r]"
L["Bars"] = "Полосы" --Also used in UnitFrames
L["Calendar"] = "Календарь"
L["Can't Roll"] = "Не могу бросить кости"
L["Disband Group"] = "Распустить группу"
L["Empty Slot"] = "Пустой слот"
L["Enable"] = "Включить" --Doesn't fit a section since it's used a lot of places
L["Experience"] = "Опыт"
L["Farm Mode"] = "Режим фарма"
L["Fishy Loot"] = "Улов"
L["Left Click:"] = "ЛКМ:" --layout\layout.lua
L["Raid Menu"] = "Рейдовое меню"
L["Remaining:"] = "Осталось:"
L["Rested:"] = "Бодрость:"
L["Right Click:"] = "ПКМ:" --layout\layout.lua
L["Show BG Texts"] = "Показать текст ПБ" --layout\layout.lua
L["Toggle Chat Frame"] = "Показать/скрыть чат" --layout\layout.lua
L["Toggle Configuration"] = "Конфигурация" --layout\layout.lua
L["XP:"] = "Опыт:"
L["You don't have permission to mark targets."] = "У вас нет разрешения на установку меток"
--Movers
L["Arena Frames"] = "Арена" --Also used in UnitFrames
L["Bag Mover (Grow Down)"] = "Сумки (Рост вниз)"
L["Bag Mover (Grow Up)"] = "Сумки (Рост вверх)"
L["Bag Mover"] = "Фиксатор сумок"
L["Bags"] = "Сумки" --Also in DataTexts
L["Bank Mover (Grow Down)"] = "Банк (Рост вниз)"
L["Bank Mover (Grow Up)"] = "Банк (Рост вверх)"
L["Bar "] = "Панель " --Also in ActionBars
L["BNet Frame"] = "Оповещения BNet"
L["Boss Frames"] = "Боссы" --Also used in UnitFrames
L["Classbar"] = "Полоса класса"
L["Experience Bar"] = "Полоса опыта"
L["Focus Castbar"] = "Полоса заклинаний фокуса"
L["Focus Frame"] = "Фокус" --Also used in UnitFrames
L["FocusTarget Frame"] = "Цель фокуса" --Also used in UnitFrames
L["GM Ticket Frame"] = "Запрос ГМу"
L["Left Chat"] = "Левый чат"
L["Loot / Alert Frames"] = "Розыгрыш/оповещения"
L["Loot Frame"] = "Окно добычи"
L["MA Frames"] = "Помощники"
L["Micro Bar"] = "Микроменю" --Also in ActionBars
L["Minimap"] = "Миникарта"
L["MirrorTimer"] = "Таймер"
L["MT Frames"] = "Танки"
L["Party Frames"] = "Группа" --Also used in UnitFrames
L["Pet Bar"] = "Панель питомца" --Also in ActionBars
L["Pet Castbar"] = "Полоса заклинаний питомца"
L["Pet Frame"] = "Питомец" --Also used in UnitFrames
L["PetTarget Frame"] = "Цель питомца" --Also used in UnitFrames
L["Player Buffs"] = "Баффы игрока"
L["Player Castbar"] = "Полоса заклинаний игрока"
L["Player Debuffs"] = "Дебаффы игрока"
L["Player Frame"] = "Игрок" --Also used in UnitFrames
L["Player Powerbar"] = "Полоса ресурса игрока"
L["PvP"] = true;
L["Raid Frames"] = "Рейд"
L["Raid Pet Frames"] = "Питомцы рейда"
L["Raid-40 Frames"] = "Рейд 40"
L["Reputation Bar"] = "Полоса репутации"
L["Right Chat"] = "Правый чат"
L["Stance Bar"] = "Панель стоек" --Also in ActionBars
L["Target Castbar"] = "Полоса заклинаний цели"
L["Target Frame"] = "Цель" --Also used in UnitFrames
L["Target Powerbar"] = "Полоса ресурса цели"
L["TargetTarget Frame"] = "Цель цели" --Also used in UnitFrames
L["TargetTargetTarget Frame"] = "Цель цели цели"
L["Time Manager Frame"] = true;
L["Tooltip"] = "Подсказка"
L["Vehicle Seat Frame"] = "Техника"
L["Watch Frame"] = "Задания"
L["Weapons"] = "Оружие"
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = "Установка плагина ElvUI"
L["In Progress"] = "В процессе"
L["List of installations in queue:"] = "Очередь установки:"
L["Pending"] = "Ожидает"
L["Steps"] = "Шаги"
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00назначено для |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "Обнаружен конфликт точек фиксирования во фрейме(ах) %s. Пожалуйста, переназначьте фиксирование баффов и дебаффов так, чтобы они не крепились друг к другу. Установлено принудительное крепление дебаффов к фрейму."
L["All keybindings cleared for |cff00ff00%s|r."] = "Сброшены все назначения для |cff00ff00%s|r."
L["Already Running.. Bailing Out!"] = "Уже выполняется.. Бобер, выдыхай!"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Информация поля боя временно скрыта. Для отображения введите /bgstat или ПКМ на иконке 'С' у миникарты."
L["Battleground datatexts will now show again if you are inside a battleground."] = "Информация поля боя снова будет отображаться, если Вы находитесь на них."
L["Binds Discarded"] = "Назначения отменены"
L["Binds Saved"] = "Назначения сохранены"
L["Confused.. Try Again!"] = "Что за?.. Попробуйте еще раз!"
L["No gray items to delete."] = "Нет предметов серого качества для удаления."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "Заклинание '%s' было добавлено в фильтр 'Blacklist' аур рамок юнитов."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Эта опция вызвала конфликт точек фиксации, в результате которого \"%s\" крепится к самому себе. Пожалуйста, проверье настройки точек фиксации. \"%s\" будет прикреплено к \"%s\"."
L["Vendored gray items for:"] = "Проданы серые предметы на сумму:"
L["You don't have enough money to repair."] = "У вас недостаточно денег для ремонта."
L["You must be at a vendor."] = "Вы должны находиться у торговца"
L["Your items have been repaired for: "] = "Ремонт обошелся в "
L["Your items have been repaired using guild bank funds for: "] = "Ремонт обошелся гильдии в "
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Обнаружена ошибка lua. Вы получите отчет о ней после завершения боя."
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "Настройка, которую Вы только что изменили, будет влиять только на этого персонажа. Она не будет изменяться при смене профиля. Также это изменение требует перезагрузки интерфейса для вступления в силу."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = "Приняв это вы сбросите ваши списки приоритетов для всех аур на индикаторах здоровья. Вы уверены?"
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = "Приняв это вы сбросите ваши списки приоритетов для всех аур на рамках юнитов. Вы уверены?"
L["Are you sure you want to apply this font to all ElvUI elements?"] = "Вы уверены, что хоттите применить этот шрифт ко всем элементам ElvUI?"
L["Are you sure you want to delete all your gray items?"] = "Вы уверены, что хотите удалить все предметы серого качества?"
L["Are you sure you want to disband the group?"] = "Вы уверены, что хотите распустить группу?"
L["Are you sure you want to reset all the settings on this profile?"] = "Вы уверены, что хотите сбросить все настройки для этого профиля?"
L["Are you sure you want to reset every mover back to it's default position?"] = "Вы уверены, что хотите сбросить все фиксаторы на позиции по умолчанию?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Из-за массового непонимания новой системы аур, я добавил новый шаг в установку. Он опционален. Если Вам нравится, как сейчас настроены Ваши ауры, перейдите до последнюю страницу установки и нажмите \"Завершить\", чтобы это сообщение больше не появлялось. Если же оно появится снова, пожалуйста, перезапустите игру."
L["Can't buy anymore slots!"] = "Невозможно приобрести больше слотов!"
L["Disable Warning"] = "Отключить предупреждение"
L["Discard"] = "Отменить"
L["Do you enjoy the new ElvUI?"] = "Вам нравится ElvUI?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "Клянетесь ли Вы не постить на форуме технической поддержки, что что-то не работает, до того, как отключите другие аддоны/модули?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "Ваш ElvUI устарел более, чем на 5 версий. Вы можете скачать последнюю версию с https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI устарел. Вы можете скачать последнюю версию с https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI нужно провести оптимизацию базы данных. Подождите, пожалуйста."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Наведите курсор на любую кнопку на панели или в книге заклинаний, чтобы назначит ей клавишу. Нажмите правую кнопку мыши или 'Escape', чтобы сбросить назначение для этой кнопки."
L["I Swear"] = "Я клянусь!"
L["No, Revert Changes!"] = "Нет, обратить изменения!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Японский городовой... у Вас одновременно включены ElvUi и Tukui. Выберите аддон для отключения."
L["One or more of the changes you have made require a ReloadUI."] = "Одно или несколько изменений требуют перезагрузки интерфейса"
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Одно или несколько изменений повлияют на всех персонажей, использующих этот аддон. Вы должны перезагрузить интерфейс для отображения этих изменений."
L["Save"] = "Сохранить"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "Профиль, который вы хотите импортировать, уже существует. Задайте новой имя или примите для перезаписи существующего профиля."
L["Type /hellokitty to revert to old settings."] = "Напишите /hellokitty для возврата к предыдущим настройкам."
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Для использования расположения для лекаря крайне рекомендуется установить аддон Clique, если вы хотите иметь возможность лечить по клику мышью."
L["Yes, Keep Changes!"] = "Да, сохранить изменения!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Вы переключились в режим тонких границ. Вы должны завершить установку для исправления графических багов."
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Вы изменили масштаб интерфейса, однако у вас все еще активирована опция автоматического масштабирования в настройках ElvUI. Нажмите 'Принять', если Вы хотите отключить эту опцию."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Вы импортировали настройки, которые могут потребовать перезагрузки для вступления в силу. Перезагрузить?"
L["You must purchase a bank slot first!"] = "Сперва Вы должны приобрести дополнительный слот в банке!"
--Tooltip
L["Count"] = "Кол-во"
L["Item Level:"] = "Уровень предметов:"
L["Talent Specialization:"] = "Специализация:"
L["Targeted By:"] = "Является целью:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "Функция рейдовых меток доступна в Escape -> Назначение клавиш. Прокрутите вниз до раздела ElvUI и назначьте клавишу для рейдовых меток."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "В ElvUI присутствует функция двойной специализации, которая позволит Вам использовать разные профили для разных наборов талантов. Вы можете включить эту функцию в разделе профилей."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "За технической поддержкой обращайтесь на https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Если Вы случайно удалили вкладку чата, всегда можно сделать следующее: зайти в конфигурацию, запустить установку, дойти до шага настроек чата и сбросить их."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Если Вы испытываете проблемы с ElvUI, попробуйте отключить все аддоны, кроме самого ElvUI. Помните, ElvUI это аддон, полностью заменяющий интерфейс, Вы не можете одновременно использовать два аддона, выполняющих одинаковые функции."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "Запомненную цель (фокус) можно установить командой /focus при взятии нужного врага в цель. Для этого рекомендуется сделать макрос."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Для перемещения способностей по панелям команд нужно перемещать их с зажатой клавишей shift. Вы можете поменять модификатор в опциях панелей команд."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Для настройки отображения каналов в чате кликните правой кнопкой мыши на закладке нужного чата и выберите пункт 'параметры'."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Вы можете получить доступ к функциям копирования чата и меню чата, наведя курсор на верхний правый угол панели чата и кликнув левой/правой кнопкой мыши на появившейся кнопке."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Вы можете узнать средний уровень предметов игрока, зажав shift и наведя на них курсор. Информация будет отражена в подсказке."
L["You can set your keybinds quickly by typing /kb."] = "Вы можете быстро назначать клавиши, введя команду /kb."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Вы можете получить доступ к микроменю, кликнув средней кнопкой мыши на миникарте. Также Вы можете включить обычное микроменю в настройках панелей команд"
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "Вы можете использовать команду /resetui чтобы сбросить положения всех фиксаторов. Вы также можете использовать команду /resetui <имя фиксатора> для сброса определенного фиксатора.\nПример: /resetui Player Frame"
--UnitFrames
L["Dead"] = "Труп"
L["Ghost"] = "Призрак"
L["Offline"] = "Не в сети"
+346
View File
@@ -0,0 +1,346 @@
-- Spanish localization file for esES and esMX.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "esES") or AceLocale:NewLocale("ElvUI", "esMX")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "The addon %s is not compatible with ElvUI's %s module. Please select either the addon or the ElvUI module to disable."
--*_MSG locales
L["LOGIN_MSG"] = "Bienvenido a %sElvUI|r versión %s%s|r, escribe /ec para acceder al menú de configuración. Si necesitas ayuda o soporte técnico puedes visitarnos en https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "Controles"
L["Key"] = "Tecla"
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "No hay teclas establecidas."
L["Remove Bar %d Action Page"] = "Quitar Barra %d de la paginación"
L["Trigger"] = "Disparador"
--Bags
L["Bank"] = "Banco"
L["Hold Control + Right Click:"] = "Mantén Control y Haz Clic Derecho:"
L["Hold Shift + Drag:"] = "Mantén Shift y Arrastra:"
L["Purchase Bags"] = "Comprar Bolsas"
L["Reset Position"] = "Reestablecer Posición"
L["Sort Bags"] = "Ordenar Bolsas"
L["Temporary Move"] = "Movimiento Temporal"
L["Toggle Bags"] = "Mostrar/Ocultar Bolsas"
L["Toggle Key"] = true;
L["Vendor Grays"] = "Vender Objetos Grises"
--Chat
L["AFK"] = "Ausente"
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "Oc"
L["G"] = "H"
L["Invalid Target"] = "Objetivo Inválido"
L["O"] = "O"
L["P"] = "G"
L["PL"] = "LG"
L["R"] = "B"
L["RL"] = "LB"
L["RW"] = "AB"
L["says"] = "dice"
L["whispers"] = "susurra"
L["yells"] = "grita"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(Mantén Shift) Uso de Memoria"
L["Avoidance Breakdown"] = "Desglose de Evasión"
L["Character: "] = "Personaje: "
L["Chest"] = "Pecho"
L["Combat"] = "Combate"
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55fc|r"
L["Deficit:"] = "Déficit:"
L["DPS"] = "DPS"
L["Earned:"] = "Ganada:"
L["Friends List"] = "Lista de Amigos"
L["Friends"] = "Amigos"
L["Gold"] = "Oro"
L["goldabbrev"] = "|cffffd700g|r"
L["Hit"] = "Golpe"
L["Hold Shift + Right Click:"] = true;
L["Home Latency:"] = "Latencia Local:"
L["HP"] = "Salud"
L["HPS"] = "VPS"
L["lvl"] = "Niv"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "Mitigación Por Nivel: "
L["No Guild"] = "Sin Hermandad"
L["Profit:"] = "Ganancia:"
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "Restablecer Datos: Mantén Shift + Clic Derecho"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "Banda(s) Guardada(s)"
L["Server: "] = "Servidor: "
L["Session:"] = "Sesión:"
L["silverabbrev"] = "|cffc7c7cfs|r"
L["SP"] = "PH"
L["Spell/Heal Power"] = true;
L["Spent:"] = "Gastada:"
L["Stats For:"] = "Estadísticas para:"
L["System"] = true;
L["Total CPU:"] = "CPU Total:"
L["Total Memory:"] = "Memoria Total:"
L["Total: "] = "Total: "
L["Unhittable:"] = "Imbatible:"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s intentó llamar a la función protegida '%s'."
L["No locals to dump"] = "No hay locales para volcar"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s quiere compartir sus filtros contigo. ¿Aceptas la petición?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s quiere compartir el perfil %s contigo. ¿Aceptas la petición?"
L["Data From: %s"] = "Datos De: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "Se completó la descarga de los filtros de %s. ¿Quieres aplicar los cambios ahora?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "¡Milagro! ¡La descarga se desvaneció como pedo! Intenta de nuevo"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "Descarga de perfil de %s completa, pero el perfil %s ya existe. Cámbiale el nombre o se reemplazará el perfil existente."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "Descarga de perfil de %s completa ¿Quieres cargar el perfil %s ahora?"
L["Profile request sent. Waiting for response from player."] = "Petición de perfil enviada. Esperando respuesta del jugador."
L["Request was denied by user."] = "Petición denegada por el jugador."
L["Your profile was successfully recieved by the player."] = "Tu perfil ha sido recibido exitosamente por el jugador."
--Install
L["Aura Bars & Icons"] = "Barras de Auras e Iconos"
L["Auras Set"] = "Auras Configuradas"
L["Auras"] = true;
L["Caster DPS"] = "DPS Hechizos"
L["Chat Set"] = "Chat Configurado"
L["Chat"] = "Chat"
L["Choose a theme layout you wish to use for your initial setup."] = "Elige un tema de distribución para usar en tu configuración inicial."
L["Classic"] = "Clásico"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "Haz clic en el botón de abajo para cambiar el tamaño de los marcos de chat y de unidad, y reubicar tus barras de acción."
L["Config Mode:"] = "Modo de Configuración"
L["CVars Set"] = "CVars Configuradas"
L["CVars"] = "CVars"
L["Dark"] = "Oscuro"
L["Disable"] = "Desactivar"
L["ElvUI Installation"] = "Instalación de ElvUI"
L["Finished"] = "Terminado"
L["Grid Size:"] = "Tamaño de la Rejilla:"
L["Healer"] = "Sanador"
L["High Resolution"] = "Alta Resolución"
L["high"] = "alta"
L["Icons Only"] = "Sólo Iconos"
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "Si tienes un icono o una barra de aura que no quieres ver simplemente mantén pulsado la tecla Shift y haz clic con el botón izquierdo del ratón en el icono para que desaparezca."
L["Importance: |cff07D400High|r"] = "Importancia: |cff07D400Alta|r"
L["Importance: |cffD3CF00Medium|r"] = "Importancia: |cffD3CF00Media|r"
L["Importance: |cffFF0000Low|r"] = "Importancia: |cffFF0000Baja|r"
L["Installation Complete"] = "Instalación Completa"
L["Layout Set"] = "Distribución Establecida"
L["Layout"] = "Distribución"
L["Lock"] = "Bloquear"
L["Low Resolution"] = "Baja Resolución"
L["low"] = "baja"
L["Nudge"] = "Ajuste Fino"
L["Physical DPS"] = "DPS Físico"
L["Please click the button below so you can setup variables and ReloadUI."] = "Haz clic en el botón de abajo para configurar variables y recargar la interfaz."
L["Please click the button below to setup your CVars."] = "Haz clic en el botón de abajo para configurar las CVars"
L["Please press the continue button to go onto the next step."] = "Presiona el botón de continuar para ir al siguiente paso"
L["Resolution Style Set"] = "Estilo de Resolución Establecido"
L["Resolution"] = "Resolución"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "Selecciona el tipo de sistema de de auras que deseas utilizar con los marcos de unidad de ElvUI. Establécelo a Barras de Auras e Iconos para usar a la vez la barra de auras y los iconos, establécelo en Sólo Iconos para ver solo los iconos."
L["Setup Chat"] = "Configurar Chat"
L["Setup CVars"] = "Configurar CVars"
L["Skip Process"] = "Saltar Proceso"
L["Sticky Frames"] = "Marcos Adhesivos"
L["Tank"] = "Tanque"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "Las ventanas de chat funcionan igual que sus contrapartes estándar de Blizzard. Puedes hacer clic derecho en las pestañas y arrastrarlas, cambiarles el nombre, etc. Haz clic en el botón de abajo para configurar las ventanas de chat."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "El menú de configuración puede ser accedido mediante el comando /ec o haciendo clic en el botón 'C' del minimapa. Presiona el botón de abajo si deseas saltarte la instalación."
L["Theme Set"] = "Establecer Tema"
L["Theme Setup"] = "Configurar Tema"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "El proceso de instalación te ayudará a aprender algunas de las características de ElvUI y preparará la interfaz para su uso."
L["This is completely optional."] = "Esto es completamente opcional."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "Esta parte de la instalación configura los nombres, posiciones y colores de las ventanas de chat."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "Esta parte de la instalación configura las opciones predeterminadas de World of Warcraft. Se recomienda hacer este paso para que todo funcione apropiadamente."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "Esta resolución no necesita que cambies los ajustes para que quepa la interfaz en tu pantalla."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "Esta resolución requiere que cambies algunos ajustes para que todo quepa en tu pantalla."
L["This will change the layout of your unitframes and actionbars."] = "Ésto cambiará el diseño de los marcos de unidades y barras de acción."
L["Trade"] = "Intercambio"
L["Welcome to ElvUI version %s!"] = "Bienvenido(a) a ElvUI versión %s!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Ya has terminado con el proceso de instalación. Si necesitas ayuda o soporte técnico por favor visítanos en https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "Siempre puedes cambiar las fuentes y colores de cualquier elemento de ElvUI desde la configuración."
L["You can now choose what layout you wish to use based on your combat role."] = "Ahora puedes elegir qué distribución quieres basándote en tu rol de combate."
L["You may need to further alter these settings depending how low you resolution is."] = "Puede que necesites cambiar estos ajutes dependiendo de qué tan baja sea tu resolución."
L["Your current resolution is %s, this is considered a %s resolution."] = "Tu resolución actual es %s, esto se considera una resolución %s."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% above |cff%02x%02x%02x%s|r]"
L["Bars"] = "Barras"
L["Calendar"] = "Calendario"
L["Can't Roll"] = "No puede tirar dados"
L["Disband Group"] = "Disolver Grupo"
L["Empty Slot"] = true;
L["Enable"] = "Habilitar"
L["Experience"] = "Experiencia"
L["Farm Mode"] = true;
L["Fishy Loot"] = "Botín Sospechoso"
L["Left Click:"] = "Click Izquierdo"
L["Raid Menu"] = "Menú de Banda"
L["Remaining:"] = "Restante"
L["Rested:"] = "Descansado:"
L["Right Click:"] = "Click Derecho"
L["Show BG Texts"] = "Mostrar Textos de CB"
L["Toggle Chat Frame"] = "Mostrar/Ocultar Marco de Chat"
L["Toggle Configuration"] = "Mostrar/Ocultar Configuración"
L["XP:"] = "XP:"
L["You don't have permission to mark targets."] = "No tienes permiso para marcar objetivos."
--Movers
L["Arena Frames"] = "Marcos de Arena"
L["Bag Mover (Grow Down)"] = "Fijador de Bolsa (Crecer hacia abajo)"
L["Bag Mover (Grow Up)"] = "Fijador de Bolsa (Crecer hacia arriba)"
L["Bag Mover"] = "Fijador de Bolsa"
L["Bags"] = "Bolsas"
L["Bank Mover (Grow Down)"] = "Fijador de Banco (Crecer hacia abajo)"
L["Bank Mover (Grow Up)"] = "Fijador de Banco (Crecer hacia arriba)"
L["Bar "] = "Barra "
L["BNet Frame"] = "Marco BNet"
L["Boss Frames"] = "Marco de Jefe"
L["Classbar"] = "Barra de Clase"
L["Experience Bar"] = "Barra de Experiencia"
L["Focus Castbar"] = "Barra de Lanzamiento del Foco"
L["Focus Frame"] = "Marco de Foco"
L["FocusTarget Frame"] = "Marco de Objetivo del Foco"
L["GM Ticket Frame"] = "Marco de Consultas para el MJ"
L["Left Chat"] = "Chat Izquierdo"
L["Loot / Alert Frames"] = "Marcos de Botín / Alerta"
L["Loot Frame"] = "Marco de Botín"
L["MA Frames"] = "Marcos de AP"
L["Micro Bar"] = "Micro Barra"
L["Minimap"] = "Minimapa"
L["MirrorTimer"] = true;
L["MT Frames"] = "Marcos de TP"
L["Party Frames"] = "Marco de Grupo"
L["Pet Bar"] = "Barra de Mascota"
L["Pet Castbar"] = "Barra de Lanzamiento de Mascota"
L["Pet Frame"] = "Marco de Mascota"
L["PetTarget Frame"] = "Marco de Objetivo de Mascota"
L["Player Buffs"] = "Ventajas de Jugador"
L["Player Castbar"] = "Barra de Lanzamiento del Jugador"
L["Player Debuffs"] = "Perjuicios de Jugador"
L["Player Frame"] = "Marco de Jugador"
L["Player Powerbar"] = "Barra de Poder del Jugador"
L["PvP"] = true;
L["Raid Frames"] = "Marcos de Banda"
L["Raid Pet Frames"] = "Marcos de Banda con Mascotas"
L["Raid-40 Frames"] = "Marcos de Banda de 40"
L["Reputation Bar"] = "Barra de Reputación"
L["Right Chat"] = "Chat Derecho"
L["Stance Bar"] = "Barra de Forma"
L["Target Castbar"] = "Barra de Lanzamiento del Objetivo"
L["Target Frame"] = "Marco de Objetivo"
L["Target Powerbar"] = "Barra de Poder del Objetivo"
L["TargetTarget Frame"] = "Marco de Objetivo de Objetivo"
L["TargetTargetTarget Frame"] = "Marco del Objetivo del Objetivo del Objetivo"
L["Time Manager Frame"] = true;
L["Tooltip"] = "Descripción Emergente"
L["Vehicle Seat Frame"] = "Marco del Asiento del Vehículo"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = "Instalación del plugin de ElvUI"
L["In Progress"] = "En Progreso"
L["List of installations in queue:"] = "Lista de Instalaciones en cola:"
L["Pending"] = "Pendiente"
L["Steps"] = "Pasos"
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00ligado(a) a |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = "El marco(s) %s tiene un punto de fijación en conflicto, por favor cambia el punto de fijación de los beneficios o los perjuicios para que no estén adjuntos entre ellos. Se forzará a los perjuicios para que se adjunten al marco de unidad principal hasta que se corrija."
L["All keybindings cleared for |cff00ff00%s|r."] = "Todos los atajos borrados para |cff00ff00%s|r."
L["Already Running.. Bailing Out!"] = "Ya está en ejecución... ¡Cancelando!"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "Textos de datos de los campos de batalla temporalmente ocultos, para mostrarlos escribe /bgstats o click derecho en 'C' donde el minimapa."
L["Battleground datatexts will now show again if you are inside a battleground."] = "Los textos de datos de los campos de batalla serán visibles de nuevo si estás en un campo de batalla."
L["Binds Discarded"] = "Teclas Descartadas"
L["Binds Saved"] = "Teclas Guardadas"
L["Confused.. Try Again!"] = "Confundido... ¡Intenta de Nuevo!"
L["No gray items to delete."] = "No hay objetos grises para eliminar."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "El hechizo '%s' ha sido añadido a la Lista Negra del filtro de auras del marco de unidad."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "Esta opción causó un punto de fijación en conflicto, donde '%s' estaría adjunto a sí mismo. Por favor comprueba tus puntos de fijación. Opción '%s' a ser fijado a '%s'"
L["Vendored gray items for:"] = "Objetos grises vendidos por:"
L["You don't have enough money to repair."] = "No tienes suficiente dinero para reparaciones."
L["You must be at a vendor."] = "Debes estar cerca de un vendedor."
L["Your items have been repaired for: "] = "Tus objetos han sido reparados por:"
L["Your items have been repaired using guild bank funds for: "] = "Tus objetos han sido reparados con fondos del banco de hermandad por:"
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000Error de Lua recibido. Podrás ver el error cuando salgas de combate."
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "La opción que has cambiado se aplicará sólo para este personaje. Esta opción no se verá alterada al cambiar el perfil de usuario. Cambiar esta opción requiere que recargues tu Interfaz de Usuario."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = true;
L["Are you sure you want to delete all your gray items?"] = "¿Estás seguro que quieres eliminar todos tus objetos grises?"
L["Are you sure you want to disband the group?"] = "¿Estás seguro que quieres deshacer el grupo?"
L["Are you sure you want to reset all the settings on this profile?"] = "¿Estás seguro que deseas restablecer todos los ajustes de este perfil?"
L["Are you sure you want to reset every mover back to it's default position?"] = "¿Estás seguro que quieres resetear cada fijador a su posición por defecto?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "Debido a la gran confusión causada por el nuevo sistema de auras he implementado un nuevo paso en el proceso de instalación, esto es opcional. Si quieres conservar la configuración actual de tus auras ve al último paso de la instalación y haz clic en terminar para que este mensaje no vuelva a ser mostrado. Si por alguna razón se vuelve a mostrar por favor reinicia el juego."
L["Can't buy anymore slots!"] = "¡No puedes comprar más huecos!"
L["Disable Warning"] = "Deshabilitar Advertencia"
L["Discard"] = "Descartar"
L["Do you enjoy the new ElvUI?"] = "¿Disfrutas del nuevo ElvUI?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "¿Juras no escribir a Soporte Técnico acerca de algo que no funciona sin antes deshabilitar la combinación addon/módulo primero?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI está cinco o mas revisiones desactualizado. Puedes descargar la versión más nueva de https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI está desactualizado. Puedes descargar la versión más nueva de https://github.com/ElvUI-WotLK/ElvUI/"
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI necesita realizar optimizaciones de base de datos por favor se paciente."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "Pasa tu ratón por encima de un botón de acción o de un botón del libro de hechizos para ligarlo. Pulsa escape o botón derecho para limpiar la asignación actual del botón de acción."
L["I Swear"] = "Lo Juro"
L["No, Revert Changes!"] = "¡No, Revierte los Cambios!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "Oh cielos, tienes ElvUI y Tukui habilitados al mismo tiempo. Elige un addon a deshabilitar"
L["One or more of the changes you have made require a ReloadUI."] = "Uno o más de los cambios que has hecho requieren una recarga de la interfaz."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "Uno o más de los cambios que has hecho afectaran a todos los personajes que usen este addon. Tendrás que recargar la intefaz de usuario para ver el cambio que has realizado."
L["Save"] = "Guardar"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "El perfil que has intentado importar ya existe. Elige un nuevo nombre o acepta sobreescribir el perfil existente."
L["Type /hellokitty to revert to old settings."] = "Escribe /hellokitty para revertir a las opciones antiguas."
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "Utilizando el diseño de sanador es altamente recomendado bajar el addon Clique si deseas tener la función de hacer clic para curar."
L["Yes, Keep Changes!"] = "¡Sí, Mantén los cambios!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "Has cambiado la opción de Tema de Border Ligero. Tendrás que completar el proceso de instalación para quitar cualquier bug gráfico."
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "Has cambiado la escala de tu interfaz, sin embargo aún tienes el AutoEscalado activado en ElvUI. Pulsa aceptar si te gustaría desactivar el AutoEscalado."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "Has importado opciones que pueden requerir una recarga de la interfaz para tomar efecto. ¿Recargar ahora?"
L["You must purchase a bank slot first!"] = "¡Debes comprar un hueco del banco primero!"
--Tooltip
L["Count"] = "Contador"
L["Item Level:"] = "Nivel de Objeto:"
L["Talent Specialization:"] = "Especialización de Talentos:"
L["Targeted By:"] = "Objetivo De:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "La opción de marcador de banda está disponible pulsando Escape -> Asignar teclas -> Recorrer hacia abajo hasta ElvUI y establecer la tecla para el marcador de banda."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI tiene la posibilidad de cargar diferentes perfiles automáticamente al cambiar de especialización de talentos. Puedes activar esta función en la pestaña de perfiles."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "Para soporte técnico visítanos en https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "Si eliminas un marco de chat accidentalmente, siempre puedes ir a la configuración, pulsar instalar, ir a la parte del chat, y restaurarlo."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "Si has experimentado errores con ElvUI prueba a desactivar todos tus addons excepto ElvUI, recuerda que ElvUI remplaza por completo la interfaz, no puede haber addons que hagan lo mismo."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "El foco puede establecerse escribiendo /enfoque cuando tienes seleccionado al objetivo al cual quieres hacer foco. Es recomendable que hagas una macro para esto."
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "Para mover habilidades a las barras de acción mantener shift + arrastrar. Puedes cambiar la tecla de modificación desde el menú de opciones de la barra de acción."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "Para configurar que canales aparecen en el chat, haz clic con el botón derecho en la pestaña del chat y elige opciones."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "Puedes acceder a copiar y a las opciones del chat pasando el ratón sobre la esquina superior derecha del panel del chat y haciendo click en el botón que aparece."
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "Puedes ver la media de nivel de objeto de un objetivo manteniendo pulsado shift mientras pasas el ratón por encima de él. El iNvl aparecerá en la descripción emergente."
L["You can set your keybinds quickly by typing /kb."] = "Puedes establecer tus atajos rapidamente escribiendo /kb."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "Puedes acceder a la microbarra usando tu botón central del ratón sobre el minimapa. También puedes activarla desde las opciones de las barras de acción."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "Puedes usar el commando /resetui para restablecer todos tus fijadores. También puedes usar el comando para restablecer alguno en específico, /resetui <fijador>. PE: /resetui Player Frame"
--UnitFrames
L["Dead"] = true;
L["Ghost"] = "Fantasma"
L["Offline"] = "Fuera de Línea"
+346
View File
@@ -0,0 +1,346 @@
-- Taiwanese localization file for zhTW.
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("ElvUI", "zhTW")
if not L then return end
--*_ADDON locales
L["INCOMPATIBLE_ADDON"] = "插件 %s 與 ElvUI 的 %s 模組不相容。請停用不相容的插件,或停用相關的模組."
--*_MSG locales
L["LOGIN_MSG"] = "歡迎使用%sElvUI |r %s%s|r 版, 請輸入/ec 進入設定介面. 如需技術支援請至 https://github.com/ElvUI-WotLK/ElvUI"
--ActionBars
L["Binding"] = "綁定"
L["Key"] = ""
L["KEY_ALT"] = "A"
L["KEY_CTRL"] = "C"
L["KEY_DELETE"] = "Del"
L["KEY_HOME"] = "Hm"
L["KEY_INSERT"] = "Ins"
L["KEY_MOUSEBUTTON"] = "M"
L["KEY_MOUSEWHEELDOWN"] = "MwD"
L["KEY_MOUSEWHEELUP"] = "MwU"
L["KEY_NUMPAD"] = "N"
L["KEY_PAGEDOWN"] = "PD"
L["KEY_PAGEUP"] = "PU"
L["KEY_SHIFT"] = "S"
L["KEY_SPACE"] = "SpB"
L["No bindings set."] = "未設定快捷綁定."
L["Remove Bar %d Action Page"] = "移除第 %d 快捷列"
L["Trigger"] = "觸發器"
--Bags
L["Bank"] = "銀行"
L["Hold Control + Right Click:"] = "按住 Ctrl 並按滑鼠右鍵:"
L["Hold Shift + Drag:"] = "按住 Shift 並拖曳:"
L["Purchase Bags"] = "購買背包"
L["Reset Position"] = "重設位置"
L["Sort Bags"] = "整理背包"
L["Temporary Move"] = "移動背包"
L["Toggle Bags"] = "開啟/關閉背包"
L["Toggle Key"] = true;
L["Vendor Grays"] = "出售灰色物品"
--Chat
L["AFK"] = "暫離" --Also used in datatexts and tooltip
L["BG"] = true;
L["BGL"] = true;
L["DND"] = "忙碌" --Also used in datatexts and tooltip
L["G"] = "公會"
L["Invalid Target"] = "無效的目標"
L["O"] = "幹部"
L["P"] = "隊伍"
L["PL"] = "隊長"
L["R"] = "團隊"
L["RL"] = "團隊隊長"
L["RW"] = "團隊警告"
L["says"] = ""
L["whispers"] = "密語"
L["yells"] = "大喊"
--DataTexts
L["(Hold Shift) Memory Usage"] = "(按住Shift) 記憶體使用量"
L["Avoidance Breakdown"] = "免傷統計"
L["Character: "] = "角色: "
L["Chest"] = "胸部"
L["Combat"] = "戰鬥"
L["Combat Time"] = true;
L["Coords"] = true;
L["copperabbrev"] = "|cffeda55f銅|r" --Also used in Bags
L["Deficit:"] = "赤字:"
L["DPS"] = "傷害輸出"
L["Earned:"] = "賺取:"
L["Friends List"] = "好友列表"
L["Friends"] = "好友" --Also in Skins
L["Gold"] = "金錢"
L["goldabbrev"] = "|cffffd700金|r" --Also used in Bags
L["Hit"] = "命中"
L["Hold Shift + Right Click:"] = "按住 Shift 並按滑鼠右鍵"
L["Home Latency:"] = "本機延遲:"
L["HP"] = "生命值"
L["HPS"] = "治療輸出"
L["lvl"] = "等級"
L["Miss Chance"] = true;
L["Mitigation By Level: "] = "等級減傷: "
L["No Guild"] = "沒有公會"
L["Profit:"] = "利潤: "
L["Reload UI"] = true;
L["Reset Data: Hold Shift + Right Click"] = "重置數據: 按住 Shift + 右鍵點擊"
L["Right Click: Reset CPU Usage"] = true;
L["Saved Raid(s)"] = "已有進度的副本"
L["Server: "] = "伺服器: "
L["Session:"] = "本次登入:"
L["silverabbrev"] = "|cffc7c7cf銀|r" --Also used in Bags
L["SP"] = "法術能量"
L["Spell/Heal Power"] = true;
L["Spent:"] = "花費:"
L["Stats For:"] = "統計:"
L["System"] = true;
L["Total CPU:"] = "CPU佔用"
L["Total Memory:"] = "總記憶體:"
L["Total: "] = "合計: "
L["Unhittable:"] = "未命中:"
L["Wintergrasp"] = true;
--DebugTools
L["%s: %s tried to call the protected function '%s'."] = "%s: %s 嘗試調用保護函數'%s'."
L["No locals to dump"] = "沒有本地檔案"
--Distributor
L["%s is attempting to share his filters with you. Would you like to accept the request?"] = "%s 試圖與你分享過濾器設定. 你是否接受?"
L["%s is attempting to share the profile %s with you. Would you like to accept the request?"] = "%s 試圖與你分享設定檔 %s. 你是否接受?"
L["Data From: %s"] = "數據來源: %s"
L["Filter download complete from %s, would you like to apply changes now?"] = "過濾器設定下載於 %s, 你是否現在變更?"
L["Lord! It's a miracle! The download up and vanished like a fart in the wind! Try Again!"] = "天啊! 太奇葩啦! 下載消失了! 就像是在風中放了個屁... 再試一次吧!"
L["Profile download complete from %s, but the profile %s already exists. Change the name or else it will overwrite the existing profile."] = "設定文件從 %s 下載完成, 但是設定文件 %s 已存在. 請更改名稱, 否則它會覆蓋你的現有設定檔."
L["Profile download complete from %s, would you like to load the profile %s now?"] = "設定檔從 %s 下載完成, 你是否要加載設定檔 %s?"
L["Profile request sent. Waiting for response from player."] = "已發送設定檔請求. 等待對方回應"
L["Request was denied by user."] = "請求被對方拒絕."
L["Your profile was successfully recieved by the player."] = "你的設定檔已被其他玩家成功接收."
--Install
L["Aura Bars & Icons"] = "光環條和圖示"
L["Auras Set"] = "光環樣式設定"
L["Auras"] = "光環"
L["Caster DPS"] = "法系輸出"
L["Chat Set"] = "對話设置"
L["Chat"] = "對話"
L["Choose a theme layout you wish to use for your initial setup."] = "為你的個人設定選擇一個你喜歡的皮膚主題."
L["Classic"] = "經典"
L["Click the button below to resize your chat frames, unitframes, and reposition your actionbars."] = "點選下面的按鈕調整對話框、單位框架的尺寸, 以及移動快捷列位置."
L["Config Mode:"] = "設定模式:"
L["CVars Set"] = "參數設定"
L["CVars"] = "參數"
L["Dark"] = "黑暗"
L["Disable"] = "停用"
L["ElvUI Installation"] = "安裝 ElvUI"
L["Finished"] = "設定完畢"
L["Grid Size:"] = "網格尺寸:"
L["Healer"] = "補師"
L["High Resolution"] = "高解析度"
L["high"] = ""
L["Icons Only"] = "圖示" --Also used in Bags
L["If you have an icon or aurabar that you don't want to display simply hold down shift and right click the icon for it to disapear."] = "如果你有不想顯示的圖示或光環條, 你可以簡單的通過按住Shift + 右鍵點擊使它隱藏."
L["Importance: |cff07D400High|r"] = "重要性: |cff07D400高|r"
L["Importance: |cffD3CF00Medium|r"] = "重要性: |cffD3CF00中|r"
L["Importance: |cffFF0000Low|r"] = "重要性: |cffFF0000低|r"
L["Installation Complete"] = "安裝完畢"
L["Layout Set"] = "版面配置設定"
L["Layout"] = "介面佈局"
L["Lock"] = "鎖定"
L["Low Resolution"] = "低解析度"
L["low"] = ""
L["Nudge"] = "微調"
L["Physical DPS"] = "物理輸出"
L["Please click the button below so you can setup variables and ReloadUI."] = "請按下方按鈕設定變數並重載介面."
L["Please click the button below to setup your CVars."] = "請按下方按鈕設定參數."
L["Please press the continue button to go onto the next step."] = "請按「繼續」按鈕,執行下一個步驟."
L["Resolution Style Set"] = "解析度樣式設定"
L["Resolution"] = "解析度"
L["Select the type of aura system you want to use with ElvUI's unitframes. Set to Aura Bar & Icons to use both aura bars and icons, set to icons only to only see icons."] = "選擇在 ElvUI 單位框架中要使用的光環系統. 選擇光環條和圖示來同時使用兩者, 選擇圖示來僅使用圖示"
L["Setup Chat"] = "設定對話視窗"
L["Setup CVars"] = "設定參數"
L["Skip Process"] = "略過"
L["Sticky Frames"] = "框架依附"
L["Tank"] = "坦克"
L["The chat windows function the same as Blizzard standard chat windows, you can right click the tabs and drag them around, rename, etc. Please click the button below to setup your chat windows."] = "對話視窗與WOW 原始對話視窗的操作方式相同, 你可以拖拉、移動分頁或重新命名分頁. 請按下方按鈕以設定對話視窗."
L["The in-game configuration menu can be accessed by typing the /ec command or by clicking the 'C' button on the minimap. Press the button below if you wish to skip the installation process."] = "若要進入內建設定選單, 請輸入/ec, 或者按一下小地圖旁的「C」按鈕.若要略過安裝程序, 請按下方按鈕."
L["Theme Set"] = "主題設定"
L["Theme Setup"] = "主題安裝"
L["This install process will help you learn some of the features in ElvUI has to offer and also prepare your user interface for usage."] = "此安裝程序有助你瞭解ElvUI 部份功能, 並可協助你預先設定UI."
L["This is completely optional."] = "此為選擇性功能."
L["This part of the installation process sets up your chat windows names, positions and colors."] = "此安裝步驟將會設定對話視窗的名稱、位置和顏色."
L["This part of the installation process sets up your World of Warcraft default options it is recommended you should do this step for everything to behave properly."] = "此安裝步驟將會設定 WOW 預設選項, 建議你執行此步驟, 以確保功能均可正常運作."
L["This resolution doesn't require that you change settings for the UI to fit on your screen."] = "這個解析度不需要你改動任何設定以適應你的螢幕."
L["This resolution requires that you change some settings to get everything to fit on your screen."] = "這個解析度需要你改變一些設定才能適應你的螢幕."
L["This will change the layout of your unitframes and actionbars."] = "這將會改變你的單位框架和動作條的佈局"
L["Trade"] = "拾取/交易"
L["Welcome to ElvUI version %s!"] = "歡迎使用 ElvUI %s 版!"
L["You are now finished with the installation process. If you are in need of technical support please visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "已完成安裝程序. 小提示: 若想開啟微型選單, 請在小地圖按滑鼠中鍵. 如果沒有中鍵按鈕, 請按住Shift鍵, 並在小地圖按滑鼠右鍵. 如需技術支援請至 https://github.com/ElvUI-WotLK/ElvUI"
L["You can always change fonts and colors of any element of ElvUI from the in-game configuration."] = "你可以在遊戲內的設定選項內更改ElvUI的字體、顏色等設定."
L["You can now choose what layout you wish to use based on your combat role."] = "你現在可以根據你的戰鬥角色選擇合適的佈局."
L["You may need to further alter these settings depending how low you resolution is."] = "根據你的解析度你可能需要改動這些設定."
L["Your current resolution is %s, this is considered a %s resolution."] = "你當前的解析度是%s, 這被認為是個%s 解析度."
--Misc
L["ABOVE_THREAT_FORMAT"] = "%s: %.0f%% [%.0f%% 以上 |cff%02x%02x%02x%s|r]"
L["Bars"] = "" --Also used in UnitFrames
L["Calendar"] = "日曆"
L["Can't Roll"] = "無法需求此裝備"
L["Disband Group"] = "解散隊伍"
L["Empty Slot"] = true;
L["Enable"] = "啟用" --Doesn't fit a section since it's used a lot of places
L["Experience"] = "經驗/聲望條"
L["Farm Mode"] = true;
L["Fishy Loot"] = "貪婪"
L["Left Click:"] = "滑鼠左鍵:" --layout\layout.lua
L["Raid Menu"] = "團隊選單"
L["Remaining:"] = "剩餘:"
L["Rested:"] = "休息:"
L["Right Click:"] = "滑鼠右鍵:" --layout\layout.lua
L["Show BG Texts"] = "顯示戰場資訊文字" --layout\layout.lua
L["Toggle Chat Frame"] = "開關對話框架" --layout\layout.lua
L["Toggle Configuration"] = "開啟/關閉設定" --layout\layout.lua
L["XP:"] = "經驗:"
L["You don't have permission to mark targets."] = "你沒有標記目標的權限."
--Movers
L["Arena Frames"] = "競技場框架" --Also used in UnitFrames
L["Bag Mover (Grow Down)"] = "背包錨點 (向下增長)"
L["Bag Mover (Grow Up)"] = "背包錨點 (向上增長)"
L["Bag Mover"] = "背包錨點"
L["Bags"] = "背包" --Also in DataTexts
L["Bank Mover (Grow Down)"] = "銀行錨點 (向下增長)"
L["Bank Mover (Grow Up)"] = "銀行錨點 (向上增長)"
L["Bar "] = "快捷列 " --Also in ActionBars
L["BNet Frame"] = "戰網提示資訊"
L["Boss Frames"] = "首領框架" --Also used in UnitFrames
L["Classbar"] = "職業特有條"
L["Experience Bar"] = "經驗條"
L["Focus Castbar"] = "焦點目標施法條"
L["Focus Frame"] = "焦點目標框架" --Also used in UnitFrames
L["FocusTarget Frame"] = "焦點目標的目標框架" --Also used in UnitFrames
L["GM Ticket Frame"] = "GM 對話框"
L["Left Chat"] = "左側對話框"
L["Loot / Alert Frames"] = "拾取 / 提醒框架"
L["Loot Frame"] = "拾取框架"
L["MA Frames"] = "主助理框架"
L["Micro Bar"] = "微型系統菜單" --Also in ActionBars
L["Minimap"] = "小地圖"
L["MirrorTimer"] = "鏡像計時器"
L["MT Frames"] = "主坦克框架"
L["Party Frames"] = "隊伍框架" --Also used in UnitFrames
L["Pet Bar"] = "寵物快捷列" --Also in ActionBars
L["Pet Castbar"] = "寵物施法條"
L["Pet Frame"] = "寵物框架" --Also used in UnitFrames
L["PetTarget Frame"] = "寵物目標框架" --Also used in UnitFrames
L["Player Buffs"] = "玩家增益"
L["Player Castbar"] = "玩家施法條"
L["Player Debuffs"] = "玩家減益"
L["Player Frame"] = "玩家框架" --Also used in UnitFrames
L["Player Powerbar"] = "玩家能量條"
L["PvP"] = true;
L["Raid Frames"] = "團隊框架"
L["Raid Pet Frames"] = "團隊寵物框架"
L["Raid-40 Frames"] = "40人團隊框架"
L["Reputation Bar"] = "聲望條"
L["Right Chat"] = "右側對話框"
L["Stance Bar"] = "姿態列" --Also in ActionBars
L["Target Castbar"] = "目標施法條"
L["Target Frame"] = "目標框架" --Also used in UnitFrames
L["Target Powerbar"] = "目標能量條"
L["TargetTarget Frame"] = "目標的目標框架" --Also used in UnitFrames
L["TargetTargetTarget Frame"] = "目標的目標的目標框架"
L["Time Manager Frame"] = true;
L["Tooltip"] = "浮動提示"
L["Vehicle Seat Frame"] = "載具座位框"
L["Watch Frame"] = true;
L["Weapons"] = true;
L["DESC_MOVERCONFIG"] = "Movers unlocked. Move them now and click Lock when you are done./nOptions:/nShift + RightClick - Hides mover temporarily./nCtrl + RightClick - Resets mover position to default."
--Plugin Installer
L["ElvUI Plugin Installation"] = "ElvUI 插件安裝"
L["In Progress"] = "進行中"
L["List of installations in queue:"] = "即將安裝的列表"
L["Pending"] = "等待中"
L["Steps"] = "步驟"
--Prints
L[" |cff00ff00bound to |r"] = " |cff00ff00綁定到 |r"
L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."] = " %s 個框架錨點衝突, 請移動buff或者debuff錨點讓他們彼此不依附. 暫時強制debuff依附到主框架."
L["All keybindings cleared for |cff00ff00%s|r."] = "取消|cff00ff00%s|r 所有綁定的快捷鍵."
L["Already Running.. Bailing Out!"] = "正在運行"
L["Battleground datatexts temporarily hidden, to show type /bgstats or right click the 'C' icon near the minimap."] = "戰場資訊暫時隱藏, 你可以通過輸入/bgstats 或右鍵點擊小地圖旁「C」按鈕顯示."
L["Battleground datatexts will now show again if you are inside a battleground."] = "當你處於戰場時戰場資訊將再次顯示."
L["Binds Discarded"] = "取消綁定"
L["Binds Saved"] = "儲存綁定"
L["Confused.. Try Again!"] = "請再試一次!"
L["No gray items to delete."] = "沒有可刪除的灰色物品."
L["The spell '%s' has been added to the Blacklist unitframe aura filter."] = "法術'%s'已經被添加到單位框架的光環過濾器中."
L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."] = "此設定造成了錨點衝突, '%s' 框架會依附於自己, 請檢查你的錨點. 將 '%s' 依附於 '%s'."
L["Vendored gray items for:"] = "已售出灰色物品,共得:"
L["You don't have enough money to repair."] = "沒有足夠的資金來修復."
L["You must be at a vendor."] = "你必須與商人對話."
L["Your items have been repaired for: "] = "裝備已修復,共支出:"
L["Your items have been repaired using guild bank funds for: "] = "已使用公會資金修復裝備,共支出:"
L["|cFFE30000Lua error recieved. You can view the error message when you exit combat."] = "|cFFE30000LUA錯誤已接收, 你可以在脫離戰鬥後檢查.|r"
--Static Popups
L["A setting you have changed will change an option for this character only. This setting that you have changed will be uneffected by changing user profiles. Changing this setting requires that you reload your User Interface."] = "你所做的改動只會影響到使用這個插件的本角色, 你需要重新加載介面才能使改動生效."
L["Accepting this will reset your Filter Priority lists for all auras on NamePlates. Are you sure?"] = true
L["Accepting this will reset your Filter Priority lists for all auras on UnitFrames. Are you sure?"] = true
L["Are you sure you want to apply this font to all ElvUI elements?"] = "你確定要將此字型應用到所有 ElvUI 元素嗎?"
L["Are you sure you want to delete all your gray items?"] = "是否確定要刪除所有灰色物品?"
L["Are you sure you want to disband the group?"] = "確定要解散隊伍?"
L["Are you sure you want to reset all the settings on this profile?"] = "確定需要重置這個設定檔中的所有設定?"
L["Are you sure you want to reset every mover back to it's default position?"] = "確定需要重置所有框架至預設位置?"
L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."] = "因為新的光環系統造成了大量的混亂因此我導入了一個新的步驟到安裝過程中. 這是可選的, 如果你喜歡你現在的設定請跳到最後一個步驟並點擊「完成」將不會再提示. 如果由於某些原因反復提示, 請重新開啟遊戲."
L["Can't buy anymore slots!"] = "無法再購買更多銀行欄位!"
L["Disable Warning"] = "停用警告"
L["Discard"] = "取消"
L["Do you enjoy the new ElvUI?"] = "你享受新版的 ElvUI嗎?"
L["Do you swear not to post in technical support about something not working without first disabling the addon/module combination first?"] = "你發誓在你沒停用其他插件或是模組前不會到技術支援發文詢問某些功能失效嗎?"
L["ElvUI is five or more revisions out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI 以過期超過5個版本. 你可以在 https://github.com/ElvUI-WotLK/ElvUI/ 下載到最新的版本."
L["ElvUI is out of date. You can download the newest version from https://github.com/ElvUI-WotLK/ElvUI/"] = "ElvUI 以過期. 你可以在 https://github.com/ElvUI-WotLK/ElvUI/ 下載到最新的版本."
L["ElvUI needs to perform database optimizations please be patient."] = "ElvUI 需要進行資料庫優化, 請稍待."
L["Hover your mouse over any actionbutton or spellbook button to bind it. Press the escape key or right click to clear the current actionbutton's keybinding."] = "移動滑鼠到快捷列或技能書按鈕上綁定快捷鍵.按ESC或滑鼠右鍵取消目前快捷鍵."
L["I Swear"] = "我承諾"
L["No, Revert Changes!"] = "不, 回復修改!"
L["Oh lord, you have got ElvUI and Tukui both enabled at the same time. Select an addon to disable."] = "喔 拜託,你不能同時使用 Elvui 和 Tukui, 請選擇一個停用."
L["One or more of the changes you have made require a ReloadUI."] = "已變更一或多個設定, 需重載介面."
L["One or more of the changes you have made will effect all characters using this addon. You will have to reload the user interface to see the changes you have made."] = "你所做的改動可能會影響到使用這個插件的所有角色, 你需要重新加載介面才能使改動生效."
L["Save"] = "儲存"
L["The profile you tried to import already exists. Choose a new name or accept to overwrite the existing profile."] = "你嘗試導入的設定檔已存在. 選擇一個新名稱或是允許覆蓋原有設定檔"
L["Type /hellokitty to revert to old settings."] = "輸入 /hellokitty 來回復舊設定"
L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."] = "使用治療者佈局時建議你下載 Clique 插件, 以擁有點擊血條治療的功能"
L["Yes, Keep Changes!"] = "是的, 保留變更!"
L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."] = "你選擇了細邊框主題選項. 你必須完成安裝程序來移除任何圖像錯誤"
L["You have changed your UIScale, however you still have the AutoScale option enabled in ElvUI. Press accept if you would like to disable the Auto Scale option."] = "你改變了介面縮放比例, 然而ElvUI的自動縮放選項是開啟的. 點擊接受以關閉ElvUI的自動縮放."
L["You have imported settings which may require a UI reload to take effect. Reload now?"] = "你導入的設定可能需要重新載入UI才能生效. 現在重新載入嗎?"
L["You must purchase a bank slot first!"] = "你必需先購買一個銀行背包欄位!"
--Tooltip
L["Count"] = "計數"
L["Item Level:"] = "物品等級:"
L["Talent Specialization:"] = "天賦專精:"
L["Targeted By:"] = "同目標的有:"
--Tutorials
L["A raid marker feature is available by pressing Escape -> Keybinds scroll to the bottom under ElvUI and setting a keybind for the raid marker."] = "你可以通過按ESC鍵-> 按鍵設定, 滾動到ElvUI設定下方設定一個快速標記的快捷鍵."
L["ElvUI has a dual spec feature which allows you to load different profiles based on your current spec on the fly. You can enable this from the profiles tab."] = "ElvUI 可以根據你所使用的天賦自動套用不同的裝備組. 你可以在設定檔中啟用此功能."
L["For technical support visit us at https://github.com/ElvUI-WotLK/ElvUI"] = "如需技術支援請至 https://github.com/ElvUI-WotLK/ElvUI"
L["If you accidently remove a chat frame you can always go the in-game configuration menu, press install, go to the chat portion and reset them."] = "如果你不慎移除了對話框, 你可以重新安裝一次重置他們."
L["If you are experiencing issues with ElvUI try disabling all your addons except ElvUI, remember ElvUI is a full UI replacement addon, you cannot run two addons that do the same thing."] = "如果你使用 ElvUI 時遇到問題, 請嘗試停用除了ElvUI之外的插件. 請記住 ElvUI 是一套全套的 UI 替換插件, 你不能同時使用不同的插件來完成同一件事."
L["The focus unit can be set by typing /focus when you are targeting the unit you want to focus. It is recommended you make a macro to do this."] = "你可以使用 /focus 指令設定目前目標為焦點目標. 建議你可以寫一個聚集來做這件事"
L["To move abilities on the actionbars by default hold shift + drag. You can change the modifier key from the actionbar options menu."] = "你可以通過按住Shift拖動技能條中的按鍵. 你可以在Blizzard的快捷列設定中更改按鍵."
L["To setup which channels appear in which chat frame, right click the chat tab and go to settings."] = "你可以通過右鍵點擊對話框標籤欄設定你需要在對話框內顯示的頻道."
L["You can access copy chat and chat menu functions by mouse over the top right corner of chat panel and left/right click on the button that will appear."] = "你可以將滑鼠滑到對話框右上角並且點擊左鍵或右鍵來開啟對話複製或是對話指令視窗"
L["You can see someones average item level of their gear by holding shift and mousing over them. It should appear inside the tooltip."] = "你可以透過按住Shift並將滑鼠滑過目標來看到目標的平均裝等, 結果將顯示在你的滑鼠提示框內."
L["You can set your keybinds quickly by typing /kb."] = "你可以通過輸入/kb 快速綁定按鍵."
L["You can toggle the microbar by using your middle mouse button on the minimap you can also accomplish this by enabling the actual microbar located in the actionbar settings."] = "你可以通過滑鼠中鍵點擊小地圖或在快捷列設定內選擇打開微型系統欄."
L["You can use the /resetui command to reset all of your movers. You can also use the command to reset a specific mover, /resetui <mover name>.\nExample: /resetui Player Frame"] = "你可以使用 /resetui 命令來重置所有框架的位置. 你也可以通過命令 /resetui <框架名稱> 單獨重置某個框架.\n例如: /resetui Player Frame"
--UnitFrames
L["Dead"] = "死亡"
L["Ghost"] = "鬼魂"
L["Offline"] = "離線"

Some files were not shown because too many files have changed in this diff Show More