WoWInterface SVN EnsidiaFails

Compare Revisions

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

Rev 3 → Rev 4

trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua New file
0,0 → 1,298
--[[-----------------------------------------------------------------------------
Frame Container
-------------------------------------------------------------------------------]]
local Type, Version = "Frame", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs, assert, type = pairs, assert, type
local wipe = table.wipe
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: CLOSE
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Button_OnClick(frame)
PlaySound("gsTitleOptionExit")
frame.obj:Hide()
end
 
local function Frame_OnClose(frame)
frame.obj:Fire("OnClose")
end
 
local function Frame_OnMouseDown(frame)
AceGUI:ClearFocus()
end
 
local function Title_OnMouseDown(frame)
frame:GetParent():StartMoving()
AceGUI:ClearFocus()
end
 
local function MoverSizer_OnMouseUp(mover)
local frame = mover:GetParent()
frame:StopMovingOrSizing()
local self = frame.obj
local status = self.status or self.localstatus
status.width = frame:GetWidth()
status.height = frame:GetHeight()
status.top = frame:GetTop()
status.left = frame:GetLeft()
end
 
local function SizerSE_OnMouseDown(frame)
frame:GetParent():StartSizing("BOTTOMRIGHT")
AceGUI:ClearFocus()
end
 
local function SizerS_OnMouseDown(frame)
frame:GetParent():StartSizing("BOTTOM")
AceGUI:ClearFocus()
end
 
local function SizerE_OnMouseDown(frame)
frame:GetParent():StartSizing("RIGHT")
AceGUI:ClearFocus()
end
 
local function StatusBar_OnEnter(frame)
frame.obj:Fire("OnEnterStatusBar")
end
 
local function StatusBar_OnLeave(frame)
frame.obj:Fire("OnLeaveStatusBar")
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self.frame:SetParent(UIParent)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
self:SetTitle()
self:SetStatusText()
self:ApplyStatus()
self:Show()
end,
 
["OnRelease"] = function(self)
self.status = nil
wipe(self.localstatus)
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 34
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 57
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
 
["SetTitle"] = function(self, title)
self.titletext:SetText(title)
end,
 
["SetStatusText"] = function(self, text)
self.statustext:SetText(text)
end,
 
["Hide"] = function(self)
self.frame:Hide()
end,
 
["Show"] = function(self)
self.frame:Show()
end,
 
-- called to set an external table to store status in
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
self:ApplyStatus()
end,
 
["ApplyStatus"] = function(self)
local status = self.status or self.localstatus
local frame = self.frame
self:SetWidth(status.width or 700)
self:SetHeight(status.height or 500)
frame:ClearAllPoints()
if status.top and status.left then
frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
else
frame:SetPoint("CENTER")
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local FrameBackdrop = {
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 8, right = 8, top = 8, bottom = 8 }
}
 
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
 
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
 
frame:EnableMouse(true)
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetBackdrop(FrameBackdrop)
frame:SetBackdropColor(0, 0, 0, 1)
frame:SetMinResize(400, 200)
frame:SetToplevel(true)
frame:SetScript("OnHide", Frame_OnClose)
frame:SetScript("OnMouseDown", Frame_OnMouseDown)
 
local closebutton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
closebutton:SetScript("OnClick", Button_OnClick)
closebutton:SetPoint("BOTTOMRIGHT", -27, 17)
closebutton:SetHeight(20)
closebutton:SetWidth(100)
closebutton:SetText(CLOSE)
 
local statusbg = CreateFrame("Button", nil, frame)
statusbg:SetPoint("BOTTOMLEFT", 15, 15)
statusbg:SetPoint("BOTTOMRIGHT", -132, 15)
statusbg:SetHeight(24)
statusbg:SetBackdrop(PaneBackdrop)
statusbg:SetBackdropColor(0.1,0.1,0.1)
statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
statusbg:SetScript("OnEnter", StatusBar_OnEnter)
statusbg:SetScript("OnLeave", StatusBar_OnLeave)
 
local statustext = statusbg:CreateFontString(nil, "OVERLAY", "GameFontNormal")
statustext:SetPoint("TOPLEFT", 7, -2)
statustext:SetPoint("BOTTOMRIGHT", -7, 2)
statustext:SetHeight(20)
statustext:SetJustifyH("LEFT")
statustext:SetText("")
 
local titlebg = frame:CreateTexture(nil, "OVERLAY")
titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
titlebg:SetPoint("TOP", 0, 12)
titlebg:SetWidth(100)
titlebg:SetHeight(40)
 
local title = CreateFrame("Frame", nil, frame)
title:EnableMouse(true)
title:SetScript("OnMouseDown", Title_OnMouseDown)
title:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
title:SetAllPoints(titlebg)
 
local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
 
local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
titlebg_l:SetWidth(30)
titlebg_l:SetHeight(40)
 
local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
titlebg_r:SetWidth(30)
titlebg_r:SetHeight(40)
 
local sizer_se = CreateFrame("Frame", nil, frame)
sizer_se:SetPoint("BOTTOMRIGHT")
sizer_se:SetWidth(25)
sizer_se:SetHeight(25)
sizer_se:EnableMouse()
sizer_se:SetScript("OnMouseDown",SizerSE_OnMouseDown)
sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
 
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
 
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
 
local sizer_s = CreateFrame("Frame", nil, frame)
sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
sizer_s:SetPoint("BOTTOMLEFT")
sizer_s:SetHeight(25)
sizer_s:EnableMouse(true)
sizer_s:SetScript("OnMouseDown", SizerS_OnMouseDown)
sizer_s:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
 
local sizer_e = CreateFrame("Frame", nil, frame)
sizer_e:SetPoint("BOTTOMRIGHT", 0, 25)
sizer_e:SetPoint("TOPRIGHT")
sizer_e:SetWidth(25)
sizer_e:EnableMouse(true)
sizer_e:SetScript("OnMouseDown", SizerE_OnMouseDown)
sizer_e:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
 
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 17, -27)
content:SetPoint("BOTTOMRIGHT", -17, 40)
 
local widget = {
localstatus = {},
titletext = titletext,
statustext = statustext,
content = content,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
closebutton.obj, statusbg.obj = widget, widget
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua New file
0,0 → 1,102
--[[-----------------------------------------------------------------------------
InlineGroup Container
Simple container widget that creates a visible "box" with an optional title.
-------------------------------------------------------------------------------]]
local Type, Version = "InlineGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(300)
self:SetHeight(100)
end,
 
-- ["OnRelease"] = nil,
 
["SetTitle"] = function(self,title)
self.titletext:SetText(title)
end,
 
 
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + 40)
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 20
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 20
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
 
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
 
local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOPLEFT", 14, 0)
titletext:SetPoint("TOPRIGHT", -14, 0)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
 
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 0, -17)
border:SetPoint("BOTTOMRIGHT", -1, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
border:SetBackdropBorderColor(0.4, 0.4, 0.4)
 
--Container Support
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
 
local widget = {
frame = frame,
content = content,
titletext = titletext,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua New file
0,0 → 1,707
--[[ $Id: AceGUIWidget-DropDown.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0")
 
-- Lua APIs
local min, max, floor = math.min, math.max, math.floor
local select, pairs, ipairs = select, pairs, ipairs
local tsort = table.sort
 
-- WoW APIs
local PlaySound = PlaySound
local UIParent, CreateFrame = UIParent, CreateFrame
local _G = _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: CLOSE
 
local function fixlevels(parent,...)
local i = 1
local child = select(i, ...)
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1)
fixlevels(child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
 
local function fixstrata(strata, parent, ...)
local i = 1
local child = select(i, ...)
parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
 
do
local widgetType = "Dropdown-Pullout"
local widgetVersion = 3
 
--[[ Static data ]]--
 
local backdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
edgeSize = 32,
tileSize = 32,
tile = true,
insets = { left = 11, right = 12, top = 12, bottom = 11 },
}
local sliderBackdrop = {
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
tile = true, tileSize = 8, edgeSize = 8,
insets = { left = 3, right = 3, top = 3, bottom = 3 }
}
 
local defaultWidth = 200
local defaultMaxHeight = 600
 
--[[ UI Event Handlers ]]--
 
-- HACK: This should be no part of the pullout, but there
-- is no other 'clean' way to response to any item-OnEnter
-- Used to close Submenus when an other item is entered
local function OnEnter(item)
local self = item.pullout
for k, v in ipairs(self.items) do
if v.CloseMenu and v ~= item then
v:CloseMenu()
end
end
end
 
-- See the note in Constructor() for each scroll related function
local function OnMouseWheel(this, value)
this.obj:MoveScroll(value)
end
 
local function OnScrollValueChanged(this, value)
this.obj:SetScroll(value)
end
 
local function OnSizeChanged(this)
this.obj:FixScroll()
end
 
--[[ Exported methods ]]--
 
-- exported
local function SetScroll(self, value)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
 
local offset
if height > viewheight then
offset = 0
else
offset = floor((viewheight - height) / 1000 * value)
end
child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
status.offset = offset
status.scrollvalue = value
end
 
-- exported
local function MoveScroll(self, value)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
 
if height > viewheight then
self.slider:Hide()
else
self.slider:Show()
local diff = height - viewheight
local delta = 1
if value < 0 then
delta = -1
end
self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
end
end
 
-- exported
local function FixScroll(self)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
local offset = status.offset or 0
 
if viewheight < height then
self.slider:Hide()
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
self.slider:SetValue(0)
else
self.slider:Show()
local value = (offset / (viewheight - height) * 1000)
if value > 1000 then value = 1000 end
self.slider:SetValue(value)
self:SetScroll(value)
if value < 1000 then
child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
status.offset = offset
end
end
end
 
-- exported, AceGUI callback
local function OnAcquire(self)
self.frame:SetParent(UIParent)
--self.itemFrame:SetToplevel(true)
end
 
-- exported, AceGUI callback
local function OnRelease(self)
self:Clear()
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
-- exported
local function AddItem(self, item)
self.items[#self.items + 1] = item
 
local h = #self.items * 16
self.itemFrame:SetHeight(h)
self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
 
item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")
 
item:SetPullout(self)
item:SetOnEnter(OnEnter)
end
 
-- exported
local function Open(self, point, relFrame, relPoint, x, y)
local items = self.items
local frame = self.frame
local itemFrame = self.itemFrame
 
frame:SetPoint(point, relFrame, relPoint, x, y)
 
 
local height = 8
for i, item in pairs(items) do
if i == 1 then
item:SetPoint("TOP", itemFrame, "TOP", 0, -2)
else
item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1)
end
 
item:Show()
 
height = height + 16
end
itemFrame:SetHeight(height)
fixstrata("TOOLTIP", frame, frame:GetChildren())
frame:Show()
self:Fire("OnOpen")
end
 
-- exported
local function Close(self)
self.frame:Hide()
self:Fire("OnClose")
end
 
-- exported
local function Clear(self)
local items = self.items
for i, item in pairs(items) do
AceGUI:Release(item)
items[i] = nil
end
end
 
-- exported
local function IterateItems(self)
return ipairs(self.items)
end
 
-- exported
local function SetHideOnLeave(self, val)
self.hideOnLeave = val
end
 
-- exported
local function SetMaxHeight(self, height)
self.maxHeight = height or defaultMaxHeight
if self.frame:GetHeight() > height then
self.frame:SetHeight(height)
elseif (self.itemFrame:GetHeight() + 34) < height then
self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
end
end
 
-- exported
local function GetRightBorderWidth(self)
return 6 + (self.slider:IsShown() and 12 or 0)
end
 
-- exported
local function GetLeftBorderWidth(self)
return 6
end
 
--[[ Constructor ]]--
 
local function Constructor()
local count = AceGUI:GetNextWidgetNum(widgetType)
local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent)
local self = {}
self.count = count
self.type = widgetType
self.frame = frame
frame.obj = self
 
self.OnAcquire = OnAcquire
self.OnRelease = OnRelease
 
self.AddItem = AddItem
self.Open = Open
self.Close = Close
self.Clear = Clear
self.IterateItems = IterateItems
self.SetHideOnLeave = SetHideOnLeave
 
self.SetScroll = SetScroll
self.MoveScroll = MoveScroll
self.FixScroll = FixScroll
 
self.SetMaxHeight = SetMaxHeight
self.GetRightBorderWidth = GetRightBorderWidth
self.GetLeftBorderWidth = GetLeftBorderWidth
 
self.items = {}
 
self.scrollStatus = {
scrollvalue = 0,
}
 
self.maxHeight = defaultMaxHeight
 
frame:SetBackdrop(backdrop)
frame:SetBackdropColor(0, 0, 0)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetClampedToScreen(true)
frame:SetWidth(defaultWidth)
frame:SetHeight(self.maxHeight)
--frame:SetToplevel(true)
 
-- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
local itemFrame = CreateFrame("Frame", nil, scrollFrame)
 
self.scrollFrame = scrollFrame
self.itemFrame = itemFrame
 
scrollFrame.obj = self
itemFrame.obj = self
 
local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame)
slider:SetOrientation("VERTICAL")
slider:SetHitRectInsets(0, 0, -10, 0)
slider:SetBackdrop(sliderBackdrop)
slider:SetWidth(8)
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
slider:SetFrameStrata("FULLSCREEN_DIALOG")
self.slider = slider
slider.obj = self
 
scrollFrame:SetScrollChild(itemFrame)
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
scrollFrame:SetToplevel(true)
scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
 
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
itemFrame:SetHeight(400)
itemFrame:SetToplevel(true)
itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
 
slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
slider:SetScript("OnValueChanged", OnScrollValueChanged)
slider:SetMinMaxValues(0, 1000)
slider:SetValueStep(1)
slider:SetValue(0)
 
scrollFrame:Show()
itemFrame:Show()
slider:Hide()
 
self:FixScroll()
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end
 
do
local widgetType = "Dropdown"
local widgetVersion = 22
 
--[[ Static data ]]--
 
--[[ UI event handler ]]--
 
local function Control_OnEnter(this)
this.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(this)
this.obj:Fire("OnLeave")
end
 
local function Dropdown_OnHide(this)
local self = this.obj
if self.open then
self.pullout:Close()
end
end
 
local function Dropdown_TogglePullout(this)
local self = this.obj
PlaySound("igMainMenuOptionCheckBoxOn") -- missleading name, but the Blizzard code uses this sound
if self.open then
self.open = nil
self.pullout:Close()
AceGUI:ClearFocus()
else
self.open = true
self.pullout:SetWidth(self.frame:GetWidth())
self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
AceGUI:SetFocus(self)
end
end
 
local function OnPulloutOpen(this)
local self = this.userdata.obj
local value = self.value
 
if not self.multiselect then
for i, item in this:IterateItems() do
item:SetValue(item.userdata.value == value)
end
end
 
self.open = true
end
 
local function OnPulloutClose(this)
local self = this.userdata.obj
self.open = nil
self:Fire("OnClosed")
end
 
local function ShowMultiText(self)
local text
for i, widget in self.pullout:IterateItems() do
if widget.type == "Dropdown-Item-Toggle" then
if widget:GetValue() then
if text then
text = text..", "..widget:GetText()
else
text = widget:GetText()
end
end
end
end
self:SetText(text)
end
 
local function OnItemValueChanged(this, event, checked)
local self = this.userdata.obj
 
if self.multiselect then
self:Fire("OnValueChanged", this.userdata.value, checked)
ShowMultiText(self)
else
if checked then
self:SetValue(this.userdata.value)
self:Fire("OnValueChanged", this.userdata.value)
else
this:SetValue(true)
end
if self.open then
self.pullout:Close()
end
end
end
 
--[[ Exported methods ]]--
 
-- exported, AceGUI callback
local function OnAcquire(self)
local pullout = AceGUI:Create("Dropdown-Pullout")
self.pullout = pullout
pullout.userdata.obj = self
pullout:SetCallback("OnClose", OnPulloutClose)
pullout:SetCallback("OnOpen", OnPulloutOpen)
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
 
self:SetHeight(44)
self:SetWidth(200)
end
 
-- exported, AceGUI callback
local function OnRelease(self)
if self.open then
self.pullout:Close()
end
AceGUI:Release(self.pullout)
self.pullout = nil
 
self:SetText("")
self:SetLabel("")
self:SetDisabled(false)
self:SetMultiselect(false)
 
self.value = nil
self.list = nil
self.open = nil
self.hasClose = nil
 
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
-- exported
local function SetDisabled(self, disabled)
self.disabled = disabled
if disabled then
self.text:SetTextColor(0.5,0.5,0.5)
self.button:Disable()
self.label:SetTextColor(0.5,0.5,0.5)
else
self.button:Enable()
self.label:SetTextColor(1,.82,0)
self.text:SetTextColor(1,1,1)
end
end
 
-- exported
local function ClearFocus(self)
if self.open then
self.pullout:Close()
end
end
 
-- exported
local function SetText(self, text)
self.text:SetText(text or "")
end
 
-- exported
local function SetLabel(self, text)
if text and text ~= "" then
self.label:SetText(text)
self.label:Show()
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-18)
self.frame:SetHeight(44)
else
self.label:SetText("")
self.label:Hide()
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
self.frame:SetHeight(26)
end
end
 
-- exported
local function SetValue(self, value)
if self.list then
self:SetText(self.list[value] or "")
end
self.value = value
end
 
-- exported
local function GetValue(self)
return self.value
end
 
-- exported
local function SetItemValue(self, item, value)
if not self.multiselect then return end
for i, widget in self.pullout:IterateItems() do
if widget.userdata.value == item then
if widget.SetValue then
widget:SetValue(value)
end
end
end
ShowMultiText(self)
end
 
-- exported
local function SetItemDisabled(self, item, disabled)
for i, widget in self.pullout:IterateItems() do
if widget.userdata.value == item then
widget:SetDisabled(disabled)
end
end
end
 
local function AddListItem(self, value, text)
local item = AceGUI:Create("Dropdown-Item-Toggle")
item:SetText(text)
item.userdata.obj = self
item.userdata.value = value
item:SetCallback("OnValueChanged", OnItemValueChanged)
self.pullout:AddItem(item)
end
 
local function AddCloseButton(self)
if not self.hasClose then
local close = AceGUI:Create("Dropdown-Item-Execute")
close:SetText(CLOSE)
self.pullout:AddItem(close)
self.hasClose = true
end
end
 
-- exported
local sortlist = {}
local function SetList(self, list)
self.list = list
self.pullout:Clear()
self.hasClose = nil
if not list then return end
 
for v in pairs(list) do
sortlist[#sortlist + 1] = v
end
tsort(sortlist)
 
for i, value in pairs(sortlist) do
AddListItem(self, value, list[value])
sortlist[i] = nil
end
if self.multiselect then
ShowMultiText(self)
AddCloseButton(self)
end
end
 
-- exported
local function AddItem(self, value, text)
if self.list then
self.list[value] = text
AddListItem(self, value, text)
end
end
 
-- exported
local function SetMultiselect(self, multi)
self.multiselect = multi
if multi then
ShowMultiText(self)
AddCloseButton(self)
end
end
 
-- exported
local function GetMultiselect(self)
return self.multiselect
end
 
--[[ Constructor ]]--
 
local function Constructor()
local count = AceGUI:GetNextWidgetNum(widgetType)
local frame = CreateFrame("Frame", nil, UIParent)
local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")
 
local self = {}
self.type = widgetType
self.frame = frame
self.dropdown = dropdown
self.count = count
frame.obj = self
dropdown.obj = self
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
 
self.ClearFocus = ClearFocus
 
self.SetText = SetText
self.SetValue = SetValue
self.GetValue = GetValue
self.SetList = SetList
self.SetLabel = SetLabel
self.SetDisabled = SetDisabled
self.AddItem = AddItem
self.SetMultiselect = SetMultiselect
self.GetMultiselect = GetMultiselect
self.SetItemValue = SetItemValue
self.SetItemDisabled = SetItemDisabled
 
self.alignoffset = 31
 
frame:SetHeight(44)
frame:SetWidth(200)
frame:SetScript("OnHide",Dropdown_OnHide)
 
dropdown:ClearAllPoints()
dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
dropdown:SetScript("OnHide", nil)
 
local left = _G[dropdown:GetName() .. "Left"]
local middle = _G[dropdown:GetName() .. "Middle"]
local right = _G[dropdown:GetName() .. "Right"]
 
middle:ClearAllPoints()
right:ClearAllPoints()
 
middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)
 
local button = _G[dropdown:GetName() .. "Button"]
self.button = button
button.obj = self
button:SetScript("OnEnter",Control_OnEnter)
button:SetScript("OnLeave",Control_OnLeave)
button:SetScript("OnClick",Dropdown_TogglePullout)
 
local text = _G[dropdown:GetName() .. "Text"]
self.text = text
text.obj = self
text:ClearAllPoints()
text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
text:SetPoint("LEFT", left, "LEFT", 25, 2)
 
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
label:SetJustifyH("LEFT")
label:SetHeight(18)
label:Hide()
self.label = label
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua New file
0,0 → 1,228
--[[-----------------------------------------------------------------------------
EditBox Widget
-------------------------------------------------------------------------------]]
local Type, Version = "EditBox", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local tostring, pairs = tostring, pairs
 
-- WoW APIs
local PlaySound = PlaySound
local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _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: AceGUIEditBoxInsertLink, ChatFontNormal, OKAY
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
if not AceGUIEditBoxInsertLink then
-- upgradeable hook
hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end)
end
 
function _G.AceGUIEditBoxInsertLink(text)
for i = 1, AceGUI:GetWidgetCount(Type) do
local editbox = _G["AceGUI-3.0EditBox"..i]
if editbox and editbox:IsVisible() and editbox:HasFocus() then
editbox:Insert(text)
return true
end
end
end
 
local function ShowButton(self)
if not self.disablebutton then
self.button:Show()
self.editbox:SetTextInsets(0, 20, 3, 3)
end
end
 
local function HideButton(self)
self.button:Hide()
self.editbox:SetTextInsets(0, 0, 3, 3)
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function EditBox_OnEscapePressed(frame)
AceGUI:ClearFocus()
end
 
local function EditBox_OnEnterPressed(frame)
local self = frame.obj
local value = frame:GetText()
local cancel = self:Fire("OnEnterPressed", value)
if not cancel then
PlaySound("igMainMenuOptionCheckBoxOn")
HideButton(self)
end
end
 
local function EditBox_OnReceiveDrag(frame)
local self = frame.obj
local type, id, info = GetCursorInfo()
if type == "item" then
self:SetText(info)
self:Fire("OnEnterPressed", info)
ClearCursor()
elseif type == "spell" then
local name, rank = GetSpellName(id, info)
if rank and rank:match("%d") then
name = name.."("..rank..")"
end
self:SetText(name)
self:Fire("OnEnterPressed", name)
ClearCursor()
end
HideButton(self)
AceGUI:ClearFocus()
end
 
local function EditBox_OnTextChanged(frame)
local self = frame.obj
local value = frame:GetText()
if tostring(value) ~= tostring(self.lasttext) then
self:Fire("OnTextChanged", value)
self.lasttext = value
ShowButton(self)
end
end
 
local function Button_OnClick(frame)
local editbox = frame.obj.editbox
editbox:ClearFocus()
EditBox_OnEnterPressed(editbox)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- height is controlled by SetLabel
self:SetWidth(200)
self:SetDisabled(false)
self:SetLabel()
self:SetText()
self:DisableButton(false)
self:SetMaxLetters(0)
end,
 
-- ["OnRelease"] = nil,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.editbox:EnableMouse(false)
self.editbox:ClearFocus()
self.editbox:SetTextColor(0.5,0.5,0.5)
self.label:SetTextColor(0.5,0.5,0.5)
else
self.editbox:EnableMouse(true)
self.editbox:SetTextColor(1,1,1)
self.label:SetTextColor(1,.82,0)
end
end,
 
["SetText"] = function(self, text)
self.lasttext = text or ""
self.editbox:SetText(text or "")
self.editbox:SetCursorPosition(0)
HideButton(self)
end,
 
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:SetText(text)
self.label:Show()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
self:SetHeight(44)
self.alignoffset = 30
else
self.label:SetText("")
self.label:Hide()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
self:SetHeight(26)
self.alignoffset = 12
end
end,
 
["DisableButton"] = function(self, disabled)
self.disablebutton = disabled
end,
 
["SetMaxLetters"] = function (self, num)
self.editbox:SetMaxLetters(num or 0)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
 
local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
editbox:SetAutoFocus(false)
editbox:SetFontObject(ChatFontNormal)
editbox:SetScript("OnEnter", Control_OnEnter)
editbox:SetScript("OnLeave", Control_OnLeave)
editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
editbox:SetTextInsets(0, 0, 3, 3)
editbox:SetMaxLetters(256)
editbox:SetPoint("BOTTOMLEFT", 6, 0)
editbox:SetPoint("BOTTOMRIGHT")
editbox:SetHeight(19)
 
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", 0, -2)
label:SetPoint("TOPRIGHT", 0, -2)
label:SetJustifyH("LEFT")
label:SetHeight(18)
 
local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
button:SetWidth(40)
button:SetHeight(20)
button:SetPoint("RIGHT", -2, 0)
button:SetText(OKAY)
button:SetScript("OnClick", Button_OnClick)
button:Hide()
 
local widget = {
alignoffset = 30,
editbox = editbox,
label = label,
button = button,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
editbox.obj, button.obj = widget, widget
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua New file
0,0 → 1,78
--[[-----------------------------------------------------------------------------
Heading Widget
-------------------------------------------------------------------------------]]
local Type, Version = "Heading", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetText()
self:SetFullWidth()
self:SetHeight(18)
end,
 
-- ["OnRelease"] = nil,
 
["SetText"] = function(self, text)
self.label:SetText(text or "")
if text and text ~= "" then
self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
self.right:Show()
else
self.left:SetPoint("RIGHT", -3, 0)
self.right:Hide()
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
 
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
label:SetPoint("TOP")
label:SetPoint("BOTTOM")
label:SetJustifyH("CENTER")
 
local left = frame:CreateTexture(nil, "BACKGROUND")
left:SetHeight(8)
left:SetPoint("LEFT", 3, 0)
left:SetPoint("RIGHT", label, "LEFT", -5, 0)
left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
left:SetTexCoord(0.81, 0.94, 0.5, 1)
 
local right = frame:CreateTexture(nil, "BACKGROUND")
right:SetHeight(8)
right:SetPoint("RIGHT", -3, 0)
right:SetPoint("LEFT", label, "RIGHT", 5, 0)
right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
right:SetTexCoord(0.81, 0.94, 0.5, 1)
 
local widget = {
label = label,
left = left,
right = right,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua New file
0,0 → 1,69
--[[-----------------------------------------------------------------------------
SimpleGroup Container
Simple container widget that just groups widgets.
-------------------------------------------------------------------------------]]
local Type, Version = "SimpleGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(300)
self:SetHeight(100)
end,
 
-- ["OnRelease"] = nil,
 
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight(height or 0)
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
content:SetWidth(width)
content.width = width
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
content:SetHeight(height)
content.height = height
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
 
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT")
content:SetPoint("BOTTOMRIGHT")
 
local widget = {
frame = frame,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-Window.lua New file
0,0 → 1,331
local AceGUI = LibStub("AceGUI-3.0")
 
-- Lua APIs
local pairs, assert, type = pairs, assert, type
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontNormal
 
----------------
-- Main Frame --
----------------
--[[
Events :
OnClose
 
]]
do
local Type = "Window"
local Version = 4
 
local function frameOnClose(this)
this.obj:Fire("OnClose")
end
 
local function closeOnClick(this)
PlaySound("gsTitleOptionExit")
this.obj:Hide()
end
 
local function frameOnMouseDown(this)
AceGUI:ClearFocus()
end
 
local function titleOnMouseDown(this)
this:GetParent():StartMoving()
AceGUI:ClearFocus()
end
 
local function frameOnMouseUp(this)
local frame = this:GetParent()
frame:StopMovingOrSizing()
local self = frame.obj
local status = self.status or self.localstatus
status.width = frame:GetWidth()
status.height = frame:GetHeight()
status.top = frame:GetTop()
status.left = frame:GetLeft()
end
 
local function sizerseOnMouseDown(this)
this:GetParent():StartSizing("BOTTOMRIGHT")
AceGUI:ClearFocus()
end
 
local function sizersOnMouseDown(this)
this:GetParent():StartSizing("BOTTOM")
AceGUI:ClearFocus()
end
 
local function sizereOnMouseDown(this)
this:GetParent():StartSizing("RIGHT")
AceGUI:ClearFocus()
end
 
local function sizerOnMouseUp(this)
this:GetParent():StopMovingOrSizing()
end
 
local function SetTitle(self,title)
self.titletext:SetText(title)
end
 
local function SetStatusText(self,text)
-- self.statustext:SetText(text)
end
 
local function Hide(self)
self.frame:Hide()
end
 
local function Show(self)
self.frame:Show()
end
 
local function OnAcquire(self)
self.frame:SetParent(UIParent)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
self:ApplyStatus()
self:EnableResize(true)
self:Show()
end
 
local function OnRelease(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
end
 
-- called to set an external table to store status in
local function SetStatusTable(self, status)
assert(type(status) == "table")
self.status = status
self:ApplyStatus()
end
 
local function ApplyStatus(self)
local status = self.status or self.localstatus
local frame = self.frame
self:SetWidth(status.width or 700)
self:SetHeight(status.height or 500)
if status.top and status.left then
frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top)
frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0)
else
frame:SetPoint("CENTER",UIParent,"CENTER")
end
end
 
local function OnWidthSet(self, width)
local content = self.content
local contentwidth = width - 34
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end
 
 
local function OnHeightSet(self, height)
local content = self.content
local contentheight = height - 57
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end
 
local function EnableResize(self, state)
local func = state and "Show" or "Hide"
self.sizer_se[func](self.sizer_se)
self.sizer_s[func](self.sizer_s)
self.sizer_e[func](self.sizer_e)
end
 
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = "Window"
 
self.Hide = Hide
self.Show = Show
self.SetTitle = SetTitle
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetStatusText = SetStatusText
self.SetStatusTable = SetStatusTable
self.ApplyStatus = ApplyStatus
self.OnWidthSet = OnWidthSet
self.OnHeightSet = OnHeightSet
self.EnableResize = EnableResize
 
self.localstatus = {}
 
self.frame = frame
frame.obj = self
frame:SetWidth(700)
frame:SetHeight(500)
frame:SetPoint("CENTER",UIParent,"CENTER",0,0)
frame:EnableMouse()
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetScript("OnMouseDown", frameOnMouseDown)
 
frame:SetScript("OnHide",frameOnClose)
frame:SetMinResize(240,240)
frame:SetToplevel(true)
 
local titlebg = frame:CreateTexture(nil, "BACKGROUND")
titlebg:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Title-Background]])
titlebg:SetPoint("TOPLEFT", 9, -6)
titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
 
local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
dialogbg:SetTexture([[Interface\Tooltips\UI-Tooltip-Background]])
dialogbg:SetPoint("TOPLEFT", 8, -24)
dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
dialogbg:SetVertexColor(0, 0, 0, .75)
 
local topleft = frame:CreateTexture(nil, "BORDER")
topleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
topleft:SetWidth(64)
topleft:SetHeight(64)
topleft:SetPoint("TOPLEFT")
topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
 
local topright = frame:CreateTexture(nil, "BORDER")
topright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
topright:SetWidth(64)
topright:SetHeight(64)
topright:SetPoint("TOPRIGHT")
topright:SetTexCoord(0.625, 0.75, 0, 1)
 
local top = frame:CreateTexture(nil, "BORDER")
top:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
top:SetHeight(64)
top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
top:SetTexCoord(0.25, 0.369140625, 0, 1)
 
local bottomleft = frame:CreateTexture(nil, "BORDER")
bottomleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottomleft:SetWidth(64)
bottomleft:SetHeight(64)
bottomleft:SetPoint("BOTTOMLEFT")
bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
 
local bottomright = frame:CreateTexture(nil, "BORDER")
bottomright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottomright:SetWidth(64)
bottomright:SetHeight(64)
bottomright:SetPoint("BOTTOMRIGHT")
bottomright:SetTexCoord(0.875, 1, 0, 1)
 
local bottom = frame:CreateTexture(nil, "BORDER")
bottom:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottom:SetHeight(64)
bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
 
local left = frame:CreateTexture(nil, "BORDER")
left:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
left:SetWidth(64)
left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
left:SetTexCoord(0.001953125, 0.125, 0, 1)
 
local right = frame:CreateTexture(nil, "BORDER")
right:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
right:SetWidth(64)
right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
right:SetTexCoord(0.1171875, 0.2421875, 0, 1)
 
local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
close:SetPoint("TOPRIGHT", 2, 1)
close:SetScript("OnClick", closeOnClick)
self.closebutton = close
close.obj = self
 
local titletext = frame:CreateFontString(nil, "ARTWORK")
titletext:SetFontObject(GameFontNormal)
titletext:SetPoint("TOPLEFT", 12, -8)
titletext:SetPoint("TOPRIGHT", -32, -8)
self.titletext = titletext
 
local title = CreateFrame("Button", nil, frame)
title:SetPoint("TOPLEFT", titlebg)
title:SetPoint("BOTTOMRIGHT", titlebg)
title:EnableMouse()
title:SetScript("OnMouseDown",titleOnMouseDown)
title:SetScript("OnMouseUp", frameOnMouseUp)
self.title = title
 
local sizer_se = CreateFrame("Frame",nil,frame)
sizer_se:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
sizer_se:SetWidth(25)
sizer_se:SetHeight(25)
sizer_se:EnableMouse()
sizer_se:SetScript("OnMouseDown",sizerseOnMouseDown)
sizer_se:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_se = sizer_se
 
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
self.line1 = line1
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
 
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
self.line2 = line2
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
 
local sizer_s = CreateFrame("Frame",nil,frame)
sizer_s:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-25,0)
sizer_s:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
sizer_s:SetHeight(25)
sizer_s:EnableMouse()
sizer_s:SetScript("OnMouseDown",sizersOnMouseDown)
sizer_s:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_s = sizer_s
 
local sizer_e = CreateFrame("Frame",nil,frame)
sizer_e:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,25)
sizer_e:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
sizer_e:SetWidth(25)
sizer_e:EnableMouse()
sizer_e:SetScript("OnMouseDown",sizereOnMouseDown)
sizer_e:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_e = sizer_e
 
--Container Support
local content = CreateFrame("Frame",nil,frame)
self.content = content
content.obj = self
content:SetPoint("TOPLEFT",frame,"TOPLEFT",12,-32)
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-12,13)
 
AceGUI:RegisterAsContainer(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua New file
0,0 → 1,157
--[[-----------------------------------------------------------------------------
DropdownGroup Container
Container controlled by a dropdown on the top.
-------------------------------------------------------------------------------]]
local Type, Version = "DropdownGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local assert, pairs, type = assert, pairs, type
 
-- WoW APIs
local CreateFrame = CreateFrame
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function SelectedGroup(self, event, value)
local group = self.parentgroup
local status = group.status or group.localstatus
status.selected = value
self.parentgroup:Fire("OnGroupSelected", value)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self.dropdown:SetText("")
self:SetDropdownWidth(200)
self:SetTitle("")
end,
 
["OnRelease"] = function(self)
self.dropdown.list = nil
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
end,
 
["SetTitle"] = function(self, title)
self.titletext:SetText(title)
self.dropdown.frame:ClearAllPoints()
if title and title ~= "" then
self.dropdown.frame:SetPoint("TOPRIGHT", -2, 0)
else
self.dropdown.frame:SetPoint("TOPLEFT", -1, 0)
end
end,
 
["SetGroupList"] = function(self,list)
self.dropdown:SetList(list)
end,
 
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
end,
 
["SetGroup"] = function(self,group)
self.dropdown:SetValue(group)
local status = self.status or self.localstatus
status.selected = group
self:Fire("OnGroupSelected", group)
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 26
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 63
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
 
["LayoutFinished"] = function(self, width, height)
self:SetHeight((height or 0) + 63)
end,
 
["SetDropdownWidth"] = function(self, width)
self.dropdown:SetWidth(width)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
 
local function Constructor()
local frame = CreateFrame("Frame")
frame:SetHeight(100)
frame:SetWidth(100)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
 
local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOPLEFT", 4, -5)
titletext:SetPoint("TOPRIGHT", -4, -5)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
 
local dropdown = AceGUI:Create("Dropdown")
dropdown.frame:SetParent(frame)
dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
dropdown:SetCallback("OnValueChanged", SelectedGroup)
dropdown.frame:SetPoint("TOPLEFT", -1, 0)
dropdown.frame:Show()
dropdown:SetLabel("")
 
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 0, -26)
border:SetPoint("BOTTOMRIGHT", 0, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1,0.1,0.1,0.5)
border:SetBackdropBorderColor(0.4,0.4,0.4)
 
--Container Support
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
 
local widget = {
frame = frame,
localstatus = {},
titletext = titletext,
dropdown = dropdown,
border = border,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
dropdown.parentgroup = widget
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua New file
0,0 → 1,204
--[[-----------------------------------------------------------------------------
ScrollFrame Container
Plain container that scrolls its content and doesn't grow in height.
-------------------------------------------------------------------------------]]
local Type, Version = "ScrollFrame", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs, assert, type = pairs, assert, type
local min, max, floor = math.min, math.max, math.floor
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function FixScrollOnUpdate(frame)
frame:SetScript("OnUpdate", nil)
frame.obj:FixScroll()
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function ScrollFrame_OnMouseWheel(frame, value)
frame.obj:MoveScroll(value)
end
 
local function ScrollFrame_OnSizeChanged(frame)
frame:SetScript("OnUpdate", FixScrollOnUpdate)
end
 
local function ScrollBar_OnScrollValueChanged(frame, value)
frame.obj:SetScroll(value)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetScroll(0)
end,
 
["OnRelease"] = function(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
self.scrollframe:SetPoint("BOTTOMRIGHT")
self.scrollbar:Hide()
self.scrollBarShown = nil
self.content.height, self.content.width = nil, nil
end,
 
["SetScroll"] = function(self, value)
local status = self.status or self.localstatus
local viewheight = self.scrollframe:GetHeight()
local height = self.content:GetHeight()
local offset
 
if viewheight > height then
offset = 0
else
offset = floor((height - viewheight) / 1000.0 * value)
end
self.content:ClearAllPoints()
self.content:SetPoint("TOPLEFT", 0, offset)
self.content:SetPoint("TOPRIGHT", 0, offset)
status.offset = offset
status.scrollvalue = value
end,
 
["MoveScroll"] = function(self, value)
local status = self.status or self.localstatus
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
 
if height > viewheight then
self.scrollbar:Hide()
else
self.scrollbar:Show()
local diff = height - viewheight
local delta = 1
if value < 0 then
delta = -1
end
self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
end
end,
 
["FixScroll"] = function(self)
if self.updateLock then return end
self.updateLock = true
local status = self.status or self.localstatus
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
local offset = status.offset or 0
local curvalue = self.scrollbar:GetValue()
if viewheight < height then
if self.scrollBarShown then
self.scrollBarShown = nil
self.scrollbar:Hide()
self.scrollbar:SetValue(0)
self.scrollframe:SetPoint("BOTTOMRIGHT")
self:DoLayout()
end
else
if not self.scrollBarShown then
self.scrollBarShown = true
self.scrollbar:Show()
self.scrollframe:SetPoint("BOTTOMRIGHT", -20, 0)
self:DoLayout()
end
local value = (offset / (viewheight - height) * 1000)
if value > 1000 then value = 1000 end
self.scrollbar:SetValue(value)
self:SetScroll(value)
if value < 1000 then
self.content:ClearAllPoints()
self.content:SetPoint("TOPLEFT", 0, offset)
self.content:SetPoint("TOPRIGHT", 0, offset)
status.offset = offset
end
end
self.updateLock = nil
end,
 
["LayoutFinished"] = function(self, width, height)
self.content:SetHeight(height or 0 + 20)
self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
end,
 
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
if not status.scrollvalue then
status.scrollvalue = 0
end
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
content.width = width
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
content.height = height
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
local num = AceGUI:GetNextWidgetNum(Type)
 
local scrollframe = CreateFrame("ScrollFrame", nil, frame)
scrollframe:SetPoint("TOPLEFT")
scrollframe:SetPoint("BOTTOMRIGHT")
scrollframe:EnableMouseWheel(true)
scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
 
local scrollbar = CreateFrame("Slider", ("AceConfigDialogScrollFrame%dScrollBar"):format(num), scrollframe, "UIPanelScrollBarTemplate")
scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
scrollbar:SetMinMaxValues(0, 1000)
scrollbar:SetValueStep(1)
scrollbar:SetValue(0)
scrollbar:SetWidth(16)
scrollbar:Hide()
-- set the script as the last step, so it doesn't fire yet
scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged)
 
local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
scrollbg:SetAllPoints(scrollbar)
scrollbg:SetTexture(0, 0, 0, 0.4)
 
--Container Support
local content = CreateFrame("Frame", nil, scrollframe)
content:SetPoint("TOPLEFT")
content:SetPoint("TOPRIGHT")
content:SetHeight(400)
scrollframe:SetScrollChild(content)
 
local widget = {
localstatus = { scrollvalue = 0 },
scrollframe = scrollframe,
scrollbar = scrollbar,
content = content,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
scrollframe.obj, scrollbar.obj = widget, widget
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua New file
0,0 → 1,670
--[[-----------------------------------------------------------------------------
TreeGroup Container
Container that uses a tree control to switch between groups.
-------------------------------------------------------------------------------]]
local Type, Version = "TreeGroup", 30
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
local math_min, math_max, floor = math.min, math.max, floor
local select, tremove, unpack = select, table.remove, unpack
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE
 
-- Recycling functions
local new, del
do
local pool = setmetatable({},{__mode='k'})
function new()
local t = next(pool)
if t then
pool[t] = nil
return t
else
return {}
end
end
function del(t)
for k in pairs(t) do
t[k] = nil
end
pool[t] = true
end
end
 
local DEFAULT_TREE_WIDTH = 175
local DEFAULT_TREE_SIZABLE = true
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function GetButtonUniqueValue(line)
local parent = line.parent
if parent and parent.value then
return GetButtonUniqueValue(parent).."\001"..line.value
else
return line.value
end
end
 
local function UpdateButton(button, treeline, selected, canExpand, isExpanded)
local self = button.obj
local toggle = button.toggle
local frame = self.frame
local text = treeline.text or ""
local icon = treeline.icon
local iconCoords = treeline.iconCoords
local level = treeline.level
local value = treeline.value
local uniquevalue = treeline.uniquevalue
local disabled = treeline.disabled
 
button.treeline = treeline
button.value = value
button.uniquevalue = uniquevalue
if selected then
button:LockHighlight()
button.selected = true
else
button:UnlockHighlight()
button.selected = false
end
local normalTexture = button:GetNormalTexture()
local line = button.line
button.level = level
if ( level == 1 ) then
button:SetNormalFontObject("GameFontNormal")
button:SetHighlightFontObject("GameFontHighlight")
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2)
else
button:SetNormalFontObject("GameFontHighlightSmall")
button:SetHighlightFontObject("GameFontHighlightSmall")
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2)
end
 
if disabled then
button:EnableMouse(false)
button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE)
else
button.text:SetText(text)
button:EnableMouse(true)
end
 
if icon then
button.icon:SetTexture(icon)
button.icon:SetPoint("LEFT", 8 * level, (level == 1) and 0 or 1)
else
button.icon:SetTexture(nil)
end
 
if iconCoords then
button.icon:SetTexCoord(unpack(iconCoords))
else
button.icon:SetTexCoord(0, 1, 0, 1)
end
 
if canExpand then
if not isExpanded then
toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP")
toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN")
else
toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
end
toggle:Show()
else
toggle:Hide()
end
end
 
local function ShouldDisplayLevel(tree)
local result = false
for k, v in ipairs(tree) do
if v.children == nil and v.visible ~= false then
result = true
elseif v.children then
result = result or ShouldDisplayLevel(v.children)
end
if result then return result end
end
return false
end
 
local function addLine(self, v, tree, level, parent)
local line = new()
line.value = v.value
line.text = v.text
line.icon = v.icon
line.iconCoords = v.iconCoords
line.disabled = v.disabled
line.tree = tree
line.level = level
line.parent = parent
line.visible = v.visible
line.uniquevalue = GetButtonUniqueValue(line)
if v.children then
line.hasChildren = true
else
line.hasChildren = nil
end
self.lines[#self.lines+1] = line
return line
end
 
--fire an update after one frame to catch the treeframes height
local function FirstFrameUpdate(frame)
local self = frame.obj
frame:SetScript("OnUpdate", nil)
self:RefreshTree()
end
 
local function BuildUniqueValue(...)
local n = select('#', ...)
if n == 1 then
return ...
else
return (...).."\001"..BuildUniqueValue(select(2,...))
end
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Expand_OnClick(frame)
local button = frame.button
local self = button.obj
local status = (self.status or self.localstatus).groups
status[button.uniquevalue] = not status[button.uniquevalue]
self:RefreshTree()
end
 
local function Button_OnClick(frame)
local self = frame.obj
self:Fire("OnClick", frame.uniquevalue, frame.selected)
if not frame.selected then
self:SetSelected(frame.uniquevalue)
frame.selected = true
frame:LockHighlight()
self:RefreshTree()
end
AceGUI:ClearFocus()
end
 
local function Button_OnDoubleClick(button)
local self = button.obj
local status = self.status or self.localstatus
local status = (self.status or self.localstatus).groups
status[button.uniquevalue] = not status[button.uniquevalue]
self:RefreshTree()
end
 
local function Button_OnEnter(frame)
local self = frame.obj
self:Fire("OnButtonEnter", frame.uniquevalue, frame)
 
if self.enabletooltips then
GameTooltip:SetOwner(frame, "ANCHOR_NONE")
GameTooltip:SetPoint("LEFT",frame,"RIGHT")
GameTooltip:SetText(frame.text:GetText() or "", 1, .82, 0, 1)
 
GameTooltip:Show()
end
end
 
local function Button_OnLeave(frame)
local self = frame.obj
self:Fire("OnButtonLeave", frame.uniquevalue, frame)
 
if self.enabletooltips then
GameTooltip:Hide()
end
end
 
local function OnScrollValueChanged(frame, value)
if frame.obj.noupdate then return end
local self = frame.obj
local status = self.status or self.localstatus
status.scrollvalue = value
self:RefreshTree()
AceGUI:ClearFocus()
end
 
local function Tree_OnSizeChanged(frame)
frame.obj:RefreshTree()
end
 
local function Tree_OnMouseWheel(frame, delta)
local self = frame.obj
if self.showscroll then
local scrollbar = self.scrollbar
local min, max = scrollbar:GetMinMaxValues()
local value = scrollbar:GetValue()
local newvalue = math_min(max,math_max(min,value - delta))
if value ~= newvalue then
scrollbar:SetValue(newvalue)
end
end
end
 
local function Dragger_OnLeave(frame)
frame:SetBackdropColor(1, 1, 1, 0)
end
 
local function Dragger_OnEnter(frame)
frame:SetBackdropColor(1, 1, 1, 0.8)
end
 
local function Dragger_OnMouseDown(frame)
local treeframe = frame:GetParent()
treeframe:StartSizing("RIGHT")
end
 
local function Dragger_OnMouseUp(frame)
local treeframe = frame:GetParent()
local self = treeframe.obj
local frame = treeframe:GetParent()
treeframe:StopMovingOrSizing()
--treeframe:SetScript("OnUpdate", nil)
treeframe:SetUserPlaced(false)
--Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
treeframe:SetHeight(0)
treeframe:SetPoint("TOPLEFT", frame, "TOPLEFT",0,0)
treeframe:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0)
 
local status = self.status or self.localstatus
status.treewidth = treeframe:GetWidth()
 
treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
-- recalculate the content width
treeframe.obj:OnWidthSet(status.fullwidth)
-- update the layout of the content
treeframe.obj:DoLayout()
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE)
self:EnableButtonTooltips(true)
end,
 
["OnRelease"] = function(self)
self.status = nil
for k, v in pairs(self.localstatus) do
if k == "groups" then
for k2 in pairs(v) do
v[k2] = nil
end
else
self.localstatus[k] = nil
end
end
self.localstatus.scrollvalue = 0
self.localstatus.treewidth = DEFAULT_TREE_WIDTH
self.localstatus.treesizable = DEFAULT_TREE_SIZABLE
end,
 
["EnableButtonTooltips"] = function(self, enable)
self.enabletooltips = enable
end,
 
["CreateButton"] = function(self)
local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
local button = CreateFrame("Button", ("AceGUI30TreeButton%d"):format(num), self.treeframe, "OptionsListButtonTemplate")
button.obj = self
 
local icon = button:CreateTexture(nil, "OVERLAY")
icon:SetWidth(14)
icon:SetHeight(14)
button.icon = icon
 
button:SetScript("OnClick",Button_OnClick)
button:SetScript("OnDoubleClick", Button_OnDoubleClick)
button:SetScript("OnEnter",Button_OnEnter)
button:SetScript("OnLeave",Button_OnLeave)
 
button.toggle.button = button
button.toggle:SetScript("OnClick",Expand_OnClick)
 
return button
end,
 
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
if not status.groups then
status.groups = {}
end
if not status.scrollvalue then
status.scrollvalue = 0
end
if not status.treewidth then
status.treewidth = DEFAULT_TREE_WIDTH
end
if not status.treesizable then
status.treesizable = DEFAULT_TREE_SIZABLE
end
self:SetTreeWidth(status.treewidth,status.treesizable)
self:RefreshTree()
end,
 
--sets the tree to be displayed
["SetTree"] = function(self, tree, filter)
self.filter = filter
if tree then
assert(type(tree) == "table")
end
self.tree = tree
self:RefreshTree()
end,
 
["BuildLevel"] = function(self, tree, level, parent)
local groups = (self.status or self.localstatus).groups
local hasChildren = self.hasChildren
 
for i, v in ipairs(tree) do
if v.children then
if not self.filter or ShouldDisplayLevel(v.children) then
local line = addLine(self, v, tree, level, parent)
if groups[line.uniquevalue] then
self:BuildLevel(v.children, level+1, line)
end
end
elseif v.visible ~= false or not self.filter then
addLine(self, v, tree, level, parent)
end
end
end,
 
["RefreshTree"] = function(self)
local buttons = self.buttons
local lines = self.lines
 
for i, v in ipairs(buttons) do
v:Hide()
end
while lines[1] do
local t = tremove(lines)
for k in pairs(t) do
t[k] = nil
end
del(t)
end
 
if not self.tree then return end
--Build the list of visible entries from the tree and status tables
local status = self.status or self.localstatus
local groupstatus = status.groups
local tree = self.tree
 
local treeframe = self.treeframe
 
self:BuildLevel(tree, 1)
 
local numlines = #lines
 
local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
 
local first, last
 
if numlines <= maxlines then
--the whole tree fits in the frame
status.scrollvalue = 0
self:ShowScroll(false)
first, last = 1, numlines
else
self:ShowScroll(true)
--scrolling will be needed
self.noupdate = true
self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
--check if we are scrolled down too far
if numlines - status.scrollvalue < maxlines then
status.scrollvalue = numlines - maxlines
self.scrollbar:SetValue(status.scrollvalue)
end
self.noupdate = nil
first, last = status.scrollvalue+1, status.scrollvalue + maxlines
end
 
local buttonnum = 1
for i = first, last do
local line = lines[i]
local button = buttons[buttonnum]
if not button then
button = self:CreateButton()
 
buttons[buttonnum] = button
button:SetParent(treeframe)
button:SetFrameLevel(treeframe:GetFrameLevel()+1)
button:ClearAllPoints()
if i == 1 then
if self.showscroll then
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
else
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
end
else
button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0)
button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0)
end
end
 
UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] )
button:Show()
buttonnum = buttonnum + 1
end
end,
 
["SetSelected"] = function(self, value)
local status = self.status or self.localstatus
if status.selected ~= value then
status.selected = value
self:Fire("OnGroupSelected", value)
end
end,
 
["Select"] = function(self, uniquevalue, ...)
self.filter = false
local status = self.status or self.localstatus
local groups = status.groups
for i = 1, select('#', ...) do
groups[BuildUniqueValue(select(i, ...))] = true
end
status.selected = uniquevalue
self:RefreshTree()
self:Fire("OnGroupSelected", uniquevalue)
end,
 
["SelectByPath"] = function(self, ...)
self:Select(BuildUniqueValue(...), ...)
end,
 
["SelectByValue"] = function(self, uniquevalue)
self:Select(uniquevalue, ("\001"):split(uniquevalue))
end,
 
["ShowScroll"] = function(self, show)
self.showscroll = show
if show then
self.scrollbar:Show()
if self.buttons[1] then
self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
end
else
self.scrollbar:Hide()
if self.buttons[1] then
self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
end
end
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local treeframe = self.treeframe
local status = self.status or self.localstatus
status.fullwidth = width
 
local contentwidth = width - status.treewidth - 20
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
 
local maxtreewidth = math_min(400, width - 50)
 
if maxtreewidth > 100 and status.treewidth > maxtreewidth then
self:SetTreeWidth(maxtreewidth, status.treesizable)
end
treeframe:SetMaxResize(maxtreewidth, 1600)
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 20
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
 
["SetTreeWidth"] = function(self, treewidth, resizable)
if not resizable then
if type(treewidth) == 'number' then
resizable = false
elseif type(treewidth) == 'boolean' then
resizable = treewidth
treewidth = DEFAULT_TREE_WIDTH
else
resizable = false
treewidth = DEFAULT_TREE_WIDTH
end
end
self.treeframe:SetWidth(treewidth)
self.dragger:EnableMouse(resizable)
 
local status = self.status or self.localstatus
status.treewidth = treewidth
status.treesizable = resizable
 
-- recalculate the content width
if status.fullwidth then
self:OnWidthSet(status.fullwidth)
end
end,
 
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + 20)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
 
local DraggerBackdrop = {
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
edgeFile = nil,
tile = true, tileSize = 16, edgeSize = 0,
insets = { left = 3, right = 3, top = 7, bottom = 7 }
}
 
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", nil, UIParent)
 
local treeframe = CreateFrame("Frame", nil, frame)
treeframe:SetPoint("TOPLEFT")
treeframe:SetPoint("BOTTOMLEFT")
treeframe:SetWidth(DEFAULT_TREE_WIDTH)
treeframe:EnableMouseWheel(true)
treeframe:SetBackdrop(PaneBackdrop)
treeframe:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
treeframe:SetBackdropBorderColor(0.4, 0.4, 0.4)
treeframe:SetResizable(true)
treeframe:SetMinResize(100, 1)
treeframe:SetMaxResize(400, 1600)
treeframe:SetScript("OnUpdate", FirstFrameUpdate)
treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged)
treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel)
 
local dragger = CreateFrame("Frame", nil, treeframe)
dragger:SetWidth(8)
dragger:SetPoint("TOP", treeframe, "TOPRIGHT")
dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT")
dragger:SetBackdrop(DraggerBackdrop)
dragger:SetBackdropColor(1, 1, 1, 0)
dragger:SetScript("OnEnter", Dragger_OnEnter)
dragger:SetScript("OnLeave", Dragger_OnLeave)
dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
 
local scrollbar = CreateFrame("Slider", ("AceConfigDialogTreeGroup%dScrollBar"):format(num), treeframe, "UIPanelScrollBarTemplate")
scrollbar:SetScript("OnValueChanged", nil)
scrollbar:SetPoint("TOPRIGHT", -10, -26)
scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
scrollbar:SetMinMaxValues(0,0)
scrollbar:SetValueStep(1)
scrollbar:SetValue(0)
scrollbar:SetWidth(16)
scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
 
local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
scrollbg:SetAllPoints(scrollbar)
scrollbg:SetTexture(0,0,0,0.4)
 
local border = CreateFrame("Frame",nil,frame)
border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT")
border:SetPoint("BOTTOMRIGHT")
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
border:SetBackdropBorderColor(0.4, 0.4, 0.4)
 
--Container Support
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
 
local widget = {
frame = frame,
lines = {},
levels = {},
buttons = {},
hasChildren = {},
localstatus = { groups = {}, scrollvalue = 0 },
filter = false,
treeframe = treeframe,
dragger = dragger,
scrollbar = scrollbar,
border = border,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua New file
0,0 → 1,92
--[[-----------------------------------------------------------------------------
Button Widget
Graphical Button.
-------------------------------------------------------------------------------]]
local Type, Version = "Button", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local _G = _G
local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Button_OnClick(frame, ...)
PlaySound("igMainMenuOption")
frame.obj:Fire("OnClick", ...)
AceGUI:ClearFocus()
end
 
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- restore default values
self:SetHeight(24)
self:SetWidth(200)
self:SetDisabled(false)
self:SetText()
end,
 
-- ["OnRelease"] = nil,
 
["SetText"] = function(self, text)
self.text:SetText(text)
end,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
else
self.frame:Enable()
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate2")
frame:Hide()
 
frame:EnableMouse(true)
frame:SetScript("OnClick", Button_OnClick)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
 
local text = frame:GetFontString()
text:ClearAllPoints()
text:SetPoint("TOPLEFT", 15, -1)
text:SetPoint("BOTTOMRIGHT", -15, 1)
text:SetJustifyV("MIDDLE")
 
local widget = {
text = text,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua New file
0,0 → 1,465
--[[ $Id: AceGUIWidget-DropDown-Items.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
 
local AceGUI = LibStub("AceGUI-3.0")
 
-- Lua APIs
local select, assert = select, assert
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame = CreateFrame
 
local function fixlevels(parent,...)
local i = 1
local child = select(i, ...)
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1)
fixlevels(child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
 
local function fixstrata(strata, parent, ...)
local i = 1
local child = select(i, ...)
parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
 
-- ItemBase is the base "class" for all dropdown items.
-- Each item has to use ItemBase.Create(widgetType) to
-- create an initial 'self' value.
-- ItemBase will add common functions and ui event handlers.
-- Be sure to keep basic usage when you override functions.
 
local ItemBase = {
-- NOTE: The ItemBase version is added to each item's version number
-- to ensure proper updates on ItemBase changes.
-- Use at least 1000er steps.
version = 1000,
counter = 0,
}
 
function ItemBase.Frame_OnEnter(this)
local self = this.obj
 
if self.useHighlight then
self.highlight:Show()
end
self:Fire("OnEnter")
 
if self.specialOnEnter then
self.specialOnEnter(self)
end
end
 
function ItemBase.Frame_OnLeave(this)
local self = this.obj
 
self.highlight:Hide()
self:Fire("OnLeave")
 
if self.specialOnLeave then
self.specialOnLeave(self)
end
end
 
-- exported, AceGUI callback
function ItemBase.OnAcquire(self)
self.frame:SetToplevel(true)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
end
 
-- exported, AceGUI callback
function ItemBase.OnRelease(self)
self:SetDisabled(false)
self.pullout = nil
self.frame:SetParent(nil)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetPullout(self, pullout)
self.pullout = pullout
 
self.frame:SetParent(nil)
self.frame:SetParent(pullout.itemFrame)
self.parent = pullout.itemFrame
fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
end
 
-- exported
function ItemBase.SetText(self, text)
self.text:SetText(text or "")
end
 
-- exported
function ItemBase.GetText(self)
return self.text:GetText()
end
 
-- exported
function ItemBase.SetPoint(self, ...)
self.frame:SetPoint(...)
end
 
-- exported
function ItemBase.Show(self)
self.frame:Show()
end
 
-- exported
function ItemBase.Hide(self)
self.frame:Hide()
end
 
-- exported
function ItemBase.SetDisabled(self, disabled)
self.disabled = disabled
if disabled then
self.useHighlight = false
self.text:SetTextColor(.5, .5, .5)
else
self.useHighlight = true
self.text:SetTextColor(1, 1, 1)
end
end
 
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetOnLeave(self, func)
self.specialOnLeave = func
end
 
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetOnEnter(self, func)
self.specialOnEnter = func
end
 
function ItemBase.Create(type)
-- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget
local count = AceGUI:GetNextWidgetNum(type)
local frame = CreateFrame("Button", "AceGUI30DropDownItem"..count)
local self = {}
self.frame = frame
frame.obj = self
self.type = type
 
self.useHighlight = true
 
frame:SetHeight(17)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
 
local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
text:SetTextColor(1,1,1)
text:SetJustifyH("LEFT")
text:SetPoint("TOPLEFT",frame,"TOPLEFT",18,0)
text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-8,0)
self.text = text
 
local highlight = frame:CreateTexture(nil, "OVERLAY")
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetHeight(14)
highlight:ClearAllPoints()
highlight:SetPoint("RIGHT",frame,"RIGHT",-3,0)
highlight:SetPoint("LEFT",frame,"LEFT",5,0)
highlight:Hide()
self.highlight = highlight
 
local check = frame:CreateTexture("OVERLAY")
check:SetWidth(16)
check:SetHeight(16)
check:SetPoint("LEFT",frame,"LEFT",3,-1)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:Hide()
self.check = check
 
local sub = frame:CreateTexture("OVERLAY")
sub:SetWidth(16)
sub:SetHeight(16)
sub:SetPoint("RIGHT",frame,"RIGHT",-3,-1)
sub:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
sub:Hide()
self.sub = sub
 
frame:SetScript("OnEnter", ItemBase.Frame_OnEnter)
frame:SetScript("OnLeave", ItemBase.Frame_OnLeave)
 
self.OnAcquire = ItemBase.OnAcquire
self.OnRelease = ItemBase.OnRelease
 
self.SetPullout = ItemBase.SetPullout
self.GetText = ItemBase.GetText
self.SetText = ItemBase.SetText
self.SetDisabled = ItemBase.SetDisabled
 
self.SetPoint = ItemBase.SetPoint
self.Show = ItemBase.Show
self.Hide = ItemBase.Hide
 
self.SetOnLeave = ItemBase.SetOnLeave
self.SetOnEnter = ItemBase.SetOnEnter
 
return self
end
 
--[[
Template for items:
 
-- Item:
--
do
local widgetType = "Dropdown-Item-"
local widgetVersion = 1
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
--]]
 
-- Item: Header
-- A single text entry.
-- Special: Different text color and no highlight
do
local widgetType = "Dropdown-Item-Header"
local widgetVersion = 1
 
local function OnEnter(this)
local self = this.obj
self:Fire("OnEnter")
 
if self.specialOnEnter then
self.specialOnEnter(self)
end
end
 
local function OnLeave(this)
local self = this.obj
self:Fire("OnLeave")
 
if self.specialOnLeave then
self.specialOnLeave(self)
end
end
 
-- exported, override
local function SetDisabled(self, disabled)
ItemBase.SetDisabled(self, disabled)
if not disabled then
self.text:SetTextColor(1, 1, 0)
end
end
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
self.SetDisabled = SetDisabled
 
self.frame:SetScript("OnEnter", OnEnter)
self.frame:SetScript("OnLeave", OnLeave)
 
self.text:SetTextColor(1, 1, 0)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
 
-- Item: Execute
-- A simple button
do
local widgetType = "Dropdown-Item-Execute"
local widgetVersion = 1
 
local function Frame_OnClick(this, button)
local self = this.obj
if self.disabled then return end
self:Fire("OnClick")
if self.pullout then
self.pullout:Close()
end
end
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
self.frame:SetScript("OnClick", Frame_OnClick)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
 
-- Item: Toggle
-- Some sort of checkbox for dropdown menus.
-- Does not close the pullout on click.
do
local widgetType = "Dropdown-Item-Toggle"
local widgetVersion = 3
 
local function UpdateToggle(self)
if self.value then
self.check:Show()
else
self.check:Hide()
end
end
 
local function OnRelease(self)
ItemBase.OnRelease(self)
self:SetValue(nil)
end
 
local function Frame_OnClick(this, button)
local self = this.obj
if self.disabled then return end
self.value = not self.value
if self.value then
PlaySound("igMainMenuOptionCheckBoxOn")
else
PlaySound("igMainMenuOptionCheckBoxOff")
end
UpdateToggle(self)
self:Fire("OnValueChanged", self.value)
end
 
-- exported
local function SetValue(self, value)
self.value = value
UpdateToggle(self)
end
 
-- exported
local function GetValue(self)
return self.value
end
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
self.frame:SetScript("OnClick", Frame_OnClick)
 
self.SetValue = SetValue
self.GetValue = GetValue
self.OnRelease = OnRelease
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
 
-- Item: Menu
-- Shows a submenu on mouse over
-- Does not close the pullout on click
do
local widgetType = "Dropdown-Item-Menu"
local widgetVersion = 2
 
local function OnEnter(this)
local self = this.obj
self:Fire("OnEnter")
 
if self.specialOnEnter then
self.specialOnEnter(self)
end
 
self.highlight:Show()
 
if not self.disabled and self.submenu then
self.submenu:Open("TOPLEFT", self.frame, "TOPRIGHT", self.pullout:GetRightBorderWidth(), 0, self.frame:GetFrameLevel() + 100)
end
end
 
local function OnHide(this)
local self = this.obj
if self.submenu then
self.submenu:Close()
end
end
 
-- exported
local function SetMenu(self, menu)
assert(menu.type == "Dropdown-Pullout")
self.submenu = menu
end
 
-- exported
local function CloseMenu(self)
self.submenu:Close()
end
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
self.sub:Show()
 
self.frame:SetScript("OnEnter", OnEnter)
self.frame:SetScript("OnHide", OnHide)
 
self.SetMenu = SetMenu
self.CloseMenu = CloseMenu
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
 
-- Item: Separator
-- A single line to separate items
do
local widgetType = "Dropdown-Item-Separator"
local widgetVersion = 1
 
-- exported, override
local function SetDisabled(self, disabled)
ItemBase.SetDisabled(self, disabled)
self.useHighlight = false
end
 
local function Constructor()
local self = ItemBase.Create(widgetType)
 
self.SetDisabled = SetDisabled
 
local line = self.frame:CreateTexture(nil, "OVERLAY")
line:SetHeight(1)
line:SetTexture(.5, .5, .5)
line:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0)
 
self.text:Hide()
 
self.useHighlight = false
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua New file
0,0 → 1,186
--[[-----------------------------------------------------------------------------
ColorPicker Widget
-------------------------------------------------------------------------------]]
local Type, Version = "ColorPicker", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: ShowUIPanel, HideUIPanel, ColorPickerFrame, OpacitySliderFrame
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function ColorCallback(self, r, g, b, a, isAlpha)
if not self.HasAlpha then
a = 1
end
self:SetColor(r, g, b, a)
if ColorPickerFrame:IsVisible() then
--colorpicker is still open
self:Fire("OnValueChanged", r, g, b, a)
else
--colorpicker is closed, color callback is first, ignore it,
--alpha callback is the final call after it closes so confirm now
if isAlpha then
self:Fire("OnValueConfirmed", r, g, b, a)
end
end
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function ColorSwatch_OnClick(frame)
HideUIPanel(ColorPickerFrame)
local self = frame.obj
if not self.disabled then
ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
 
ColorPickerFrame.func = function()
local r, g, b = ColorPickerFrame:GetColorRGB()
local a = 1 - OpacitySliderFrame:GetValue()
ColorCallback(self, r, g, b, a)
end
 
ColorPickerFrame.hasOpacity = self.HasAlpha
ColorPickerFrame.opacityFunc = function()
local r, g, b = ColorPickerFrame:GetColorRGB()
local a = 1 - OpacitySliderFrame:GetValue()
ColorCallback(self, r, g, b, a, true)
end
 
local r, g, b, a = self.r, self.g, self.b, self.a
if self.HasAlpha then
ColorPickerFrame.opacity = 1 - (a or 0)
end
ColorPickerFrame:SetColorRGB(r, g, b)
 
ColorPickerFrame.cancelFunc = function()
ColorCallback(self, r, g, b, a, true)
end
 
ShowUIPanel(ColorPickerFrame)
end
AceGUI:ClearFocus()
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetHeight(24)
self:SetWidth(200)
self:SetHasAlpha(false)
self:SetColor(0, 0, 0, 1)
self:SetDisabled(nil)
self:SetLabel(nil)
end,
 
-- ["OnRelease"] = nil,
 
["SetLabel"] = function(self, text)
self.text:SetText(text)
end,
 
["SetColor"] = function(self, r, g, b, a)
self.r = r
self.g = g
self.b = b
self.a = a or 1
self.colorSwatch:SetVertexColor(r, g, b, a)
end,
 
["SetHasAlpha"] = function(self, HasAlpha)
self.HasAlpha = HasAlpha
end,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if self.disabled then
self.frame:Disable()
self.text:SetTextColor(0.5, 0.5, 0.5)
else
self.frame:Enable()
self.text:SetTextColor(1, 1, 1)
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
 
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnClick", ColorSwatch_OnClick)
 
local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
colorSwatch:SetWidth(19)
colorSwatch:SetHeight(19)
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
colorSwatch:SetPoint("LEFT")
 
local texture = frame:CreateTexture(nil, "BACKGROUND")
texture:SetWidth(16)
texture:SetHeight(16)
texture:SetTexture(1, 1, 1)
texture:SetPoint("CENTER", colorSwatch)
texture:Show()
 
local checkers = frame:CreateTexture(nil, "BACKGROUND")
checkers:SetWidth(14)
checkers:SetHeight(14)
checkers:SetTexture("Tileset\\Generic\\Checkers")
checkers:SetTexCoord(.25, 0, 0.5, .25)
checkers:SetDesaturated(true)
checkers:SetVertexColor(1, 1, 1, 0.75)
checkers:SetPoint("CENTER", colorSwatch)
checkers:Show()
 
local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
text:SetHeight(24)
text:SetJustifyH("LEFT")
text:SetTextColor(1, 1, 1)
text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
text:SetPoint("RIGHT")
 
--local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
--highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
--highlight:SetBlendMode("ADD")
--highlight:SetAllPoints(frame)
 
local widget = {
colorSwatch = colorSwatch,
text = text,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua New file
0,0 → 1,101
--[[-----------------------------------------------------------------------------
InteractiveLabel Widget
-------------------------------------------------------------------------------]]
local Type, Version = "InteractiveLabel", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local select, pairs = select, pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function Label_OnClick(frame, button)
frame.obj:Fire("OnClick", button)
AceGUI:ClearFocus()
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:LabelOnAcquire()
self:SetHighlight()
self:SetHighlightTexCoord()
self:SetDisabled(false)
end,
 
-- ["OnRelease"] = nil,
 
["SetHighlight"] = function(self, ...)
self.highlight:SetTexture(...)
end,
 
["SetHighlightTexCoord"] = function(self, ...)
local c = select("#", ...)
if c == 4 or c == 8 then
self.highlight:SetTexCoord(...)
else
self.highlight:SetTexCoord(0, 1, 0, 1)
end
end,
 
["SetDisabled"] = function(self,disabled)
self.disabled = disabled
if disabled then
self.frame:EnableMouse(false)
self.label:SetTextColor(0.5, 0.5, 0.5)
else
self.frame:EnableMouse(true)
self.label:SetTextColor(1, 1, 1)
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
-- create a Label type that we will hijack
local label = AceGUI:Create("Label")
 
local frame = label.frame
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnMouseDown", Label_OnClick)
 
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetTexture(nil)
highlight:SetAllPoints()
highlight:SetBlendMode("ADD")
 
label.highlight = highlight
label.type = Type
label.LabelOnAcquire = label.OnAcquire
for method, func in pairs(methods) do
label[method] = func
end
 
return label
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
 
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua New file
0,0 → 1,162
--[[-----------------------------------------------------------------------------
Label Widget
Displays text and optionally an icon.
-------------------------------------------------------------------------------]]
local Type, Version = "Label", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local max, select, pairs = math.max, select, pairs
 
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
 
local function UpdateImageAnchor(self)
if self.resizing then return end
local frame = self.frame
local width = frame.width or frame:GetWidth() or 0
local image = self.image
local label = self.label
local height
 
label:ClearAllPoints()
image:ClearAllPoints()
 
if self.imageshown then
local imagewidth = image:GetWidth()
if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
-- image goes on top centered when less than 200 width for the text, or if there is no text
image:SetPoint("TOP")
label:SetPoint("TOP", image, "BOTTOM")
label:SetPoint("LEFT")
label:SetWidth(width)
height = image:GetHeight() + label:GetHeight()
else
-- image on the left
image:SetPoint("TOPLEFT")
label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
label:SetWidth(width - imagewidth - 4)
height = max(image:GetHeight(), label:GetHeight())
end
else
-- no image shown
label:SetPoint("TOPLEFT")
label:SetWidth(width)
height = label:GetHeight()
end
 
self.resizing = true
frame:SetHeight(height)
frame.height = height
self.resizing = nil
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- set the flag to stop constant size updates
self.resizing = true
-- height is set dynamically by the text and image size
self:SetWidth(200)
self:SetText()
self:SetImage(nil)
self:SetImageSize(16, 16)
self:SetColor()
self:SetFontObject()
 
-- reset the flag
self.resizing = nil
-- run the update explicitly
UpdateImageAnchor(self)
end,
 
-- ["OnRelease"] = nil,
 
["OnWidthSet"] = function(self, width)
UpdateImageAnchor(self)
end,
 
["SetText"] = function(self, text)
self.label:SetText(text)
UpdateImageAnchor(self)
end,
 
["SetColor"] = function(self, r, g, b)
if not (r and g and b) then
r, g, b = 1, 1, 1
end
self.label:SetVertexColor(r, g, b)
end,
 
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
 
if image:GetTexture() then
self.imageshown = true
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
else
self.imageshown = nil
end
UpdateImageAnchor(self)
end,
 
["SetFont"] = function(self, font, height, flags)
self.label:SetFont(font, height, flags)
end,
 
["SetFontObject"] = function(self, font)
self:SetFont((font or GameFontHighlightSmall):GetFont())
end,
 
["SetImageSize"] = function(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
UpdateImageAnchor(self)
end,
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
 
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
 
local image = frame:CreateTexture(nil, "BACKGROUND")
 
-- create widget
local widget = {
label = label,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua New file
0,0 → 1,283
local Type, Version = "MultiLineEditBox", 22
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local GetCursorInfo, GetSpellName, ClearCursor = GetCursorInfo, GetSpellName, ClearCursor
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _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: ACCEPT, ChatFontNormal
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function OnClick(self) -- Button
self = self.obj
self.editBox:ClearFocus()
if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
self.button:Disable()
end
end
 
local function OnCursorChanged(self, _, y, _, cursorHeight) -- EditBox
self, y = self.obj.scrollFrame, -y
local offset = self:GetVerticalScroll()
if y < offset then
self:SetVerticalScroll(y)
else
y = y + cursorHeight - self:GetHeight()
if y > offset then
self:SetVerticalScroll(y)
end
end
end
 
local function OnEditFocusLost(self) -- EditBox
self:HighlightText(0, 0)
end
 
local function OnEnter(self) -- EditBox / ScrollFrame
self = self.obj
if not self.entered then
self.entered = true
self:Fire("OnEnter")
end
end
 
local function OnLeave(self) -- EditBox / ScrollFrame
self = self.obj
if self.entered then
self.entered = nil
self:Fire("OnLeave")
end
end
 
local function OnMouseUp(self) -- ScrollFrame
self = self.obj.editBox
self:SetFocus()
self:SetCursorPosition(self:GetNumLetters())
end
 
local function OnReceiveDrag(self) -- EditBox / ScrollFrame
local type, id, info = GetCursorInfo()
if type == "spell" then
info, id = GetSpellName(id, info)
if id and id:match("%d") then
info = info .. "(" .. id .. ")"
end
elseif type ~= "item" then
return
end
ClearCursor()
self = self.obj
local editBox = self.editBox
if not editBox:HasFocus() then
editBox:SetFocus()
editBox:SetCursorPosition(editBox:GetNumLetters())
end
editBox:Insert(info)
self.button:Enable()
end
 
local function OnSizeChanged(self, width, height) -- ScrollFrame
self.obj.editBox:SetWidth(width)
end
 
local function OnTextChanged(self, userInput) -- EditBox
if userInput then
self = self.obj
self:Fire("OnTextChanged", self.editBox:GetText())
self.button:Enable()
end
end
 
local function OnTextSet(self) -- EditBox
self:HighlightText(0, 0)
self:SetCursorPosition(self:GetNumLetters())
self:SetCursorPosition(0)
self.obj.button:Disable()
end
 
local function OnVerticalScroll(self, offset) -- ScrollFrame
local editBox = self.obj.editBox
editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["GetText"] = function(self)
return self.editBox:GetText()
end,
 
["OnAcquire"] = function(self)
self.editBox:SetText("")
self:SetDisabled(false)
self:SetWidth(200)
self:SetNumLines()
self.entered = nil
self:SetMaxLetters(0)
end,
 
["OnRelease"] = function(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end,
 
["SetDisabled"] = function(self, disabled)
local editBox = self.editBox
if disabled then
editBox:ClearFocus()
editBox:EnableMouse(false)
editBox:SetTextColor(0.5, 0.5, 0.5)
self.label:SetTextColor(0.5, 0.5, 0.5)
self.scrollFrame:EnableMouse(false)
self.button:Disable()
else
editBox:EnableMouse(true)
editBox:SetTextColor(1, 1, 1)
self.label:SetTextColor(1, 0.82, 0)
self.scrollFrame:EnableMouse(true)
end
end,
 
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:SetText(text)
if self.labelHeight ~= 10 then
self.labelHeight = 10
self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
self:SetHeight(self.frame.height + 10)
self.label:Show()
end
elseif self.labelHeight ~= 0 then
self.labelHeight = 0
self.label:Hide()
self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
self:SetHeight(self.frame.height - 10)
end
end,
 
["SetNumLines"] = function(self, value)
if not value or value < 4 then
value = 4
end
self:SetHeight(value * 14 + 41 + self.labelHeight)
end,
 
["SetText"] = function(self, text)
self.editBox:SetText(text)
end,
 
["SetMaxLetters"] = function (self, num)
self.editBox:SetMaxLetters(num or 0)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local backdrop = {
bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
insets = { left = 4, right = 3, top = 4, bottom = 3 }
}
 
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
 
local widgetNum = AceGUI:GetNextWidgetNum(Type)
 
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
label:SetJustifyH("LEFT")
label:SetText(ACCEPT)
label:SetHeight(10)
 
local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate2")
button:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 4)
button:SetHeight(22)
button:SetWidth(label:GetStringWidth() + 24)
button:SetText(ACCEPT)
button:SetScript("OnClick", OnClick)
button:Disable()
 
local text = button:GetFontString()
text:ClearAllPoints()
text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
text:SetJustifyV("MIDDLE")
 
local scrollBG = CreateFrame("Frame", nil, frame)
scrollBG:SetBackdrop(backdrop)
scrollBG:SetBackdropColor(0, 0, 0)
scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
 
local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
 
local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
scrollBar:ClearAllPoints()
scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
scrollBar:SetPoint("RIGHT", frame, "RIGHT")
 
scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
 
scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
scrollFrame:SetScript("OnEnter", OnEnter)
scrollFrame:SetScript("OnLeave", OnLeave)
scrollFrame:SetScript("OnMouseUp", OnMouseUp)
scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
 
local editBox = CreateFrame("EditBox", nil, scrollFrame)
editBox:SetAllPoints()
editBox:SetFontObject(ChatFontNormal)
editBox:SetMultiLine(true)
editBox:EnableMouse(true)
editBox:SetAutoFocus(false)
editBox:SetCountInvisibleLetters(false)
editBox:SetScript("OnCursorChanged", OnCursorChanged)
editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
editBox:SetScript("OnEnter", OnEnter)
editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
editBox:SetScript("OnLeave", OnLeave)
editBox:SetScript("OnMouseDown", OnReceiveDrag)
editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
editBox:SetScript("OnTextChanged", OnTextChanged)
editBox:SetScript("OnTextSet", OnTextSet)
 
scrollFrame:SetScrollChild(editBox)
 
local widget = {
button = button,
editBox = editBox,
frame = frame,
label = label,
labelHeight = 10,
scrollBar = scrollBar,
scrollFrame = scrollFrame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
 
AceGUI:RegisterAsWidget(widget)
return widget
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua New file
0,0 → 1,348
--[[-----------------------------------------------------------------------------
TabGroup Container
Container that uses tabs on top to switch between groups.
-------------------------------------------------------------------------------]]
local Type, Version = "TabGroup", 30
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _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: PanelTemplates_TabResize, PanelTemplates_SetDisabledTabState, PanelTemplates_SelectTab, PanelTemplates_DeselectTab
 
-- local upvalue storage used by BuildTabs
local widths = {}
local rowwidths = {}
local rowends = {}
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function UpdateTabLook(frame)
if frame.disabled then
PanelTemplates_SetDisabledTabState(frame)
elseif frame.selected then
PanelTemplates_SelectTab(frame)
else
PanelTemplates_DeselectTab(frame)
end
end
 
local function Tab_SetText(frame, text)
frame:_SetText(text)
local width = frame.obj.frame.width or frame.obj.frame:GetWidth() or 0
PanelTemplates_TabResize(frame, 0, nil, width)
end
 
local function Tab_SetSelected(frame, selected)
frame.selected = selected
UpdateTabLook(frame)
end
 
local function Tab_SetDisabled(frame, disabled)
frame.disabled = disabled
UpdateTabLook(frame)
end
 
local function BuildTabsOnUpdate(frame)
local self = frame.obj
self:BuildTabs()
frame:SetScript("OnUpdate", nil)
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Tab_OnClick(frame)
if not (frame.selected or frame.disabled) then
PlaySound("igCharacterInfoTab")
frame.obj:SelectTab(frame.value)
end
end
 
local function Tab_OnEnter(frame)
local self = frame.obj
self:Fire("OnTabEnter", self.tabs[frame.id].value, frame)
end
 
local function Tab_OnLeave(frame)
local self = frame.obj
self:Fire("OnTabLeave", self.tabs[frame.id].value, frame)
end
 
local function Tab_OnShow(frame)
_G[frame:GetName().."HighlightTexture"]:SetWidth(frame:GetTextWidth() + 30)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetTitle()
end,
 
["OnRelease"] = function(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
self.tablist = nil
for _, tab in pairs(self.tabs) do
tab:Hide()
end
end,
 
["CreateTab"] = function(self, id)
local tabname = ("AceGUITabGroup%dTab%d"):format(self.num, id)
local tab = CreateFrame("Button", tabname, self.border, "OptionsFrameTabButtonTemplate")
tab.obj = self
tab.id = id
 
tab.text = _G[tabname .. "Text"]
tab.text:ClearAllPoints()
tab.text:SetPoint("LEFT", 14, -3)
tab.text:SetPoint("RIGHT", -12, -3)
 
tab:SetScript("OnClick", Tab_OnClick)
tab:SetScript("OnEnter", Tab_OnEnter)
tab:SetScript("OnLeave", Tab_OnLeave)
tab:SetScript("OnShow", Tab_OnShow)
 
tab._SetText = tab.SetText
tab.SetText = Tab_SetText
tab.SetSelected = Tab_SetSelected
tab.SetDisabled = Tab_SetDisabled
 
return tab
end,
 
["SetTitle"] = function(self, text)
self.titletext:SetText(text or "")
if text and text ~= "" then
self.alignoffset = 25
else
self.alignoffset = 18
end
self:BuildTabs()
end,
 
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
end,
 
["SelectTab"] = function(self, value)
local status = self.status or self.localstatus
local found
for i, v in ipairs(self.tabs) do
if v.value == value then
v:SetSelected(true)
found = true
else
v:SetSelected(false)
end
end
status.selected = value
if found then
self:Fire("OnGroupSelected",value)
end
end,
 
["SetTabs"] = function(self, tabs)
self.tablist = tabs
self:BuildTabs()
end,
 
 
["BuildTabs"] = function(self)
local hastitle = (self.titletext:GetText() and self.titletext:GetText() ~= "")
local status = self.status or self.localstatus
local tablist = self.tablist
local tabs = self.tabs
 
if not tablist then return end
 
local width = self.frame.width or self.frame:GetWidth() or 0
 
wipe(widths)
wipe(rowwidths)
wipe(rowends)
 
--Place Text into tabs and get thier initial width
for i, v in ipairs(tablist) do
local tab = tabs[i]
if not tab then
tab = self:CreateTab(i)
tabs[i] = tab
end
 
tab:Show()
tab:SetText(v.text)
tab:SetDisabled(v.disabled)
tab.value = v.value
 
widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
end
 
for i = (#tablist)+1, #tabs, 1 do
tabs[i]:Hide()
end
 
--First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
local numtabs = #tablist
local numrows = 1
local usedwidth = 0
 
for i = 1, #tablist do
--If this is not the first tab of a row and there isn't room for it
if usedwidth ~= 0 and (width - usedwidth - widths[i]) < 0 then
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
rowends[numrows] = i - 1
numrows = numrows + 1
usedwidth = 0
end
usedwidth = usedwidth + widths[i]
end
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
rowends[numrows] = #tablist
 
--Fix for single tabs being left on the last row, move a tab from the row above if applicable
if numrows > 1 then
--if the last row has only one tab
if rowends[numrows-1] == numtabs-1 then
--if there are more than 2 tabs in the 2nd last row
if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then
--move 1 tab from the second last row to the last, if there is enough space
if (rowwidths[numrows] + widths[numtabs-1]) <= width then
rowends[numrows-1] = rowends[numrows-1] - 1
rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1]
rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1]
end
end
end
end
 
--anchor the rows as defined and resize tabs to fill thier row
local starttab = 1
for row, endtab in ipairs(rowends) do
local first = true
for tabno = starttab, endtab do
local tab = tabs[tabno]
tab:ClearAllPoints()
if first then
tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -(hastitle and 14 or 7)-(row-1)*20 )
first = false
else
tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0)
end
end
 
-- equal padding for each tab to fill the available width,
-- if the used space is above 75% already
local padding = 0
if not (numrows == 1 and rowwidths[1] < width*0.75) then
padding = (width - rowwidths[row]) / (endtab - starttab+1)
end
 
for i = starttab, endtab do
PanelTemplates_TabResize(tabs[i], padding + 4, nil, width)
end
starttab = endtab + 1
end
 
self.borderoffset = (hastitle and 17 or 10)+((numrows)*20)
self.border:SetPoint("TOPLEFT", 1, -self.borderoffset)
end,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 60
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
self:BuildTabs(self)
self.frame:SetScript("OnUpdate", BuildTabsOnUpdate)
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - (self.borderoffset + 23)
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
 
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + (self.borderoffset + 23))
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
 
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame",nil,UIParent)
frame:SetHeight(100)
frame:SetWidth(100)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
 
local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
titletext:SetPoint("TOPLEFT", 14, 0)
titletext:SetPoint("TOPRIGHT", -14, 0)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
titletext:SetText("")
 
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 1, -27)
border:SetPoint("BOTTOMRIGHT", -1, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
border:SetBackdropBorderColor(0.4, 0.4, 0.4)
 
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -7)
content:SetPoint("BOTTOMRIGHT", -10, 7)
 
local widget = {
num = num,
frame = frame,
localstatus = {},
alignoffset = 18,
titletext = titletext,
border = border,
borderoffset = 27,
tabs = {},
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua New file
0,0 → 1,281
--[[-----------------------------------------------------------------------------
Slider Widget
Graphical Slider, like, for Range values.
-------------------------------------------------------------------------------]]
local Type, Version = "Slider", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local min, max, floor = math.min, math.max, math.floor
local tonumber, pairs = tonumber, pairs
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function UpdateText(self)
local value = self.value or 0
if self.ispercent then
self.editbox:SetText(("%s%%"):format(floor(value * 1000 + 0.5) / 10))
else
self.editbox:SetText(floor(value * 100 + 0.5) / 100)
end
end
 
local function UpdateLabels(self)
local min, max = (self.min or 0), (self.max or 100)
if self.ispercent then
self.lowtext:SetFormattedText("%s%%", (min * 100))
self.hightext:SetFormattedText("%s%%", (max * 100))
else
self.lowtext:SetText(min)
self.hightext:SetText(max)
end
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function Frame_OnMouseDown(frame)
frame.obj.slider:EnableMouseWheel(true)
AceGUI:ClearFocus()
end
 
local function Slider_OnValueChanged(frame)
local self = frame.obj
if not frame.setup then
local newvalue = frame:GetValue()
if newvalue ~= self.value and not self.disabled then
self.value = newvalue
self:Fire("OnValueChanged", newvalue)
end
if self.value then
UpdateText(self)
end
end
end
 
local function Slider_OnMouseUp(frame)
local self = frame.obj
self:Fire("OnMouseUp", self.value)
end
 
local function Slider_OnMouseWheel(frame, v)
local self = frame.obj
if not self.disabled then
local value = self.value
if v > 0 then
value = min(value + (self.step or 1), self.max)
else
value = max(value - (self.step or 1), self.min)
end
self.slider:SetValue(value)
end
end
 
local function EditBox_OnEscapePressed(frame)
frame:ClearFocus()
end
 
local function EditBox_OnEnterPressed(frame)
local self = frame.obj
local value = frame:GetText()
if self.ispercent then
value = value:gsub('%%', '')
value = tonumber(value) / 100
else
value = tonumber(value)
end
 
if value then
PlaySound("igMainMenuOptionCheckBoxOn")
self.slider:SetValue(value)
self:Fire("OnMouseUp", value)
end
end
 
local function EditBox_OnEnter(frame)
frame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
end
 
local function EditBox_OnLeave(frame)
frame:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(200)
self:SetHeight(44)
self:SetDisabled(false)
self:SetIsPercent(nil)
self:SetSliderValues(0,100,1)
self:SetValue(0)
self.slider:EnableMouseWheel(false)
end,
 
-- ["OnRelease"] = nil,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.slider:EnableMouse(false)
self.label:SetTextColor(.5, .5, .5)
self.hightext:SetTextColor(.5, .5, .5)
self.lowtext:SetTextColor(.5, .5, .5)
--self.valuetext:SetTextColor(.5, .5, .5)
self.editbox:SetTextColor(.5, .5, .5)
self.editbox:EnableMouse(false)
self.editbox:ClearFocus()
else
self.slider:EnableMouse(true)
self.label:SetTextColor(1, .82, 0)
self.hightext:SetTextColor(1, 1, 1)
self.lowtext:SetTextColor(1, 1, 1)
--self.valuetext:SetTextColor(1, 1, 1)
self.editbox:SetTextColor(1, 1, 1)
self.editbox:EnableMouse(true)
end
end,
 
["SetValue"] = function(self, value)
self.slider.setup = true
self.slider:SetValue(value)
self.value = value
UpdateText(self)
self.slider.setup = nil
end,
 
["GetValue"] = function(self)
return self.value
end,
 
["SetLabel"] = function(self, text)
self.label:SetText(text)
end,
 
["SetSliderValues"] = function(self, min, max, step)
local frame = self.slider
frame.setup = true
self.min = min
self.max = max
self.step = step
frame:SetMinMaxValues(min or 0,max or 100)
UpdateLabels(self)
frame:SetValueStep(step or 1)
if self.value then
frame:SetValue(self.value)
end
frame.setup = nil
end,
 
["SetIsPercent"] = function(self, value)
self.ispercent = value
UpdateLabels(self)
UpdateText(self)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local SliderBackdrop = {
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
tile = true, tileSize = 8, edgeSize = 8,
insets = { left = 3, right = 3, top = 6, bottom = 6 }
}
 
local ManualBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
tile = true, edgeSize = 1, tileSize = 5,
}
 
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
 
frame:EnableMouse(true)
frame:SetScript("OnMouseDown", Frame_OnMouseDown)
 
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("TOPLEFT")
label:SetPoint("TOPRIGHT")
label:SetJustifyH("CENTER")
label:SetHeight(15)
 
local slider = CreateFrame("Slider", nil, frame)
slider:SetOrientation("HORIZONTAL")
slider:SetHeight(15)
slider:SetHitRectInsets(0, 0, -10, 0)
slider:SetBackdrop(SliderBackdrop)
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Horizontal")
slider:SetPoint("TOP", label, "BOTTOM")
slider:SetPoint("LEFT", 3, 0)
slider:SetPoint("RIGHT", -3, 0)
slider:SetValue(0)
slider:SetScript("OnValueChanged",Slider_OnValueChanged)
slider:SetScript("OnEnter", Control_OnEnter)
slider:SetScript("OnLeave", Control_OnLeave)
slider:SetScript("OnMouseUp", Slider_OnMouseUp)
slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
 
local lowtext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
lowtext:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 2, 3)
 
local hightext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
hightext:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", -2, 3)
 
local editbox = CreateFrame("EditBox", nil, frame)
editbox:SetAutoFocus(false)
editbox:SetFontObject(GameFontHighlightSmall)
editbox:SetPoint("TOP", slider, "BOTTOM")
editbox:SetHeight(14)
editbox:SetWidth(70)
editbox:SetJustifyH("CENTER")
editbox:EnableMouse(true)
editbox:SetBackdrop(ManualBackdrop)
editbox:SetBackdropColor(0, 0, 0, 0.5)
editbox:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
editbox:SetScript("OnEnter", EditBox_OnEnter)
editbox:SetScript("OnLeave", EditBox_OnLeave)
editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
 
local widget = {
label = label,
slider = slider,
lowtext = lowtext,
hightext = hightext,
editbox = editbox,
alignoffset = 25,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
slider.obj, editbox.obj = widget, widget
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua New file
0,0 → 1,230
--[[-----------------------------------------------------------------------------
Keybinding Widget
Set Keybindings in the Config UI.
-------------------------------------------------------------------------------]]
local Type, Version = "Keybinding", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: NOT_BOUND
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
 
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function Keybinding_OnClick(frame, button)
if button == "LeftButton" or button == "RightButton" then
local self = frame.obj
if self.waitingForKey then
frame:EnableKeyboard(false)
self.msgframe:Hide()
frame:UnlockHighlight()
self.waitingForKey = nil
else
frame:EnableKeyboard(true)
self.msgframe:Show()
frame:LockHighlight()
self.waitingForKey = true
end
end
AceGUI:ClearFocus()
end
 
local ignoreKeys = {
["BUTTON1"] = true, ["BUTTON2"] = true,
["UNKNOWN"] = true,
["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
}
local function Keybinding_OnKeyDown(frame, key)
local self = frame.obj
if self.waitingForKey then
local keyPressed = key
if keyPressed == "ESCAPE" then
keyPressed = ""
else
if ignoreKeys[keyPressed] then return end
if IsShiftKeyDown() then
keyPressed = "SHIFT-"..keyPressed
end
if IsControlKeyDown() then
keyPressed = "CTRL-"..keyPressed
end
if IsAltKeyDown() then
keyPressed = "ALT-"..keyPressed
end
end
 
frame:EnableKeyboard(false)
self.msgframe:Hide()
frame:UnlockHighlight()
self.waitingForKey = nil
 
if not self.disabled then
self:SetKey(keyPressed)
self:Fire("OnKeyChanged", keyPressed)
end
end
end
 
local function Keybinding_OnMouseDown(frame, button)
if button == "LeftButton" or button == "RightButton" then
return
elseif button == "MiddleButton" then
button = "BUTTON3"
elseif button == "Button4" then
button = "BUTTON4"
elseif button == "Button5" then
button = "BUTTON5"
end
Keybinding_OnKeyDown(frame, button)
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(200)
self:SetLabel("")
self:SetKey("")
self.waitingForKey = nil
self.msgframe:Hide()
self:SetDisabled(false)
end,
 
-- ["OnRelease"] = nil,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.button:Disable()
self.label:SetTextColor(0.5,0.5,0.5)
else
self.button:Enable()
self.label:SetTextColor(1,1,1)
end
end,
 
["SetKey"] = function(self, key)
if (key or "") == "" then
self.button:SetText(NOT_BOUND)
self.button:SetNormalFontObject("GameFontNormal")
else
self.button:SetText(key)
self.button:SetNormalFontObject("GameFontHighlight")
end
end,
 
["GetKey"] = function(self)
local key = self.button:GetText()
if key == NOT_BOUND then
key = nil
end
return key
end,
 
["SetLabel"] = function(self, label)
self.label:SetText(label or "")
if (label or "") == "" then
self.alignoffset = nil
self:SetHeight(24)
else
self.alignoffset = 30
self:SetHeight(44)
end
end,
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
 
local ControlBackdrop = {
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 3, bottom = 3 }
}
 
local function keybindingMsgFixWidth(frame)
frame:SetWidth(frame.msg:GetWidth() + 10)
frame:SetScript("OnUpdate", nil)
end
 
local function Constructor()
local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)
 
local frame = CreateFrame("Frame", nil, UIParent)
local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate2")
 
button:EnableMouse(true)
button:RegisterForClicks("AnyDown")
button:SetScript("OnEnter", Control_OnEnter)
button:SetScript("OnLeave", Control_OnLeave)
button:SetScript("OnClick", Keybinding_OnClick)
button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
button:SetPoint("BOTTOMLEFT")
button:SetPoint("BOTTOMRIGHT")
button:SetHeight(24)
 
local text = button:GetFontString()
text:SetPoint("LEFT", 7, 0)
text:SetPoint("RIGHT", -7, 0)
 
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
label:SetPoint("TOPLEFT")
label:SetPoint("TOPRIGHT")
label:SetJustifyH("CENTER")
label:SetHeight(18)
 
local msgframe = CreateFrame("Frame", nil, UIParent)
msgframe:SetHeight(30)
msgframe:SetBackdrop(ControlBackdrop)
msgframe:SetBackdropColor(0,0,0)
msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
msgframe:SetFrameLevel(1000)
 
local msg = msgframe:CreateFontString(nil, "OVERLAY", "GameFontNormal")
msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel.")
msgframe.msg = msg
msg:SetPoint("TOPLEFT", 5, -5)
msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
msgframe:SetPoint("BOTTOM", button, "TOP")
msgframe:Hide()
 
local widget = {
button = button,
label = label,
msgframe = msgframe,
frame = frame,
alignoffset = 30,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
button.obj = widget
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua New file
0,0 → 1,289
--[[-----------------------------------------------------------------------------
Checkbox Widget
-------------------------------------------------------------------------------]]
local Type, Version = "CheckBox", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local select, pairs = select, pairs
 
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: SetDesaturation, GameFontHighlight
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function AlignImage(self)
local img = self.image:GetTexture()
self.text:ClearAllPoints()
if not img then
self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
self.text:SetPoint("RIGHT")
else
self.text:SetPoint("LEFT", self.image,"RIGHT", 1, 0)
self.text:SetPoint("RIGHT")
end
end
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function CheckBox_OnMouseDown(frame)
local self = frame.obj
if not self.disabled then
if self.image:GetTexture() then
self.text:SetPoint("LEFT", self.image,"RIGHT", 2, -1)
else
self.text:SetPoint("LEFT", self.checkbg, "RIGHT", 1, -1)
end
end
AceGUI:ClearFocus()
end
 
local function CheckBox_OnMouseUp(frame)
local self = frame.obj
if not self.disabled then
self:ToggleChecked()
 
if self.checked then
PlaySound("igMainMenuOptionCheckBoxOn")
else -- for both nil and false (tristate)
PlaySound("igMainMenuOptionCheckBoxOff")
end
 
self:Fire("OnValueChanged", self.checked)
AlignImage(self)
end
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetType()
self:SetValue(false)
self:SetTriState(nil)
-- height is calculated from the width and required space for the description
self:SetWidth(200)
self:SetImage()
self:SetDisabled(nil)
self:SetDescription(nil)
end,
 
-- ["OnRelease"] = nil,
 
["OnWidthSet"] = function(self, width)
if self.desc then
self.desc:SetWidth(width - 30)
if self.desc:GetText() and self.desc:GetText() ~= "" then
self:SetHeight(28 + self.desc:GetHeight())
end
end
end,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
self.text:SetTextColor(0.5, 0.5, 0.5)
SetDesaturation(self.check, true)
else
self.frame:Enable()
self.text:SetTextColor(1, 1, 1)
if self.tristate and self.checked == nil then
SetDesaturation(self.check, true)
else
SetDesaturation(self.check, false)
end
end
end,
 
["SetValue"] = function(self,value)
local check = self.check
self.checked = value
if value then
SetDesaturation(self.check, false)
self.check:Show()
else
--Nil is the unknown tristate value
if self.tristate and value == nil then
SetDesaturation(self.check, true)
self.check:Show()
else
SetDesaturation(self.check, false)
self.check:Hide()
end
end
self:SetDisabled(self.disabled)
end,
 
["GetValue"] = function(self)
return self.checked
end,
 
["SetTriState"] = function(self, enabled)
self.tristate = enabled
self:SetValue(self:GetValue())
end,
 
["SetType"] = function(self, type)
local checkbg = self.checkbg
local check = self.check
local highlight = self.highlight
 
local size
if type == "radio" then
size = 16
checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
checkbg:SetTexCoord(0, 0.25, 0, 1)
check:SetTexture("Interface\\Buttons\\UI-RadioButton")
check:SetTexCoord(0.25, 0.5, 0, 1)
check:SetBlendMode("ADD")
highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
highlight:SetTexCoord(0.5, 0.75, 0, 1)
else
size = 24
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
checkbg:SetTexCoord(0, 1, 0, 1)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:SetTexCoord(0, 1, 0, 1)
check:SetBlendMode("BLEND")
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetTexCoord(0, 1, 0, 1)
end
checkbg:SetHeight(size)
checkbg:SetWidth(size)
end,
 
["ToggleChecked"] = function(self)
local value = self:GetValue()
if self.tristate then
--cycle in true, nil, false order
if value then
self:SetValue(nil)
elseif value == nil then
self:SetValue(false)
else
self:SetValue(true)
end
else
self:SetValue(not self:GetValue())
end
end,
 
["SetLabel"] = function(self, label)
self.text:SetText(label)
end,
 
["SetDescription"] = function(self, desc)
if desc then
if not self.desc then
local desc = self.frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
desc:ClearAllPoints()
desc:SetPoint("TOPLEFT", self.checkbg, "TOPRIGHT", 5, -21)
desc:SetWidth(self.frame.width - 30)
desc:SetJustifyH("LEFT")
desc:SetJustifyV("TOP")
self.desc = desc
end
self.desc:Show()
--self.text:SetFontObject(GameFontNormal)
self.desc:SetText(desc)
self:SetHeight(28 + self.desc:GetHeight())
else
if self.desc then
self.desc:SetText("")
self.desc:Hide()
end
--self.text:SetFontObject(GameFontHighlight)
self:SetHeight(24)
end
end,
 
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
 
if image:GetTexture() then
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
end
AlignImage(self)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
 
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnMouseDown", CheckBox_OnMouseDown)
frame:SetScript("OnMouseUp", CheckBox_OnMouseUp)
 
local checkbg = frame:CreateTexture(nil, "ARTWORK")
checkbg:SetWidth(24)
checkbg:SetHeight(24)
checkbg:SetPoint("TOPLEFT")
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
 
local check = frame:CreateTexture(nil, "OVERLAY")
check:SetAllPoints(checkbg)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
 
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
text:SetJustifyH("LEFT")
text:SetHeight(18)
text:SetPoint("LEFT", checkbg, "RIGHT")
text:SetPoint("RIGHT")
 
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(checkbg)
 
local image = frame:CreateTexture(nil, "OVERLAY")
image:SetHeight(16)
image:SetWidth(16)
image:SetPoint("LEFT", checkbg, "RIGHT", 1, 0)
 
local widget = {
checkbg = checkbg,
check = check,
text = text,
highlight = highlight,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua New file
0,0 → 1,144
--[[-----------------------------------------------------------------------------
Icon Widget
-------------------------------------------------------------------------------]]
local Type, Version = "Icon", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local select, pairs, print = select, pairs, print
 
-- WoW APIs
local CreateFrame, UIParent, GetBuildInfo = CreateFrame, UIParent, GetBuildInfo
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
 
local function Button_OnClick(frame, button)
frame.obj:Fire("OnClick", button)
AceGUI:ClearFocus()
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetHeight(110)
self:SetWidth(110)
self:SetLabel()
self:SetImage(nil)
self:SetImageSize(64, 64)
self:SetDisabled(false)
end,
 
-- ["OnRelease"] = nil,
 
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:Show()
self.label:SetText(text)
self:SetHeight(self.image:GetHeight() + 25)
else
self.label:Hide()
self:SetHeight(self.image:GetHeight() + 10)
end
end,
 
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
 
if image:GetTexture() then
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
end
end,
 
["SetImageSize"] = function(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
--self.frame:SetWidth(width + 30)
if self.label:IsShown() then
self:SetHeight(height + 25)
else
self:SetHeight(height + 10)
end
end,
 
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
self.label:SetTextColor(0.5, 0.5, 0.5)
self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
else
self.frame:Enable()
self.label:SetTextColor(1, 1, 1)
self.image:SetVertexColor(1, 1, 1)
end
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
 
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnClick", Button_OnClick)
 
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
label:SetPoint("BOTTOMLEFT")
label:SetPoint("BOTTOMRIGHT")
label:SetJustifyH("CENTER")
label:SetJustifyV("TOP")
label:SetHeight(18)
 
local image = frame:CreateTexture(nil, "BACKGROUND")
image:SetWidth(64)
image:SetHeight(64)
image:SetPoint("TOP", 0, -5)
 
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetAllPoints(image)
highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
highlight:SetTexCoord(0, 1, 0.23, 0.77)
highlight:SetBlendMode("ADD")
 
local widget = {
label = label,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
-- SetText is deprecated, but keep it around for a while. (say, to WoW 4.0)
if (select(4, GetBuildInfo()) < 40000) then
widget.SetText = widget.SetLabel
else
widget.SetText = function(self, ...) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(...) end
end
 
return AceGUI:RegisterAsWidget(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua New file
0,0 → 1,133
--[[-----------------------------------------------------------------------------
BlizOptionsGroup Container
Simple container widget for the integration of AceGUI into the Blizzard Interface Options
-------------------------------------------------------------------------------]]
local Type, Version = "BlizOptionsGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
 
-- Lua APIs
local pairs = pairs
 
-- WoW APIs
local CreateFrame = CreateFrame
 
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
 
local function OnShow(frame)
frame.obj:Fire("OnShow")
end
 
local function OnHide(frame)
frame.obj:Fire("OnHide")
end
 
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
 
local function okay(frame)
frame.obj:Fire("okay")
end
 
local function cancel(frame)
frame.obj:Fire("cancel")
end
 
local function defaults(frame)
frame.obj:Fire("defaults")
end
 
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
 
local methods = {
["OnAcquire"] = function(self)
self:SetName()
self:SetTitle()
end,
 
-- ["OnRelease"] = nil,
 
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 63
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
 
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 26
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
 
["SetName"] = function(self, name, parent)
self.frame.name = name
self.frame.parent = parent
end,
 
["SetTitle"] = function(self, title)
local content = self.content
content:ClearAllPoints()
if not title or title == "" then
content:SetPoint("TOPLEFT", 10, -10)
self.label:SetText("")
else
content:SetPoint("TOPLEFT", 10, -40)
self.label:SetText(title)
end
content:SetPoint("BOTTOMRIGHT", -10, 10)
end
}
 
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame")
frame:Hide()
 
-- support functions for the Blizzard Interface Options
frame.okay = okay
frame.cancel = cancel
frame.defaults = defaults
 
frame:SetScript("OnHide", OnHide)
frame:SetScript("OnShow", OnShow)
 
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
label:SetPoint("TOPLEFT", 10, -15)
label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
 
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
 
local widget = {
label = label,
frame = frame,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
 
return AceGUI:RegisterAsContainer(widget)
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
trunk/Libs/AceGUI-3.0/AceGUI-3.0.xml New file
0,0 → 1,28
<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="AceGUI-3.0.lua"/>
<!-- Container -->
<Script file="widgets\AceGUIContainer-BlizOptionsGroup.lua"/>
<Script file="widgets\AceGUIContainer-DropDownGroup.lua"/>
<Script file="widgets\AceGUIContainer-Frame.lua"/>
<Script file="widgets\AceGUIContainer-InlineGroup.lua"/>
<Script file="widgets\AceGUIContainer-ScrollFrame.lua"/>
<Script file="widgets\AceGUIContainer-SimpleGroup.lua"/>
<Script file="widgets\AceGUIContainer-TabGroup.lua"/>
<Script file="widgets\AceGUIContainer-TreeGroup.lua"/>
<Script file="widgets\AceGUIContainer-Window.lua"/>
<!-- Widgets -->
<Script file="widgets\AceGUIWidget-Button.lua"/>
<Script file="widgets\AceGUIWidget-CheckBox.lua"/>
<Script file="widgets\AceGUIWidget-ColorPicker.lua"/>
<Script file="widgets\AceGUIWidget-DropDown.lua"/>
<Script file="widgets\AceGUIWidget-DropDown-Items.lua"/>
<Script file="widgets\AceGUIWidget-EditBox.lua"/>
<Script file="widgets\AceGUIWidget-Heading.lua"/>
<Script file="widgets\AceGUIWidget-Icon.lua"/>
<Script file="widgets\AceGUIWidget-InteractiveLabel.lua"/>
<Script file="widgets\AceGUIWidget-Keybinding.lua"/>
<Script file="widgets\AceGUIWidget-Label.lua"/>
<Script file="widgets\AceGUIWidget-MultiLineEditBox.lua"/>
<Script file="widgets\AceGUIWidget-Slider.lua"/>
</Ui>
trunk/Libs/AceGUI-3.0/AceGUI-3.0.lua New file
0,0 → 1,805
--- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs.
-- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself
-- to create any custom GUI. There are more extensive examples in the test suite in the Ace3
-- stand-alone distribution.
--
-- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly,
-- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool
-- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll
-- implement a proper API to modify it.
-- @usage
-- local AceGUI = LibStub("AceGUI-3.0")
-- -- Create a container frame
-- local f = AceGUI:Create("Frame")
-- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
-- f:SetTitle("AceGUI-3.0 Example")
-- f:SetStatusText("Status Bar")
-- f:SetLayout("Flow")
-- -- Create a button
-- local btn = AceGUI:Create("Button")
-- btn:SetWidth(170)
-- btn:SetText("Button !")
-- btn:SetCallback("OnClick", function() print("Click!") end)
-- -- Add the button to the container
-- f:AddChild(btn)
-- @class file
-- @name AceGUI-3.0
-- @release $Id: AceGUI-3.0.lua 924 2010-05-13 15:12:20Z nevcairiel $
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 33
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
 
if not AceGUI then return end -- No upgrade needed
 
-- Lua APIs
local tconcat, tremove, tinsert = table.concat, table.remove, table.insert
local select, pairs, next, type = select, pairs, next, type
local error, assert, loadstring = error, assert, loadstring
local setmetatable, rawget, rawset = setmetatable, rawget, rawset
local math_max = math.max
 
-- WoW APIs
local UIParent = UIParent
 
-- 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, LibStub
 
--local con = LibStub("AceConsole-3.0",true)
 
AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
AceGUI.WidgetBase = AceGUI.WidgetBase or {}
AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
 
-- local upvalues
local WidgetRegistry = AceGUI.WidgetRegistry
local LayoutRegistry = AceGUI.LayoutRegistry
local WidgetVersions = AceGUI.WidgetVersions
 
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
 
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
 
return dispatch
]]
 
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("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[select("#", ...)](func, ...)
end
 
-- Recycling functions
local newWidget, delWidget
do
-- Version Upgrade in Minor 29
-- Internal Storage of the objects changed, from an array table
-- to a hash table, and additionally we introduced versioning on
-- the widgets which would discard all widgets from a pre-29 version
-- anyway, so we just clear the storage now, and don't try to
-- convert the storage tables to the new format.
-- This should generally not cause *many* widgets to end up in trash,
-- since once dialogs are opened, all addons should be loaded already
-- and AceGUI should be on the latest version available on the users
-- setup.
-- -- nevcairiel - Nov 2nd, 2009
if oldminor and oldminor < 29 and AceGUI.objPools then
AceGUI.objPools = nil
end
 
AceGUI.objPools = AceGUI.objPools or {}
local objPools = AceGUI.objPools
--Returns a new instance, if none are available either returns a new table or calls the given contructor
function newWidget(type)
if not WidgetRegistry[type] then
error("Attempt to instantiate unknown widget type", 2)
end
 
if not objPools[type] then
objPools[type] = {}
end
 
local newObj = next(objPools[type])
if not newObj then
newObj = WidgetRegistry[type]()
newObj.AceGUIWidgetVersion = WidgetVersions[type]
else
objPools[type][newObj] = nil
-- if the widget is older then the latest, don't even try to reuse it
-- just forget about it, and grab a new one.
if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then
return newWidget(type)
end
end
return newObj
end
-- Releases an instance to the Pool
function delWidget(obj,type)
if not objPools[type] then
objPools[type] = {}
end
if objPools[type][obj] then
error("Attempt to Release Widget that is already released", 2)
end
objPools[type][obj] = true
end
end
 
 
-------------------
-- API Functions --
-------------------
 
-- Gets a widget Object
 
--- Create a new Widget of the given type.
-- This function will instantiate a new widget (or use one from the widget pool), and call the
-- OnAcquire function on it, before returning.
-- @param type The type of the widget.
-- @return The newly created widget.
function AceGUI:Create(type)
if WidgetRegistry[type] then
local widget = newWidget(type)
 
if rawget(widget, "Acquire") then
widget.OnAcquire = widget.Acquire
widget.Acquire = nil
elseif rawget(widget, "Aquire") then
widget.OnAcquire = widget.Aquire
widget.Aquire = nil
end
 
if rawget(widget, "Release") then
widget.OnRelease = rawget(widget, "Release")
widget.Release = nil
end
 
if widget.OnAcquire then
widget:OnAcquire()
else
error(("Widget type %s doesn't supply an OnAcquire Function"):format(type))
end
-- Set the default Layout ("List")
safecall(widget.SetLayout, widget, "List")
safecall(widget.ResumeLayout, widget)
return widget
end
end
 
--- Releases a widget Object.
-- This function calls OnRelease on the widget and places it back in the widget pool.
-- Any data on the widget is being erased, and the widget will be hidden.\\
-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
-- @param widget The widget to release
function AceGUI:Release(widget)
safecall(widget.PauseLayout, widget)
widget:Fire("OnRelease")
safecall(widget.ReleaseChildren, widget)
 
if widget.OnRelease then
widget:OnRelease()
-- else
-- error(("Widget type %s doesn't supply an OnRelease Function"):format(widget.type))
end
for k in pairs(widget.userdata) do
widget.userdata[k] = nil
end
for k in pairs(widget.events) do
widget.events[k] = nil
end
widget.width = nil
widget.relWidth = nil
widget.height = nil
widget.relHeight = nil
widget.noAutoHeight = nil
widget.frame:ClearAllPoints()
widget.frame:Hide()
widget.frame:SetParent(UIParent)
widget.frame.width = nil
widget.frame.height = nil
if widget.content then
widget.content.width = nil
widget.content.height = nil
end
delWidget(widget, widget.type)
end
 
-----------
-- Focus --
-----------
 
 
--- Called when a widget has taken focus.
-- e.g. Dropdowns opening, Editboxes gaining kb focus
-- @param widget The widget that should be focused
function AceGUI:SetFocus(widget)
if self.FocusedWidget and self.FocusedWidget ~= widget then
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
end
self.FocusedWidget = widget
end
 
 
--- Called when something has happened that could cause widgets with focus to drop it
-- e.g. titlebar of a frame being clicked
function AceGUI:ClearFocus()
if self.FocusedWidget then
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
self.FocusedWidget = nil
end
end
 
-------------
-- Widgets --
-------------
--[[
Widgets must provide the following functions
OnAcquire() - Called when the object is acquired, should set everything to a default hidden state
 
And the following members
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
type - the type of the object, same as the name given to :RegisterWidget()
 
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
It will be cleared automatically when a widget is released
Placing values directly into a widget object should be avoided
 
If the Widget can act as a container for other Widgets the following
content - frame or derivitive that children will be anchored to
 
The Widget can supply the following Optional Members
:OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data
:OnWidthSet(width) - Called when the width of the widget is changed
:OnHeightSet(height) - Called when the height of the widget is changed
Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead
AceGUI already sets a handler to the event
:LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the
area used for controls. These can be nil if the layout used the existing size to layout the controls.
 
]]
 
--------------------------
-- Widget Base Template --
--------------------------
do
local WidgetBase = AceGUI.WidgetBase
 
WidgetBase.SetParent = function(self, parent)
local frame = self.frame
frame:SetParent(nil)
frame:SetParent(parent.content)
self.parent = parent
end
 
WidgetBase.SetCallback = function(self, name, func)
if type(func) == "function" then
self.events[name] = func
end
end
 
WidgetBase.Fire = function(self, name, ...)
if self.events[name] then
local success, ret = safecall(self.events[name], self, name, ...)
if success then
return ret
end
end
end
 
WidgetBase.SetWidth = function(self, width)
self.frame:SetWidth(width)
self.frame.width = width
if self.OnWidthSet then
self:OnWidthSet(width)
end
end
 
WidgetBase.SetRelativeWidth = function(self, width)
if width <= 0 or width > 1 then
error(":SetRelativeWidth(width): Invalid relative width.", 2)
end
self.relWidth = width
self.width = "relative"
end
 
WidgetBase.SetHeight = function(self, height)
self.frame:SetHeight(height)
self.frame.height = height
if self.OnHeightSet then
self:OnHeightSet(height)
end
end
 
--[[ WidgetBase.SetRelativeHeight = function(self, height)
if height <= 0 or height > 1 then
error(":SetRelativeHeight(height): Invalid relative height.", 2)
end
self.relHeight = height
self.height = "relative"
end ]]
 
WidgetBase.IsVisible = function(self)
return self.frame:IsVisible()
end
 
WidgetBase.IsShown= function(self)
return self.frame:IsShown()
end
 
WidgetBase.Release = function(self)
AceGUI:Release(self)
end
 
WidgetBase.SetPoint = function(self, ...)
return self.frame:SetPoint(...)
end
 
WidgetBase.ClearAllPoints = function(self)
return self.frame:ClearAllPoints()
end
 
WidgetBase.GetNumPoints = function(self)
return self.frame:GetNumPoints()
end
 
WidgetBase.GetPoint = function(self, ...)
return self.frame:GetPoint(...)
end
 
WidgetBase.GetUserDataTable = function(self)
return self.userdata
end
 
WidgetBase.SetUserData = function(self, key, value)
self.userdata[key] = value
end
 
WidgetBase.GetUserData = function(self, key)
return self.userdata[key]
end
 
WidgetBase.IsFullHeight = function(self)
return self.height == "fill"
end
 
WidgetBase.SetFullHeight = function(self, isFull)
if isFull then
self.height = "fill"
else
self.height = nil
end
end
 
WidgetBase.IsFullWidth = function(self)
return self.width == "fill"
end
 
WidgetBase.SetFullWidth = function(self, isFull)
if isFull then
self.width = "fill"
else
self.width = nil
end
end
 
-- local function LayoutOnUpdate(this)
-- this:SetScript("OnUpdate",nil)
-- this.obj:PerformLayout()
-- end
 
local WidgetContainerBase = AceGUI.WidgetContainerBase
 
WidgetContainerBase.PauseLayout = function(self)
self.LayoutPaused = true
end
 
WidgetContainerBase.ResumeLayout = function(self)
self.LayoutPaused = nil
end
 
WidgetContainerBase.PerformLayout = function(self)
if self.LayoutPaused then
return
end
safecall(self.LayoutFunc, self.content, self.children)
end
 
--call this function to layout, makes sure layed out objects get a frame to get sizes etc
WidgetContainerBase.DoLayout = function(self)
self:PerformLayout()
-- if not self.parent then
-- self.frame:SetScript("OnUpdate", LayoutOnUpdate)
-- end
end
 
WidgetContainerBase.AddChild = function(self, child, beforeWidget)
if beforeWidget then
local siblingIndex = 1
for _, widget in pairs(self.children) do
if widget == beforeWidget then
break
end
siblingIndex = siblingIndex + 1
end
tinsert(self.children, siblingIndex, child)
else
tinsert(self.children, child)
end
child:SetParent(self)
child.frame:Show()
self:DoLayout()
end
 
WidgetContainerBase.AddChildren = function(self, ...)
for i = 1, select("#", ...) do
local child = select(i, ...)
tinsert(self.children, child)
child:SetParent(self)
child.frame:Show()
end
self:DoLayout()
end
 
WidgetContainerBase.ReleaseChildren = function(self)
local children = self.children
for i = 1,#children do
AceGUI:Release(children[i])
children[i] = nil
end
end
 
WidgetContainerBase.SetLayout = function(self, Layout)
self.LayoutFunc = AceGUI:GetLayout(Layout)
end
 
WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust)
if adjust then
self.noAutoHeight = nil
else
self.noAutoHeight = true
end
end
 
local function FrameResize(this)
local self = this.obj
if this:GetWidth() and this:GetHeight() then
if self.OnWidthSet then
self:OnWidthSet(this:GetWidth())
end
if self.OnHeightSet then
self:OnHeightSet(this:GetHeight())
end
end
end
 
local function ContentResize(this)
if this:GetWidth() and this:GetHeight() then
this.width = this:GetWidth()
this.height = this:GetHeight()
this.obj:DoLayout()
end
end
 
setmetatable(WidgetContainerBase, {__index=WidgetBase})
 
--One of these function should be called on each Widget Instance as part of its creation process
 
--- Register a widget-class as a container for newly created widgets.
-- @param widget The widget class
function AceGUI:RegisterAsContainer(widget)
widget.children = {}
widget.userdata = {}
widget.events = {}
widget.base = WidgetContainerBase
widget.content.obj = widget
widget.frame.obj = widget
widget.content:SetScript("OnSizeChanged", ContentResize)
widget.frame:SetScript("OnSizeChanged", FrameResize)
setmetatable(widget, {__index = WidgetContainerBase})
widget:SetLayout("List")
return widget
end
 
--- Register a widget-class as a widget.
-- @param widget The widget class
function AceGUI:RegisterAsWidget(widget)
widget.userdata = {}
widget.events = {}
widget.base = WidgetBase
widget.frame.obj = widget
widget.frame:SetScript("OnSizeChanged", FrameResize)
setmetatable(widget, {__index = WidgetBase})
return widget
end
end
 
 
 
 
------------------
-- Widget API --
------------------
 
--- Registers a widget Constructor, this function returns a new instance of the Widget
-- @param Name The name of the widget
-- @param Constructor The widget constructor function
-- @param Version The version of the widget
function AceGUI:RegisterWidgetType(Name, Constructor, Version)
assert(type(Constructor) == "function")
assert(type(Version) == "number")
 
local oldVersion = WidgetVersions[Name]
if oldVersion and oldVersion >= Version then return end
 
WidgetVersions[Name] = Version
WidgetRegistry[Name] = Constructor
end
 
--- Registers a Layout Function
-- @param Name The name of the layout
-- @param LayoutFunc Reference to the layout function
function AceGUI:RegisterLayout(Name, LayoutFunc)
assert(type(LayoutFunc) == "function")
if type(Name) == "string" then
Name = Name:upper()
end
LayoutRegistry[Name] = LayoutFunc
end
 
--- Get a Layout Function from the registry
-- @param Name The name of the layout
function AceGUI:GetLayout(Name)
if type(Name) == "string" then
Name = Name:upper()
end
return LayoutRegistry[Name]
end
 
AceGUI.counts = AceGUI.counts or {}
 
--- A type-based counter to count the number of widgets created.
-- This is used by widgets that require a named frame, e.g. when a Blizzard
-- Template requires it.
-- @param type The widget type
function AceGUI:GetNextWidgetNum(type)
if not self.counts[type] then
self.counts[type] = 0
end
self.counts[type] = self.counts[type] + 1
return self.counts[type]
end
 
--- Return the number of created widgets for this type.
-- In contrast to GetNextWidgetNum, the number is not incremented.
-- @param type The widget type
function AceGUI:GetWidgetCount(type)
return self.counts[type] or 0
end
 
--- Return the version of the currently registered widget type.
-- @param type The widget type
function AceGUI:GetWidgetVersion(type)
return WidgetVersions[type]
end
 
-------------
-- Layouts --
-------------
 
--[[
A Layout is a func that takes 2 parameters
content - the frame that widgets will be placed inside
children - a table containing the widgets to layout
]]
 
-- Very simple Layout, Children are stacked on top of each other down the left side
AceGUI:RegisterLayout("List",
function(content, children)
local height = 0
local width = content.width or content:GetWidth() or 0
for i = 1, #children do
local child = children[i]
 
local frame = child.frame
frame:ClearAllPoints()
frame:Show()
if i == 1 then
frame:SetPoint("TOPLEFT", content)
else
frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT")
end
 
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT", content)
 
if child.DoLayout then
child:DoLayout()
end
elseif child.width == "relative" then
child:SetWidth(width * child.relWidth)
 
if child.DoLayout then
child:DoLayout()
end
end
 
height = height + (frame.height or frame:GetHeight() or 0)
end
safecall(content.obj.LayoutFinished, content.obj, nil, height)
end)
 
-- A single control fills the whole content area
AceGUI:RegisterLayout("Fill",
function(content, children)
if children[1] then
children[1]:SetWidth(content:GetWidth() or 0)
children[1]:SetHeight(content:GetHeight() or 0)
children[1].frame:SetAllPoints(content)
children[1].frame:Show()
safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight())
end
end)
 
AceGUI:RegisterLayout("Flow",
function(content, children)
--used height so far
local height = 0
--width used in the current row
local usedwidth = 0
--height of the current row
local rowheight = 0
local rowoffset = 0
local lastrowoffset
 
local width = content.width or content:GetWidth() or 0
 
--control at the start of the row
local rowstart
local rowstartoffset
local lastrowstart
local isfullheight
 
local frameoffset
local lastframeoffset
local oversize
for i = 1, #children do
local child = children[i]
oversize = nil
local frame = child.frame
local frameheight = frame.height or frame:GetHeight() or 0
local framewidth = frame.width or frame:GetWidth() or 0
lastframeoffset = frameoffset
-- HACK: Why did we set a frameoffset of (frameheight / 2) ?
-- That was moving all widgets half the widgets size down, is that intended?
-- Actually, it seems to be neccessary for many cases, we'll leave it in for now.
-- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them.
-- TODO: Investigate moar!
frameoffset = child.alignoffset or (frameheight / 2)
 
if child.width == "relative" then
framewidth = width * child.relWidth
end
 
frame:Show()
frame:ClearAllPoints()
if i == 1 then
-- anchor the first control to the top left
frame:SetPoint("TOPLEFT", content)
rowheight = frameheight
rowoffset = frameoffset
rowstart = frame
rowstartoffset = frameoffset
usedwidth = framewidth
if usedwidth > width then
oversize = true
end
else
-- if there isn't available width for the control start a new row
-- if a control is "fill" it will be on a row of its own full width
if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
if isfullheight then
-- a previous row has already filled the entire height, there's nothing we can usefully do anymore
-- (maybe error/warn about this?)
break
end
--anchor the previous row, we will now know its height and offset
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
height = height + rowheight + 3
--save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
rowstart = frame
rowstartoffset = frameoffset
rowheight = frameheight
rowoffset = frameoffset
usedwidth = framewidth
if usedwidth > width then
oversize = true
end
-- put the control on the current row, adding it to the width and checking if the height needs to be increased
else
--handles cases where the new height is higher than either control because of the offsets
--math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
 
--offset is always the larger of the two offsets
rowoffset = math_max(rowoffset, frameoffset)
rowheight = math_max(rowheight, rowoffset + (frameheight / 2))
 
frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset)
usedwidth = framewidth + usedwidth
end
end
 
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT", content)
 
usedwidth = 0
rowstart = frame
rowstartoffset = frameoffset
 
if child.DoLayout then
child:DoLayout()
end
rowheight = frame.height or frame:GetHeight() or 0
rowoffset = child.alignoffset or (rowheight / 2)
rowstartoffset = rowoffset
elseif child.width == "relative" then
child:SetWidth(width * child.relWidth)
 
if child.DoLayout then
child:DoLayout()
end
elseif oversize then
if width > 1 then
frame:SetPoint("RIGHT", content)
end
end
 
if child.height == "fill" then
frame:SetPoint("BOTTOM", content)
isfullheight = true
end
end
 
--anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
if isfullheight then
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
elseif rowstart then
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
end
 
height = height + rowheight + 3
safecall(content.obj.LayoutFinished, content.obj, nil, height)
end)
trunk/Libs/AceConfig-3.0/AceConfig-3.0.xml New file
0,0 → 1,8
<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">
<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
<!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>-->
<Script file="AceConfig-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceConfig-3.0/AceConfig-3.0.lua New file
0,0 → 1,57
--- AceConfig-3.0 wrapper library.
-- Provides an API to register an options table with the config registry,
-- as well as associate it with a slash command.
-- @class file
-- @name AceConfig-3.0
-- @release $Id: AceConfig-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
 
--[[
AceConfig-3.0
 
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
 
]]
 
local MAJOR, MINOR = "AceConfig-3.0", 2
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceConfig then return end
 
local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
local cfgdlg = LibStub("AceConfigDialog-3.0")
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0")
 
-- Lua APIs
local pcall, error, type, pairs = pcall, error, type, pairs
 
-- -------------------------------------------------------------------
-- :RegisterOptionsTable(appName, options, slashcmd, persist)
--
-- - appName - (string) application name
-- - options - table or function ref, see AceConfigRegistry
-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
 
--- Register a option table with the AceConfig registry.
-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
-- @paramsig appName, options [, slashcmd]
-- @param appName The application name for the config table.
-- @param options The option table (or a function to generate one on demand)
-- @param slashcmd A slash command to register for the option table, or a table of slash commands.
-- @usage
-- local AceConfig = LibStub("AceConfig-3.0")
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
if not ok then error(msg, 2) end
 
if slashcmd then
if type(slashcmd) == "table" then
for _,cmd in pairs(slashcmd) do
cfgcmd:CreateChatCommand(cmd, appName)
end
else
cfgcmd:CreateChatCommand(slashcmd, appName)
end
end
end
trunk/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml New file
0,0 → 1,4
<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="AceConfigDialog-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua New file
0,0 → 1,1901
--- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables.
-- @class file
-- @name AceConfigDialog-3.0
-- @release $Id: AceConfigDialog-3.0.lua 958 2010-07-03 10:22:29Z nevcairiel $
 
local LibStub = LibStub
local MAJOR, MINOR = "AceConfigDialog-3.0", 49
local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceConfigDialog then return end
 
AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {}
AceConfigDialog.Status = AceConfigDialog.Status or {}
AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame")
 
AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {}
AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {}
AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {}
 
local gui = LibStub("AceGUI-3.0")
local reg = LibStub("AceConfigRegistry-3.0")
 
-- Lua APIs
local tconcat, tinsert, tsort, tremove = table.concat, table.insert, table.sort, table.remove
local strmatch, format = string.match, string.format
local assert, loadstring, error = assert, loadstring, error
local pairs, next, select, type, unpack, wipe = pairs, next, select, type, unpack, wipe
local rawset, tostring, tonumber = rawset, tostring, tonumber
local math_min, math_max, math_floor = math.min, math.max, math.floor
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: NORMAL_FONT_COLOR, GameTooltip, StaticPopupDialogs, ACCEPT, CANCEL, StaticPopup_Show
-- GLOBALS: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge
-- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler
 
local emptyTbl = {}
 
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
 
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
 
return dispatch
]]
 
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("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[select("#", ...)](func, ...)
end
 
local width_multiplier = 170
 
--[[
Group Types
Tree - All Descendant Groups will all become nodes on the tree, direct child options will appear above the tree
- Descendant Groups with inline=true and thier children will not become nodes
 
Tab - Direct Child Groups will become tabs, direct child options will appear above the tab control
- Grandchild groups will default to inline unless specified otherwise
 
Select- Same as Tab but with entries in a dropdown rather than tabs
 
 
Inline Groups
- Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border
- If declared on a direct child of a root node of a select group, they will appear above the group container control
- When a group is displayed inline, all descendants will also be inline members of the group
 
]]
 
-- Recycling functions
local new, del, copy
--newcount, delcount,createdcount,cached = 0,0,0
do
local pool = setmetatable({},{__mode="k"})
function new()
--newcount = newcount + 1
local t = next(pool)
if t then
pool[t] = nil
return t
else
--createdcount = createdcount + 1
return {}
end
end
function copy(t)
local c = new()
for k, v in pairs(t) do
c[k] = v
end
return c
end
function del(t)
--delcount = delcount + 1
for k in pairs(t) do
t[k] = nil
end
pool[t] = true
end
-- function cached()
-- local n = 0
-- for k in pairs(pool) do
-- n = n + 1
-- end
-- return n
-- end
end
 
-- picks the first non-nil value and returns it
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
 
--gets an option from a given group, checking plugins
local function GetSubOption(group, key)
if group.plugins then
for plugin, t in pairs(group.plugins) do
if t[key] then
return t[key]
end
end
end
 
return group.args[key]
end
 
--Option member type definitions, used to decide how to access it
 
--Is the member Inherited from parent options
local isInherited = {
set = true,
get = true,
func = true,
confirm = true,
validate = true,
disabled = true,
hidden = true
}
 
--Does a string type mean a literal value, instead of the default of a method of the handler
local stringIsLiteral = {
name = true,
desc = true,
icon = true,
usage = true,
width = true,
image = true,
fontSize = true,
}
 
--Is Never a function or method
local allIsLiteral = {
type = true,
descStyle = true,
imageWidth = true,
imageHeight = true,
}
 
--gets the value for a member that could be a function
--function refs are called with an info arg
--every other type is returned
local function GetOptionsMemberValue(membername, option, options, path, appName, ...)
--get definition for the member
local inherits = isInherited[membername]
 
 
--get the member of the option, traversing the tree if it can be inherited
local member
 
if inherits then
local group = options
if group[membername] ~= nil then
member = group[membername]
end
for i = 1, #path do
group = GetSubOption(group, path[i])
if group[membername] ~= nil then
member = group[membername]
end
end
else
member = option[membername]
end
 
--check if we need to call a functon, or if we have a literal value
if ( not allIsLiteral[membername] ) and ( type(member) == "function" or ((not stringIsLiteral[membername]) and type(member) == "string") ) then
--We have a function to call
local info = new()
--traverse the options table, picking up the handler and filling the info with the path
local handler
local group = options
handler = group.handler or handler
 
for i = 1, #path do
group = GetSubOption(group, path[i])
info[i] = path[i]
handler = group.handler or handler
end
 
info.options = options
info.appName = appName
info[0] = appName
info.arg = option.arg
info.handler = handler
info.option = option
info.type = option.type
info.uiType = "dialog"
info.uiName = MAJOR
 
local a, b, c ,d
--using 4 returns for the get of a color type, increase if a type needs more
if type(member) == "function" then
--Call the function
a,b,c,d = member(info, ...)
else
--Call the method
if handler and handler[member] then
a,b,c,d = handler[member](handler, info, ...)
else
error(format("Method %s doesn't exist in handler for type %s", member, membername))
end
end
del(info)
return a,b,c,d
else
--The value isnt a function to call, return it
return member
end
end
 
--[[calls an options function that could be inherited, method name or function ref
local function CallOptionsFunction(funcname ,option, options, path, appName, ...)
local info = new()
 
local func
local group = options
local handler
 
--build the info table containing the path
-- pick up functions while traversing the tree
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
 
for i, v in ipairs(path) do
group = GetSubOption(group, v)
info[i] = v
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
end
 
info.options = options
info[0] = appName
info.arg = option.arg
 
local a, b, c ,d
if type(func) == "string" then
if handler and handler[func] then
a,b,c,d = handler[func](handler, info, ...)
else
error(string.format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
a,b,c,d = func(info, ...)
end
del(info)
return a,b,c,d
end
--]]
 
--tables to hold orders and names for options being sorted, will be created with new()
--prevents needing to call functions repeatedly while sorting
local tempOrders
local tempNames
 
local function compareOptions(a,b)
if not a then
return true
end
if not b then
return false
end
local OrderA, OrderB = tempOrders[a] or 100, tempOrders[b] or 100
if OrderA == OrderB then
local NameA = (type(tempNames[a] == "string") and tempNames[a]) or ""
local NameB = (type(tempNames[b] == "string") and tempNames[b]) or ""
return NameA:upper() < NameB:upper()
end
if OrderA < 0 then
if OrderB > 0 then
return false
end
else
if OrderB < 0 then
return true
end
end
return OrderA < OrderB
end
 
 
 
--builds 2 tables out of an options group
-- keySort, sorted keys
-- opts, combined options from .plugins and args
local function BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
tempOrders = new()
tempNames = new()
 
if group.plugins then
for plugin, t in pairs(group.plugins) do
for k, v in pairs(t) do
if not opts[k] then
tinsert(keySort, k)
opts[k] = v
 
path[#path+1] = k
tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
path[#path] = nil
end
end
end
end
 
for k, v in pairs(group.args) do
if not opts[k] then
tinsert(keySort, k)
opts[k] = v
 
path[#path+1] = k
tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
path[#path] = nil
end
end
 
tsort(keySort, compareOptions)
 
del(tempOrders)
del(tempNames)
end
 
local function DelTree(tree)
if tree.children then
local childs = tree.children
for i = 1, #childs do
DelTree(childs[i])
del(childs[i])
end
del(childs)
end
end
 
local function CleanUserData(widget, event)
 
local user = widget:GetUserDataTable()
 
if user.path then
del(user.path)
end
 
if widget.type == "TreeGroup" then
local tree = user.tree
widget:SetTree(nil)
if tree then
for i = 1, #tree do
DelTree(tree[i])
del(tree[i])
end
del(tree)
end
end
 
if widget.type == "TabGroup" then
widget:SetTabs(nil)
if user.tablist then
del(user.tablist)
end
end
 
if widget.type == "DropdownGroup" then
widget:SetGroupList(nil)
if user.grouplist then
del(user.grouplist)
end
end
end
 
-- - Gets a status table for the given appname and options path.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param path The path to the options (a table with all group keys)
-- @return
function AceConfigDialog:GetStatusTable(appName, path)
local status = self.Status
 
if not status[appName] then
status[appName] = {}
status[appName].status = {}
status[appName].children = {}
end
 
status = status[appName]
 
if path then
for i = 1, #path do
local v = path[i]
if not status.children[v] then
status.children[v] = {}
status.children[v].status = {}
status.children[v].children = {}
end
status = status.children[v]
end
end
 
return status.status
end
 
--- Selects the specified path in the options window.
-- The path specified has to match the keys of the groups in the table.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param ... The path to the key that should be selected
function AceConfigDialog:SelectGroup(appName, ...)
local path = new()
 
 
local app = reg:GetOptionsTable(appName)
if not app then
error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
end
local options = app("dialog", MAJOR)
local group = options
local status = self:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
status = status.groups
local treevalue
local treestatus
 
for n = 1, select("#",...) do
local key = select(n, ...)
 
if group.childGroups == "tab" or group.childGroups == "select" then
--if this is a tab or select group, select the group
status.selected = key
--children of this group are no longer extra levels of a tree
treevalue = nil
else
--tree group by default
if treevalue then
--this is an extra level of a tree group, build a uniquevalue for it
treevalue = treevalue.."\001"..key
else
--this is the top level of a tree group, the uniquevalue is the same as the key
treevalue = key
if not status.groups then
status.groups = {}
end
--save this trees status table for any extra levels or groups
treestatus = status
end
--make sure that the tree entry is open, and select it.
--the selected group will be overwritten if a child is the final target but still needs to be open
treestatus.selected = treevalue
treestatus.groups[treevalue] = true
 
end
 
--move to the next group in the path
group = GetSubOption(group, key)
if not group then
break
end
tinsert(path, key)
status = self:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
status = status.groups
end
 
del(path)
reg:NotifyChange(appName)
end
 
local function OptionOnMouseOver(widget, event)
--show a tooltip/set the status bar to the desc text
local user = widget:GetUserDataTable()
local opt = user.option
local options = user.options
local path = user.path
local appName = user.appName
 
GameTooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT")
local name = GetOptionsMemberValue("name", opt, options, path, appName)
local desc = GetOptionsMemberValue("desc", opt, options, path, appName)
local usage = GetOptionsMemberValue("usage", opt, options, path, appName)
local descStyle = opt.descStyle
 
if descStyle and descStyle ~= "tooltip" then return end
 
GameTooltip:SetText(name, 1, .82, 0, 1)
 
if opt.type == "multiselect" then
GameTooltip:AddLine(user.text,0.5, 0.5, 0.8, 1)
end
if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, 1)
end
if type(usage) == "string" then
GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
end
 
GameTooltip:Show()
end
 
local function OptionOnMouseLeave(widget, event)
GameTooltip:Hide()
end
 
local function GetFuncName(option)
local type = option.type
if type == "execute" then
return "func"
else
return "set"
end
end
local function confirmPopup(appName, rootframe, basepath, info, message, func, ...)
if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then
StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {}
end
local t = StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"]
for k in pairs(t) do
t[k] = nil
end
t.text = message
t.button1 = ACCEPT
t.button2 = CANCEL
local dialog, oldstrata
t.OnAccept = function()
safecall(func, unpack(t))
if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata)
end
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
del(info)
end
t.OnCancel = function()
if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata)
end
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
del(info)
end
for i = 1, select("#", ...) do
t[i] = select(i, ...) or false
end
t.timeout = 0
t.whileDead = 1
t.hideOnEscape = 1
 
dialog = StaticPopup_Show("ACECONFIGDIALOG30_CONFIRM_DIALOG")
if dialog then
oldstrata = dialog:GetFrameStrata()
dialog:SetFrameStrata("TOOLTIP")
end
end
 
local function ActivateControl(widget, event, ...)
--This function will call the set / execute handler for the widget
--widget:GetUserDataTable() contains the needed info
local user = widget:GetUserDataTable()
local option = user.option
local options = user.options
local path = user.path
local info = new()
 
local func
local group = options
local funcname = GetFuncName(option)
local handler
local confirm
local validate
--build the info table containing the path
-- pick up functions while traversing the tree
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
confirm = group.confirm
validate = group.validate
for i = 1, #path do
local v = path[i]
group = GetSubOption(group, v)
info[i] = v
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
if group.confirm ~= nil then
confirm = group.confirm
end
if group.validate ~= nil then
validate = group.validate
end
end
 
info.options = options
info.appName = user.appName
info.arg = option.arg
info.handler = handler
info.option = option
info.type = option.type
info.uiType = "dialog"
info.uiName = MAJOR
 
local name
if type(option.name) == "function" then
name = option.name(info)
elseif type(option.name) == "string" then
name = option.name
else
name = ""
end
local usage = option.usage
local pattern = option.pattern
 
local validated = true
 
if option.type == "input" then
if type(pattern)=="string" then
if not strmatch(..., pattern) then
validated = false
end
end
end
 
local success
if validated and option.type ~= "execute" then
if type(validate) == "string" then
if handler and handler[validate] then
success, validated = safecall(handler[validate], handler, info, ...)
if not success then validated = false end
else
error(format("Method %s doesn't exist in handler for type execute", validate))
end
elseif type(validate) == "function" then
success, validated = safecall(validate, info, ...)
if not success then validated = false end
end
end
 
local rootframe = user.rootframe
if type(validated) == "string" then
--validate function returned a message to display
if rootframe.SetStatusText then
rootframe:SetStatusText(validated)
else
-- TODO: do something else.
end
PlaySound("igPlayerInviteDecline")
del(info)
return true
elseif not validated then
--validate returned false
if rootframe.SetStatusText then
if usage then
rootframe:SetStatusText(name..": "..usage)
else
if pattern then
rootframe:SetStatusText(name..": Expected "..pattern)
else
rootframe:SetStatusText(name..": Invalid Value")
end
end
else
-- TODO: do something else
end
PlaySound("igPlayerInviteDecline")
del(info)
return true
else
 
local confirmText = option.confirmText
--call confirm func/method
if type(confirm) == "string" then
if handler and handler[confirm] then
success, confirm = safecall(handler[confirm], handler, info, ...)
if success and type(confirm) == "string" then
confirmText = confirm
confirm = true
elseif not success then
confirm = false
end
else
error(format("Method %s doesn't exist in handler for type confirm", confirm))
end
elseif type(confirm) == "function" then
success, confirm = safecall(confirm, info, ...)
if success and type(confirm) == "string" then
confirmText = confirm
confirm = true
elseif not success then
confirm = false
end
end
 
--confirm if needed
if type(confirm) == "boolean" then
if confirm then
if not confirmText then
local name, desc = option.name, option.desc
if type(name) == "function" then
name = name(info)
end
if type(desc) == "function" then
desc = desc(info)
end
confirmText = name
if desc then
confirmText = confirmText.." - "..desc
end
end
 
local iscustom = user.rootframe:GetUserData("iscustom")
local rootframe
 
if iscustom then
rootframe = user.rootframe
end
local basepath = user.rootframe:GetUserData("basepath")
if type(func) == "string" then
if handler and handler[func] then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, ...)
else
error(format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, info, ...)
end
--func will be called and info deleted when the confirm dialog is responded to
return
end
end
 
--call the function
if type(func) == "string" then
if handler and handler[func] then
safecall(handler[func],handler, info, ...)
else
error(format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
safecall(func,info, ...)
end
 
 
 
local iscustom = user.rootframe:GetUserData("iscustom")
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
--full refresh of the frame, some controls dont cause this on all events
if option.type == "color" then
if event == "OnValueConfirmed" then
 
if iscustom then
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
else
AceConfigDialog:Open(user.appName, unpack(basepath))
end
end
elseif option.type == "range" then
if event == "OnMouseUp" then
if iscustom then
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
else
AceConfigDialog:Open(user.appName, unpack(basepath))
end
end
--multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed'
elseif option.type == "multiselect" then
user.valuechanged = true
else
if iscustom then
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
else
AceConfigDialog:Open(user.appName, unpack(basepath))
end
end
 
end
del(info)
end
 
local function ActivateSlider(widget, event, value)
local option = widget:GetUserData("option")
local min, max, step = option.min or (not option.softMin and 0 or nil), option.max or (not option.softMax and 100 or nil), option.step
if min then
if step then
value = math_floor((value - min) / step + 0.5) * step + min
end
value = math_max(value, min)
end
if max then
value = math_min(value, max)
end
ActivateControl(widget,event,value)
end
 
--called from a checkbox that is part of an internally created multiselect group
--this type is safe to refresh on activation of one control
local function ActivateMultiControl(widget, event, ...)
ActivateControl(widget, event, widget:GetUserData("value"), ...)
local user = widget:GetUserDataTable()
local iscustom = user.rootframe:GetUserData("iscustom")
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
if iscustom then
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
else
AceConfigDialog:Open(user.appName, unpack(basepath))
end
end
 
local function MultiControlOnClosed(widget, event, ...)
local user = widget:GetUserDataTable()
if user.valuechanged then
local iscustom = user.rootframe:GetUserData("iscustom")
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
if iscustom then
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
else
AceConfigDialog:Open(user.appName, unpack(basepath))
end
end
end
 
local function FrameOnClose(widget, event)
local appName = widget:GetUserData("appName")
AceConfigDialog.OpenFrames[appName] = nil
gui:Release(widget)
end
 
local function CheckOptionHidden(option, options, path, appName)
--check for a specific boolean option
local hidden = pickfirstset(option.dialogHidden,option.guiHidden)
if hidden ~= nil then
return hidden
end
 
return GetOptionsMemberValue("hidden", option, options, path, appName)
end
 
local function CheckOptionDisabled(option, options, path, appName)
--check for a specific boolean option
local disabled = pickfirstset(option.dialogDisabled,option.guiDisabled)
if disabled ~= nil then
return disabled
end
 
return GetOptionsMemberValue("disabled", option, options, path, appName)
end
--[[
local function BuildTabs(group, options, path, appName)
local tabs = new()
local text = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
tinsert(tabs, k)
text[k] = GetOptionsMemberValue("name", v, options, path, appName)
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
 
return tabs, text
end
]]
local function BuildSelect(group, options, path, appName)
local groups = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
groups[k] = GetOptionsMemberValue("name", v, options, path, appName)
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
 
return groups
end
 
local function BuildSubGroups(group, tree, options, path, appName)
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
local entry = new()
entry.value = k
entry.text = GetOptionsMemberValue("name", v, options, path, appName)
entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName)
entry.disabled = CheckOptionDisabled(v, options, path, appName)
if not tree.children then tree.children = new() end
tinsert(tree.children,entry)
if (v.childGroups or "tree") == "tree" then
BuildSubGroups(v,entry, options, path, appName)
end
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
end
 
local function BuildGroups(group, options, path, appName, recurse)
local tree = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
local entry = new()
entry.value = k
entry.text = GetOptionsMemberValue("name", v, options, path, appName)
entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
entry.disabled = CheckOptionDisabled(v, options, path, appName)
tinsert(tree,entry)
if recurse and (v.childGroups or "tree") == "tree" then
BuildSubGroups(v,entry, options, path, appName)
end
end
path[#path] = nil
end
end
del(keySort)
del(opts)
return tree
end
 
local function InjectInfo(control, options, option, path, rootframe, appName)
local user = control:GetUserDataTable()
for i = 1, #path do
user[i] = path[i]
end
user.rootframe = rootframe
user.option = option
user.options = options
user.path = copy(path)
user.appName = appName
control:SetCallback("OnRelease", CleanUserData)
control:SetCallback("OnLeave", OptionOnMouseLeave)
control:SetCallback("OnEnter", OptionOnMouseOver)
end
 
 
--[[
options - root of the options table being fed
container - widget that controls will be placed in
rootframe - Frame object the options are in
path - table with the keys to get to the group being fed
--]]
 
local function FeedOptions(appName, options,container,rootframe,path,group,inline)
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
tinsert(path, k)
local hidden = CheckOptionHidden(v, options, path, appName)
local name = GetOptionsMemberValue("name", v, options, path, appName)
if not hidden then
if v.type == "group" then
if inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
--Inline group
local GroupContainer
if name and name ~= "" then
GroupContainer = gui:Create("InlineGroup")
GroupContainer:SetTitle(name or "")
else
GroupContainer = gui:Create("SimpleGroup")
end
 
GroupContainer.width = "fill"
GroupContainer:SetLayout("flow")
container:AddChild(GroupContainer)
FeedOptions(appName,options,GroupContainer,rootframe,path,v,true)
end
else
--Control to feed
local control
 
local name = GetOptionsMemberValue("name", v, options, path, appName)
 
if v.type == "execute" then
 
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
 
if type(image) == "string" then
control = gui:Create("Icon")
if not width then
width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
end
if not height then
height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
end
if type(imageCoords) == "table" then
control:SetImage(image, unpack(imageCoords))
else
control:SetImage(image)
end
if type(width) ~= "number" then
width = 32
end
if type(height) ~= "number" then
height = 32
end
control:SetImageSize(width, height)
control:SetLabel(name)
else
control = gui:Create("Button")
control:SetText(name)
end
control:SetCallback("OnClick",ActivateControl)
 
elseif v.type == "input" then
local controlType = v.dialogControl or v.control or (v.multiline and "MultiLineEditBox") or "EditBox"
control = gui:Create(controlType)
if not control then
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
control = gui:Create(v.multiline and "MultiLineEditBox" or "EditBox")
end
 
if v.multiline and control.SetNumLines then
control:SetNumLines(tonumber(v.multiline) or 4)
end
control:SetLabel(name)
control:SetCallback("OnEnterPressed",ActivateControl)
local text = GetOptionsMemberValue("get",v, options, path, appName)
if type(text) ~= "string" then
text = ""
end
control:SetText(text)
 
elseif v.type == "toggle" then
control = gui:Create("CheckBox")
control:SetLabel(name)
control:SetTriState(v.tristate)
local value = GetOptionsMemberValue("get",v, options, path, appName)
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateControl)
 
if v.descStyle == "inline" then
local desc = GetOptionsMemberValue("desc", v, options, path, appName)
control:SetDescription(desc)
end
 
local image = GetOptionsMemberValue("image", v, options, path, appName)
local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName)
 
if type(image) == "string" then
if type(imageCoords) == "table" then
control:SetImage(image, unpack(imageCoords))
else
control:SetImage(image)
end
end
elseif v.type == "range" then
control = gui:Create("Slider")
control:SetLabel(name)
control:SetSliderValues(v.softMin or v.min or 0, v.softMax or v.max or 100, v.bigStep or v.step or 0)
control:SetIsPercent(v.isPercent)
local value = GetOptionsMemberValue("get",v, options, path, appName)
if type(value) ~= "number" then
value = 0
end
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateSlider)
control:SetCallback("OnMouseUp",ActivateSlider)
 
elseif v.type == "select" then
local values = GetOptionsMemberValue("values", v, options, path, appName)
local controlType = v.dialogControl or v.control or "Dropdown"
control = gui:Create(controlType)
if not control then
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
control = gui:Create("Dropdown")
end
control:SetLabel(name)
control:SetList(values)
local value = GetOptionsMemberValue("get",v, options, path, appName)
if not values[value] then
value = nil
end
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateControl)
 
elseif v.type == "multiselect" then
local values = GetOptionsMemberValue("values", v, options, path, appName)
local disabled = CheckOptionDisabled(v, options, path, appName)
 
local controlType = v.dialogControl or v.control
 
local valuesort = new()
if values then
for value, text in pairs(values) do
tinsert(valuesort, value)
end
end
tsort(valuesort)
 
if controlType then
control = gui:Create(controlType)
if not control then
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
end
end
if control then
control:SetMultiselect(true)
control:SetLabel(name)
control:SetList(values)
control:SetDisabled(disabled)
control:SetCallback("OnValueChanged",ActivateControl)
control:SetCallback("OnClosed", MultiControlOnClosed)
local width = GetOptionsMemberValue("width",v,options,path,appName)
if width == "double" then
control:SetWidth(width_multiplier * 2)
elseif width == "half" then
control:SetWidth(width_multiplier / 2)
elseif width == "full" then
control.width = "fill"
else
control:SetWidth(width_multiplier)
end
--check:SetTriState(v.tristate)
for i = 1, #valuesort do
local key = valuesort[i]
local value = GetOptionsMemberValue("get",v, options, path, appName, key)
control:SetItemValue(key,value)
end
else
control = gui:Create("InlineGroup")
control:SetLayout("Flow")
control:SetTitle(name)
control.width = "fill"
 
control:PauseLayout()
local width = GetOptionsMemberValue("width",v,options,path,appName)
for i = 1, #valuesort do
local value = valuesort[i]
local text = values[value]
local check = gui:Create("CheckBox")
check:SetLabel(text)
check:SetUserData("value", value)
check:SetUserData("text", text)
check:SetDisabled(disabled)
check:SetTriState(v.tristate)
check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, value))
check:SetCallback("OnValueChanged",ActivateMultiControl)
InjectInfo(check, options, v, path, rootframe, appName)
control:AddChild(check)
if width == "double" then
check:SetWidth(width_multiplier * 2)
elseif width == "half" then
check:SetWidth(width_multiplier / 2)
elseif width == "full" then
check.width = "fill"
else
check:SetWidth(width_multiplier)
end
end
control:ResumeLayout()
control:DoLayout()
 
 
end
 
del(valuesort)
 
elseif v.type == "color" then
control = gui:Create("ColorPicker")
control:SetLabel(name)
control:SetHasAlpha(v.hasAlpha)
control:SetColor(GetOptionsMemberValue("get",v, options, path, appName))
control:SetCallback("OnValueChanged",ActivateControl)
control:SetCallback("OnValueConfirmed",ActivateControl)
 
elseif v.type == "keybinding" then
control = gui:Create("Keybinding")
control:SetLabel(name)
control:SetKey(GetOptionsMemberValue("get",v, options, path, appName))
control:SetCallback("OnKeyChanged",ActivateControl)
 
elseif v.type == "header" then
control = gui:Create("Heading")
control:SetText(name)
control.width = "fill"
 
elseif v.type == "description" then
control = gui:Create("Label")
control:SetText(name)
 
local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName)
if fontSize == "medium" then
control:SetFontObject(GameFontHighlight)
elseif fontSize == "large" then
control:SetFontObject(GameFontHighlightLarge)
else -- small or invalid
control:SetFontObject(GameFontHighlightSmall)
end
 
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
 
if type(image) == "string" then
if not width then
width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
end
if not height then
height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
end
if type(imageCoords) == "table" then
control:SetImage(image, unpack(imageCoords))
else
control:SetImage(image)
end
if type(width) ~= "number" then
width = 32
end
if type(height) ~= "number" then
height = 32
end
control:SetImageSize(width, height)
end
local width = GetOptionsMemberValue("width",v,options,path,appName)
control.width = not width and "fill"
end
 
--Common Init
if control then
if control.width ~= "fill" then
local width = GetOptionsMemberValue("width",v,options,path,appName)
if width == "double" then
control:SetWidth(width_multiplier * 2)
elseif width == "half" then
control:SetWidth(width_multiplier / 2)
elseif width == "full" then
control.width = "fill"
else
control:SetWidth(width_multiplier)
end
end
if control.SetDisabled then
local disabled = CheckOptionDisabled(v, options, path, appName)
control:SetDisabled(disabled)
end
 
InjectInfo(control, options, v, path, rootframe, appName)
container:AddChild(control)
end
 
end
end
tremove(path)
end
container:ResumeLayout()
container:DoLayout()
del(keySort)
del(opts)
end
 
local function BuildPath(path, ...)
for i = 1, select("#",...) do
tinsert(path, (select(i,...)))
end
end
 
 
local function TreeOnButtonEnter(widget, event, uniquevalue, button)
local user = widget:GetUserDataTable()
if not user then return end
local options = user.options
local option = user.option
local path = user.path
local appName = user.appName
 
local feedpath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, ("\001"):split(uniquevalue))
local group = options
for i = 1, #feedpath do
if not group then return end
group = GetSubOption(group, feedpath[i])
end
 
local name = GetOptionsMemberValue("name", group, options, feedpath, appName)
local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName)
 
GameTooltip:SetOwner(button, "ANCHOR_NONE")
if widget.type == "TabGroup" then
GameTooltip:SetPoint("BOTTOM",button,"TOP")
else
GameTooltip:SetPoint("LEFT",button,"RIGHT")
end
 
GameTooltip:SetText(name, 1, .82, 0, 1)
 
if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, 1)
end
 
GameTooltip:Show()
end
 
local function TreeOnButtonLeave(widget, event, value, button)
GameTooltip:Hide()
end
 
 
local function GroupExists(appName, options, path, uniquevalue)
if not uniquevalue then return false end
 
local feedpath = new()
local temppath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, ("\001"):split(uniquevalue))
 
local group = options
for i = 1, #feedpath do
local v = feedpath[i]
temppath[i] = v
group = GetSubOption(group, v)
 
if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then
del(feedpath)
del(temppath)
return false
end
end
del(feedpath)
del(temppath)
return true
end
 
local function GroupSelected(widget, event, uniquevalue)
 
local user = widget:GetUserDataTable()
 
local options = user.options
local option = user.option
local path = user.path
local rootframe = user.rootframe
 
local feedpath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, ("\001"):split(uniquevalue))
local group = options
for i = 1, #feedpath do
group = GetSubOption(group, feedpath[i])
end
widget:ReleaseChildren()
AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath)
 
del(feedpath)
end
 
 
 
--[[
-- INTERNAL --
This function will feed one group, and any inline child groups into the given container
Select Groups will only have the selection control (tree, tabs, dropdown) fed in
and have a group selected, this event will trigger the feeding of child groups
 
Rules:
If the group is Inline, FeedOptions
If the group has no child groups, FeedOptions
 
If the group is a tab or select group, FeedOptions then add the Group Control
If the group is a tree group FeedOptions then
its parent isnt a tree group: then add the tree control containing this and all child tree groups
if its parent is a tree group, its already a node on a tree
--]]
 
function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot)
local group = options
--follow the path to get to the curent group
local inline
local grouptype, parenttype = options.childGroups, "none"
 
 
for i = 1, #path do
local v = path[i]
group = GetSubOption(group, v)
inline = inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
parenttype = grouptype
grouptype = group.childGroups
end
 
if not parenttype then
parenttype = "tree"
end
 
--check if the group has child groups
local hasChildGroups
for k, v in pairs(group.args) do
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
hasChildGroups = true
end
end
if group.plugins then
for plugin, t in pairs(group.plugins) do
for k, v in pairs(t) do
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
hasChildGroups = true
end
end
end
end
 
container:SetLayout("flow")
local scroll
 
--Add a scrollframe if we are not going to add a group control, this is the inverse of the conditions for that later on
if (not (hasChildGroups and not inline)) or (grouptype ~= "tab" and grouptype ~= "select" and (parenttype == "tree" and not isRoot)) then
if container.type ~= "InlineGroup" and container.type ~= "SimpleGroup" then
scroll = gui:Create("ScrollFrame")
scroll:SetLayout("flow")
scroll.width = "fill"
scroll.height = "fill"
container:SetLayout("fill")
container:AddChild(scroll)
container = scroll
end
end
 
FeedOptions(appName,options,container,rootframe,path,group,nil)
 
if scroll then
container:PerformLayout()
local status = self:GetStatusTable(appName, path)
if not status.scroll then
status.scroll = {}
end
scroll:SetStatusTable(status.scroll)
end
 
if hasChildGroups and not inline then
local name = GetOptionsMemberValue("name", group, options, path, appName)
if grouptype == "tab" then
 
local tab = gui:Create("TabGroup")
InjectInfo(tab, options, group, path, rootframe, appName)
tab:SetCallback("OnGroupSelected", GroupSelected)
tab:SetCallback("OnTabEnter", TreeOnButtonEnter)
tab:SetCallback("OnTabLeave", TreeOnButtonLeave)
 
local status = AceConfigDialog:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
tab:SetStatusTable(status.groups)
tab.width = "fill"
tab.height = "fill"
 
local tabs = BuildGroups(group, options, path, appName)
tab:SetTabs(tabs)
tab:SetUserData("tablist", tabs)
 
for i = 1, #tabs do
local entry = tabs[i]
if not entry.disabled then
tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
break
end
end
 
container:AddChild(tab)
 
elseif grouptype == "select" then
 
local select = gui:Create("DropdownGroup")
select:SetTitle(name)
InjectInfo(select, options, group, path, rootframe, appName)
select:SetCallback("OnGroupSelected", GroupSelected)
local status = AceConfigDialog:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
select:SetStatusTable(status.groups)
local grouplist = BuildSelect(group, options, path, appName)
select:SetGroupList(grouplist)
select:SetUserData("grouplist", grouplist)
local firstgroup
for k, v in pairs(grouplist) do
if not firstgroup or k < firstgroup then
firstgroup = k
end
end
 
if firstgroup then
select:SetGroup((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup)
end
 
select.width = "fill"
select.height = "fill"
 
container:AddChild(select)
 
--assume tree group by default
--if parenttype is tree then this group is already a node on that tree
elseif (parenttype ~= "tree") or isRoot then
local tree = gui:Create("TreeGroup")
InjectInfo(tree, options, group, path, rootframe, appName)
tree:EnableButtonTooltips(false)
 
tree.width = "fill"
tree.height = "fill"
 
tree:SetCallback("OnGroupSelected", GroupSelected)
tree:SetCallback("OnButtonEnter", TreeOnButtonEnter)
tree:SetCallback("OnButtonLeave", TreeOnButtonLeave)
 
local status = AceConfigDialog:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
local treedefinition = BuildGroups(group, options, path, appName, true)
tree:SetStatusTable(status.groups)
 
tree:SetTree(treedefinition)
tree:SetUserData("tree",treedefinition)
 
for i = 1, #treedefinition do
local entry = treedefinition[i]
if not entry.disabled then
tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
break
end
end
 
container:AddChild(tree)
end
end
end
 
local old_CloseSpecialWindows
 
 
local function RefreshOnUpdate(this)
for appName in pairs(this.closing) do
if AceConfigDialog.OpenFrames[appName] then
AceConfigDialog.OpenFrames[appName]:Hide()
end
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
if not widget:IsVisible() then
widget:ReleaseChildren()
end
end
end
this.closing[appName] = nil
end
 
if this.closeAll then
for k, v in pairs(AceConfigDialog.OpenFrames) do
if not this.closeAllOverride[k] then
v:Hide()
end
end
this.closeAll = nil
wipe(this.closeAllOverride)
end
 
for appName in pairs(this.apps) do
if AceConfigDialog.OpenFrames[appName] then
local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable()
AceConfigDialog:Open(appName, unpack(user.basepath or emptyTbl))
end
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
local user = widget:GetUserDataTable()
if widget:IsVisible() then
AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(user.basepath or emptyTbl))
end
end
end
this.apps[appName] = nil
end
this:SetScript("OnUpdate", nil)
end
 
-- Upgrade the OnUpdate script as well, if needed.
if AceConfigDialog.frame:GetScript("OnUpdate") then
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
end
 
--- Close all open options windows
function AceConfigDialog:CloseAll()
AceConfigDialog.frame.closeAll = true
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
if next(self.OpenFrames) then
return true
end
end
 
--- Close a specific options window.
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigDialog:Close(appName)
if self.OpenFrames[appName] then
AceConfigDialog.frame.closing[appName] = true
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
return true
end
end
 
-- Internal -- Called by AceConfigRegistry
function AceConfigDialog:ConfigTableChanged(event, appName)
AceConfigDialog.frame.apps[appName] = true
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
end
 
reg.RegisterCallback(AceConfigDialog, "ConfigTableChange", "ConfigTableChanged")
 
--- Sets the default size of the options window for a specific application.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param width The default width
-- @param height The default height
function AceConfigDialog:SetDefaultSize(appName, width, height)
local status = AceConfigDialog:GetStatusTable(appName)
if type(width) == "number" and type(height) == "number" then
status.width = width
status.height = height
end
end
 
--- Open an option window at the specified path (if any).
-- This function can optionally feed the group into a pre-created container
-- instead of creating a new container frame.
-- @paramsig appName [, container][, ...]
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param container An optional container frame to feed the options into
-- @param ... The path to open after creating the options window (see `:SelectGroup` for details)
function AceConfigDialog:Open(appName, container, ...)
if not old_CloseSpecialWindows then
old_CloseSpecialWindows = CloseSpecialWindows
CloseSpecialWindows = function()
local found = old_CloseSpecialWindows()
return self:CloseAll() or found
end
end
local app = reg:GetOptionsTable(appName)
if not app then
error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
end
local options = app("dialog", MAJOR)
 
local f
 
local path = new()
local name = GetOptionsMemberValue("name", options, options, path, appName)
 
--If an optional path is specified add it to the path table before feeding the options
--as container is optional as well it may contain the first element of the path
if type(container) == "string" then
tinsert(path, container)
container = nil
end
for n = 1, select("#",...) do
tinsert(path, (select(n, ...)))
end
 
--if a container is given feed into that
if container then
f = container
f:ReleaseChildren()
f:SetUserData("appName", appName)
f:SetUserData("iscustom", true)
if #path > 0 then
f:SetUserData("basepath", copy(path))
end
local status = AceConfigDialog:GetStatusTable(appName)
if not status.width then
status.width = 700
end
if not status.height then
status.height = 500
end
if f.SetStatusTable then
f:SetStatusTable(status)
end
if f.SetTitle then
f:SetTitle(name or "")
end
else
if not self.OpenFrames[appName] then
f = gui:Create("Frame")
self.OpenFrames[appName] = f
else
f = self.OpenFrames[appName]
end
f:ReleaseChildren()
f:SetCallback("OnClose", FrameOnClose)
f:SetUserData("appName", appName)
if #path > 0 then
f:SetUserData("basepath", copy(path))
end
f:SetTitle(name or "")
local status = AceConfigDialog:GetStatusTable(appName)
f:SetStatusTable(status)
end
 
self:FeedGroup(appName,options,f,f,path,true)
if f.Show then
f:Show()
end
del(path)
 
if AceConfigDialog.frame.closeAll then
-- close all is set, but thats not good, since we're just opening here, so force it
AceConfigDialog.frame.closeAllOverride[appName] = true
end
end
 
-- convert pre-39 BlizOptions structure to the new format
if oldminor and oldminor < 39 and AceConfigDialog.BlizOptions then
local old = AceConfigDialog.BlizOptions
local new = {}
for key, widget in pairs(old) do
local appName = widget:GetUserData("appName")
if not new[appName] then new[appName] = {} end
new[appName][key] = widget
end
AceConfigDialog.BlizOptions = new
else
AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {}
end
 
local function FeedToBlizPanel(widget, event)
local path = widget:GetUserData("path")
AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(path or emptyTbl))
end
 
local function ClearBlizPanel(widget, event)
local appName = widget:GetUserData("appName")
AceConfigDialog.frame.closing[appName] = true
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
end
 
--- Add an option table into the Blizzard Interface Options panel.
-- You can optionally supply a descriptive name to use and a parent frame to use,
-- as well as a path in the options table.\\
-- If no name is specified, the appName will be used instead.
--
-- If you specify a proper `parent` (by name), the interface options will generate a
-- tree layout. Note that only one level of children is supported, so the parent always
-- has to be a head-level note.
--
-- This function returns a reference to the container frame registered with the Interface
-- Options. You can use this reference to open the options with the API function
-- `InterfaceOptionsFrame_OpenToCategory`.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param name A descriptive name to display in the options tree (defaults to appName)
-- @param parent The parent to use in the interface options tree.
-- @param ... The path in the options table to feed into the interface options panel.
-- @return The reference to the frame registered into the Interface Options.
function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...)
local BlizOptions = AceConfigDialog.BlizOptions
 
local key = appName
for n = 1, select("#", ...) do
key = key.."\001"..select(n, ...)
end
 
if not BlizOptions[appName] then
BlizOptions[appName] = {}
end
 
if not BlizOptions[appName][key] then
local group = gui:Create("BlizOptionsGroup")
BlizOptions[appName][key] = group
group:SetName(name or appName, parent)
 
group:SetTitle(name or appName)
group:SetUserData("appName", appName)
if select("#", ...) > 0 then
local path = {}
for n = 1, select("#",...) do
tinsert(path, (select(n, ...)))
end
group:SetUserData("path", path)
end
group:SetCallback("OnShow", FeedToBlizPanel)
group:SetCallback("OnHide", ClearBlizPanel)
InterfaceOptions_AddCategory(group.frame)
return group.frame
else
error(("%s has already been added to the Blizzard Options Window with the given path"):format(appName), 2)
end
end
trunk/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml New file
0,0 → 1,4
<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="AceConfigCmd-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua New file
0,0 → 1,787
--- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
-- @class file
-- @name AceConfigCmd-3.0
-- @release $Id: AceConfigCmd-3.0.lua 904 2009-12-13 11:56:37Z nevcairiel $
 
--[[
AceConfigCmd-3.0
 
Handles commandline optionstable access
 
REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
 
]]
 
-- TODO: plugin args
 
 
local MAJOR, MINOR = "AceConfigCmd-3.0", 12
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceConfigCmd then return end
 
AceConfigCmd.commands = AceConfigCmd.commands or {}
local commands = AceConfigCmd.commands
 
local cfgreg = LibStub("AceConfigRegistry-3.0")
local AceConsole -- LoD
local AceConsoleName = "AceConsole-3.0"
 
-- Lua APIs
local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim
local format, tonumber, tostring = string.format, tonumber, tostring
local tsort, tinsert = table.sort, table.insert
local select, pairs, next, type = select, pairs, next, type
local error, assert = error, assert
 
-- WoW APIs
local _G = _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, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME
 
 
local L = setmetatable({}, { -- TODO: replace with proper locale
__index = function(self,k) return k end
})
 
 
 
local function print(msg)
(SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
end
 
-- constants used by getparam() calls below
 
local handlertypes = {["table"]=true}
local handlermsg = "expected a table"
 
local functypes = {["function"]=true, ["string"]=true}
local funcmsg = "expected function or member name"
 
 
-- pickfirstset() - picks the first non-nil value and returns it
 
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
 
 
-- err() - produce real error() regarding malformed options tables etc
 
local function err(info,inputpos,msg )
local cmdstr=" "..strsub(info.input, 1, inputpos-1)
error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
end
 
 
-- usererr() - produce chatframe message regarding bad slash syntax etc
 
local function usererr(info,inputpos,msg )
local cmdstr=strsub(info.input, 1, inputpos-1);
print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
end
 
 
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
 
local function callmethod(info, inputpos, tab, methodtype, ...)
local method = info[methodtype]
if not method then
err(info, inputpos, "'"..methodtype.."': not set")
end
 
info.arg = tab.arg
info.option = tab
info.type = tab.type
 
if type(method)=="function" then
return method(info, ...)
elseif type(method)=="string" then
if type(info.handler[method])~="function" then
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
end
return info.handler[method](info.handler, info, ...)
else
assert(false) -- type should have already been checked on read
end
end
 
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
 
local function callfunction(info, tab, methodtype, ...)
local method = tab[methodtype]
 
info.arg = tab.arg
info.option = tab
info.type = tab.type
 
if type(method)=="function" then
return method(info, ...)
else
assert(false) -- type should have already been checked on read
end
end
 
-- do_final() - do the final step (set/execute) along with validation and confirmation
 
local function do_final(info, inputpos, tab, methodtype, ...)
if info.validate then
local res = callmethod(info,inputpos,tab,"validate",...)
if type(res)=="string" then
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
return
end
end
-- console ignores .confirm
 
callmethod(info,inputpos,tab,methodtype, ...)
end
 
 
-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
 
local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
local old,oldat = info[paramname], info[paramname.."_at"]
local val=tab[paramname]
if val~=nil then
if val==false then
val=nil
elseif not types[type(val)] then
err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
end
info[paramname] = val
info[paramname.."_at"] = depth
end
return old,oldat
end
 
 
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
local dummytable={}
 
local function iterateargs(tab)
if not tab.plugins then
return pairs(tab.args)
end
 
local argtabkey,argtab=next(tab.plugins)
local v
 
return function(_, k)
while argtab do
k,v = next(argtab, k)
if k then return k,v end
if argtab==tab.args then
argtab=nil
else
argtabkey,argtab = next(tab.plugins, argtabkey)
if not argtabkey then
argtab=tab.args
end
end
end
end
end
 
local function checkhidden(info, inputpos, tab)
if tab.cmdHidden~=nil then
return tab.cmdHidden
end
local hidden = tab.hidden
if type(hidden) == "function" or type(hidden) == "string" then
info.hidden = hidden
hidden = callmethod(info, inputpos, tab, 'hidden')
info.hidden = nil
end
return hidden
end
 
local function showhelp(info, inputpos, tab, depth, noHead)
if not noHead then
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
end
 
local sortTbl = {} -- [1..n]=name
local refTbl = {} -- [name]=tableref
 
for k,v in iterateargs(tab) do
if not refTbl[k] then -- a plugin overriding something in .args
tinsert(sortTbl, k)
refTbl[k] = v
end
end
 
tsort(sortTbl, function(one, two)
local o1 = refTbl[one].order or 100
local o2 = refTbl[two].order or 100
if type(o1) == "function" or type(o1) == "string" then
info.order = o1
info[#info+1] = one
o1 = callmethod(info, inputpos, refTbl[one], "order")
info[#info] = nil
info.order = nil
end
if type(o2) == "function" or type(o1) == "string" then
info.order = o2
info[#info+1] = two
o2 = callmethod(info, inputpos, refTbl[two], "order")
info[#info] = nil
info.order = nil
end
if o1<0 and o2<0 then return o1<o2 end
if o2<0 then return true end
if o1<0 then return false end
if o1==o2 then return tostring(one)<tostring(two) end -- compare names
return o1<o2
end)
 
for i = 1, #sortTbl do
local k = sortTbl[i]
local v = refTbl[k]
if not checkhidden(info, inputpos, v) then
if v.type ~= "description" and v.type ~= "header" then
-- recursively show all inline groups
local name, desc = v.name, v.desc
if type(name) == "function" then
name = callfunction(info, v, 'name')
end
if type(desc) == "function" then
desc = callfunction(info, v, 'desc')
end
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
print(" "..(desc or name)..":")
local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg)
showhelp(info, inputpos, v, depth, true)
info.handler,info.handler_at = oldhandler,oldhandler_at
else
local key = k:gsub(" ", "_")
print(" |cffffff78"..key.."|r - "..(desc or name or ""))
end
end
end
end
end
 
 
local function keybindingValidateFunc(text)
if text == nil or text == "NONE" then
return nil
end
text = text:upper()
local shift, ctrl, alt
local modifier
while true do
if text == "-" then
break
end
modifier, text = strsplit('-', text, 2)
if text then
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then
return false
end
if modifier == "SHIFT" then
if shift then
return false
end
shift = true
end
if modifier == "CTRL" then
if ctrl then
return false
end
ctrl = true
end
if modifier == "ALT" then
if alt then
return false
end
alt = true
end
else
text = modifier
break
end
end
if text == "" then
return false
end
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then
return false
end
local s = text
if shift then
s = "SHIFT-" .. s
end
if ctrl then
s = "CTRL-" .. s
end
if alt then
s = "ALT-" .. s
end
return s
end
 
-- handle() - selfrecursing function that processes input->optiontable
-- - depth - starts at 0
-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
 
local function handle(info, inputpos, tab, depth, retfalse)
 
if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
 
-------------------------------------------------------------------
-- Grab hold of handler,set,get,func,etc if set (and remember old ones)
-- Note that we do NOT validate if method names are correct at this stage,
-- the handler may change before they're actually used!
 
local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
 
-------------------------------------------------------------------
-- Act according to .type of this table
 
if tab.type=="group" then
------------ group --------------------------------------------
 
if type(tab.args)~="table" then err(info, inputpos) end
if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
 
-- grab next arg from input
local _,nextpos,arg = (info.input):find(" *([^ ]+) *", inputpos)
if not arg then
showhelp(info, inputpos, tab, depth)
return
end
nextpos=nextpos+1
 
-- loop .args and try to find a key with a matching name
for k,v in iterateargs(tab) do
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
 
-- is this child an inline group? if so, traverse into it
if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
info[depth+1] = k
if handle(info, inputpos, v, depth+1, true)==false then
info[depth+1] = nil
-- wasn't found in there, but that's ok, we just keep looking down here
else
return -- done, name was found in inline group
end
-- matching name and not a inline group
elseif strlower(arg)==strlower(k:gsub(" ", "_")) then
info[depth+1] = k
return handle(info,nextpos,v,depth+1)
end
end
 
-- no match
if retfalse then
-- restore old infotable members and return false to indicate failure
info.handler,info.handler_at = oldhandler,oldhandler_at
info.set,info.set_at = oldset,oldset_at
info.get,info.get_at = oldget,oldget_at
info.func,info.func_at = oldfunc,oldfunc_at
info.validate,info.validate_at = oldvalidate,oldvalidate_at
--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
return false
end
 
-- couldn't find the command, display error
usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
return
end
 
local str = strsub(info.input,inputpos);
 
if tab.type=="execute" then
------------ execute --------------------------------------------
do_final(info, inputpos, tab, "func")
 
 
 
elseif tab.type=="input" then
------------ input --------------------------------------------
 
local res = true
if tab.pattern then
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
if not strmatch(str, tab.pattern) then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return
end
end
 
do_final(info, inputpos, tab, "set", str)
 
 
 
elseif tab.type=="toggle" then
------------ toggle --------------------------------------------
local b
local str = strtrim(strlower(str))
if str=="" then
b = callmethod(info, inputpos, tab, "get")
 
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
 
elseif str==L["on"] then
b = true
elseif str==L["off"] then
b = false
elseif tab.tristate and str==L["default"] then
b = nil
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
else
usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
end
return
end
 
do_final(info, inputpos, tab, "set", b)
 
 
elseif tab.type=="range" then
------------ range --------------------------------------------
local val = tonumber(str)
if not val then
usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
return
end
if type(info.step)=="number" then
val = val- (val % info.step)
end
if type(info.min)=="number" and val<info.min then
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
return
end
if type(info.max)=="number" and val>info.max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
return
end
 
do_final(info, inputpos, tab, "set", val)
 
 
elseif tab.type=="select" then
------------ select ------------------------------------
local str = strtrim(strlower(str))
 
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
 
if str == "" then
local b = callmethod(info, inputpos, tab, "get")
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r:"])
for k, v in pairs(values) do
if b == k then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
 
local ok
for k,v in pairs(values) do
if strlower(k)==str then
str = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
return
end
 
do_final(info, inputpos, tab, "set", str)
 
elseif tab.type=="multiselect" then
------------ multiselect -------------------------------------------
local str = strtrim(strlower(str))
 
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
 
if str == "" then
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r (multiple possible):"])
for k, v in pairs(values) do
if callmethod(info, inputpos, tab, "get", k) then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
 
--build a table of the selections, checking that they exist
--parse for =on =off =default in the process
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set
local sels = {}
for v in str:gmatch("[^ ]+") do
--parse option=on etc
local opt, val = v:match('(.+)=(.+)')
--get option if toggling
if not opt then
opt = v
end
 
--check that the opt is valid
local ok
for k,v in pairs(values) do
if strlower(k)==opt then
opt = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
 
if not ok then
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
return
end
 
--check that if val was supplied it is valid
if val then
if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
--val is valid insert it
sels[opt] = val
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
else
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
end
return
end
else
-- no val supplied, toggle
sels[opt] = true
end
end
 
for opt, val in pairs(sels) do
local newval
 
if (val == true) then
--toggle the option
local b = callmethod(info, inputpos, tab, "get", opt)
 
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
newval = b
else
--set the option as specified
if val==L["on"] then
newval = true
elseif val==L["off"] then
newval = false
elseif val==L["default"] then
newval = nil
end
end
 
do_final(info, inputpos, tab, "set", opt, newval)
end
 
 
elseif tab.type=="color" then
------------ color --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
 
local r, g, b, a
 
if tab.hasAlpha then
if str:len() == 8 and str:find("^%x*$") then
--parse a hex string
r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255
else
--parse seperate values
r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
end
if not (r and g and b and a) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
return
end
 
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
a = a / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
end
else
a = 1.0
if str:len() == 6 and str:find("^%x*$") then
--parse a hex string
r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255
else
--parse seperate values
r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b = tonumber(r), tonumber(g), tonumber(b)
end
if not (r and g and b) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
end
end
 
do_final(info, inputpos, tab, "set", r,g,b,a)
 
elseif tab.type=="keybinding" then
------------ keybinding --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local value = keybindingValidateFunc(str:upper())
if value == false then
usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
return
end
 
do_final(info, inputpos, tab, "set", value)
 
elseif tab.type=="description" then
------------ description --------------------
-- ignore description, GUI config only
else
err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
end
end
 
--- Handle the chat command.
-- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\
-- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand`
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param input The commandline input (as given by the WoW handler, i.e. without the command itself)
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
-- -- Use AceConsole-3.0 to register a Chat Command
-- MyAddon:RegisterChatCommand("mychat", "ChatCommand")
--
-- -- Show the GUI if no input is supplied, otherwise handle the chat input.
-- function MyAddon:ChatCommand(input)
-- -- Assuming "MyOptions" is the appName of a valid options table
-- if not input or input:trim() == "" then
-- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
-- else
-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
-- end
-- end
function AceConfigCmd:HandleCommand(slashcmd, appName, input)
 
local optgetter = cfgreg:GetOptionsTable(appName)
if not optgetter then
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
end
local options = assert( optgetter("cmd", MAJOR) )
 
local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
[0] = slashcmd,
appName = appName,
options = options,
input = input,
self = self,
handler = self,
uiType = "cmd",
uiName = MAJOR,
}
 
handle(info, 1, options, 0) -- (info, inputpos, table, depth)
end
 
--- Utility function to create a slash command handler.
-- Also registers tab completion with AceTab
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigCmd:CreateChatCommand(slashcmd, appName)
if not AceConsole then
AceConsole = LibStub(AceConsoleName)
end
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
end,
true) then -- succesfully registered so lets get the command -> app table in
commands[slashcmd] = appName
end
end
 
--- Utility function that returns the options table that belongs to a slashcommand.
-- Designed to be used for the AceTab interface.
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @return The options table associated with the slash command (or nil if the slash command was not registered)
function AceConfigCmd:GetChatCommandOptions(slashcmd)
return commands[slashcmd]
end
trunk/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml New file
0,0 → 1,4
<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="AceConfigRegistry-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua New file
0,0 → 1,346
--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
-- * The **appName** field is the options table name as given at registration time \\
--
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
-- @class file
-- @name AceConfigRegistry-3.0
-- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceConfigRegistry then return end
 
AceConfigRegistry.tables = AceConfigRegistry.tables or {}
 
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
 
if not AceConfigRegistry.callbacks then
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
end
 
-- Lua APIs
local tinsert, tconcat = table.insert, table.concat
local strfind, strmatch = string.find, string.match
local type, tostring, select, pairs = type, tostring, select, pairs
local error, assert = error, assert
 
-----------------------------------------------------------------------
-- Validating options table consistency:
 
 
AceConfigRegistry.validated = {
-- list of options table names ran through :ValidateOptionsTable automatically.
-- CLEARED ON PURPOSE, since newer versions may have newer validators
cmd = {},
dropdown = {},
dialog = {},
}
 
 
 
local function err(msg, errlvl, ...)
local t = {}
for i=select("#",...),1,-1 do
tinsert(t, (select(i, ...)))
end
error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
end
 
 
local isstring={["string"]=true, _="string"}
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
local istable={["table"]=true, _="table"}
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
local optstring={["nil"]=true,["string"]=true, _="string"}
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
local optnumber={["nil"]=true,["number"]=true, _="number"}
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
local opttable={["nil"]=true,["table"]=true, _="table"}
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
 
local basekeys={
type=isstring,
name=isstringfunc,
desc=optstringfunc,
descStyle=optstring,
order=optmethodnumber,
validate=optmethodfalse,
confirm=optmethodbool,
confirmText=optstring,
disabled=optmethodbool,
hidden=optmethodbool,
guiHidden=optmethodbool,
dialogHidden=optmethodbool,
dropdownHidden=optmethodbool,
cmdHidden=optmethodbool,
icon=optstringfunc,
iconCoords=optmethodtable,
handler=opttable,
get=optmethodfalse,
set=optmethodfalse,
func=optmethodfalse,
arg={["*"]=true},
width=optstring,
}
 
local typedkeys={
header={},
description={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
fontSize=optstringfunc,
},
group={
args=istable,
plugins=opttable,
inline=optbool,
cmdInline=optbool,
guiInline=optbool,
dropdownInline=optbool,
dialogInline=optbool,
childGroups=optstring,
},
execute={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
},
input={
pattern=optstring,
usage=optstring,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
multiline=optboolnumber,
},
toggle={
tristate=optbool,
image=optstringfunc,
imageCoords=optmethodtable,
},
tristate={
},
range={
min=optnumber,
softMin=optnumber,
max=optnumber,
softMax=optnumber,
step=optnumber,
bigStep=optnumber,
isPercent=optbool,
},
select={
values=ismethodtable,
style={
["nil"]=true,
["string"]={dropdown=true,radio=true},
_="string: 'dropdown' or 'radio'"
},
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
multiselect={
values=ismethodtable,
style=optstring,
tristate=optbool,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
color={
hasAlpha=optbool,
},
keybinding={
-- TODO
},
}
 
local function validateKey(k,errlvl,...)
errlvl=(errlvl or 0)+1
if type(k)~="string" then
err("["..tostring(k).."] - key is not a string", errlvl,...)
end
if strfind(k, "[%c\127]") then
err("["..tostring(k).."] - key name contained control characters", errlvl,...)
end
end
 
local function validateVal(v, oktypes, errlvl,...)
errlvl=(errlvl or 0)+1
local isok=oktypes[type(v)] or oktypes["*"]
 
if not isok then
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
end
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
if not isok[v] then
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
end
end
end
 
local function validate(options,errlvl,...)
errlvl=(errlvl or 0)+1
-- basic consistency
if type(options)~="table" then
err(": expected a table, got a "..type(options), errlvl,...)
end
if type(options.type)~="string" then
err(".type: expected a string, got a "..type(options.type), errlvl,...)
end
 
-- get type and 'typedkeys' member
local tk = typedkeys[options.type]
if not tk then
err(".type: unknown type '"..options.type.."'", errlvl,...)
end
 
-- make sure that all options[] are known parameters
for k,v in pairs(options) do
if not (tk[k] or basekeys[k]) then
err(": unknown parameter", errlvl,tostring(k),...)
end
end
 
-- verify that required params are there, and that everything is the right type
for k,oktypes in pairs(basekeys) do
validateVal(options[k], oktypes, errlvl,k,...)
end
for k,oktypes in pairs(tk) do
validateVal(options[k], oktypes, errlvl,k,...)
end
 
-- extra logic for groups
if options.type=="group" then
for k,v in pairs(options.args) do
validateKey(k,errlvl,"args",...)
validate(v, errlvl,k,"args",...)
end
if options.plugins then
for plugname,plugin in pairs(options.plugins) do
if type(plugin)~="table" then
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
end
for k,v in pairs(plugin) do
validateKey(k,errlvl,tostring(plugname),"plugins",...)
validate(v, errlvl,k,tostring(plugname),"plugins",...)
end
end
end
end
end
 
 
--- Validates basic structure and integrity of an options table \\
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
-- @param options The table to be validated
-- @param name The name of the table to be validated (shown in any error message)
-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
errlvl=(errlvl or 0)+1
name = name or "Optionstable"
if not options.name then
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
end
validate(options,errlvl,name)
end
 
--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
-- You should call this function if your options table changed from any outside event, like a game event
-- or a timer.
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigRegistry:NotifyChange(appName)
if not AceConfigRegistry.tables[appName] then return end
AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
end
 
-- -------------------------------------------------------------------
-- Registering and retreiving options tables:
 
 
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
 
local function validateGetterArgs(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+2
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
end
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
end
end
 
--- Register an options table with the config registry.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param options The options table, OR a function reference that generates it on demand. \\
-- See the top of the page for info on arguments passed to such functions.
function AceConfigRegistry:RegisterOptionsTable(appName, options)
if type(options)=="table" then
if options.type~="group" then -- quick sanity checker
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
end
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return options
end
elseif type(options)=="function" then
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
local tab = assert(options(uiType, uiName, appName))
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return tab
end
else
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
end
end
 
--- Returns an iterator of ["appName"]=funcref pairs
function AceConfigRegistry:IterateOptionsTables()
return pairs(AceConfigRegistry.tables)
end
 
 
 
 
--- Query the registry for a specific options table.
-- If only appName is given, a function is returned which you
-- can call with (uiType,uiName) to get the table.\\
-- If uiType&uiName are given, the table is returned.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
local f = AceConfigRegistry.tables[appName]
if not f then
return nil
end
 
if uiType then
return f(uiType,uiName,1) -- get the table for us
else
return f -- return the function
end
end
trunk/Libs/AceDB-3.0/AceDB-3.0.xml New file
0,0 → 1,4
<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="AceDB-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceDB-3.0/AceDB-3.0.lua New file
0,0 → 1,728
--- **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.
-- * **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 940 2010-06-19 08:01:47Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 21
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
 
if not AceDB then return end -- No upgrade needed
 
-- Lua APIs
local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
 
-- WoW APIs
local _G = _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 = {}
 
--[[-------------------------------------------------------------------------
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
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
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
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
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
local new = initSection(t, section, "profiles", key, defaults)
if new then
-- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", 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")
local factionrealmKey = factionKey .. " - " .. realmKey
-- 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"] = factionrealmKey,
["profile"] = profileKey,
["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(frame, event)
if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", 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", 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", 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
 
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", 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", 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", self)
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", self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", 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
trunk/Libs/LibSimpleTimer-1.0/LibSimpleTimer-1.0.lua New file
0,0 → 1,276
--[[----------------------------------------------------------------------------
Name: LibSimpleTimer-1.0.lua
Description: A simple timer
Revision: $Revision: 32 $
Author: Whitetooth
Email: hotdogee [at] gmail [dot] com
Credits: Dongle Development Team
Encoding: UTF-8
Features:
* Schedule/Cancel one-time or repeating timer by id.
* Able to schedule a timer without any callback. Why? Used with :IsTimerScheduled(id) for checks
* Able to overwrite existing timer.
* Fast OnUpdate utilizing a heap.
* Embedable.
------------------------------------------------------------------------------]]
 
local MAJOR_VERSION = "LibSimpleTimer-1.0"
local MINOR_VERSION = 90000 + tonumber(("$Revision: 32 $"):match("%d+"))
local SimpleTimer, oldMinor = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
 
if not SimpleTimer then return end -- No upgrade needed
 
--------------------------------------------------------------------------------
-- Base code taken from Dongle, sightly modified
--------------------------------------------------------------------------------
 
SimpleTimer.timers = SimpleTimer.timers or {}
SimpleTimer.heap = SimpleTimer.heap or {}
SimpleTimer.frame = SimpleTimer.frame or CreateFrame("Frame", "SimpleTimer10Frame")
 
local timers = SimpleTimer.timers
local heap = SimpleTimer.heap
local frame = SimpleTimer.frame
 
local GetTime = GetTime
local pairs = pairs
local unpack = unpack
local floor = floor
local select = select
local type = type
local error = error
local strjoin = strjoin
local debugstack = debugstack
local strmatch = strmatch
local format = format
local pcall = pcall
local geterrorhandler = geterrorhandler
 
local function argcheck(value, num, ...)
if type(num) ~= "number" then
error(("bad argument #%d to '%s' (%s expected, got %s)"):format(2, "argcheck", "number", type(num)), 1)
end
 
for i=1,select("#", ...) do
if type(value) == select(i, ...) then return end
end
 
local types = strjoin(", ", ...)
local name = strmatch(debugstack(2,2,0), ": in function [`<](.-)['>]")
error(("bad argument #%d to '%s' (%s expected, got %s)"):format(num, name, types, type(value)), 3)
end
 
local function safecall(func,...)
local success,err = pcall(func,...)
if not success then
geterrorhandler()(err)
end
end
 
local function HeapBubbleUp(index)
while index > 1 do
local parentIndex = floor(index / 2)
if heap[index].timeToFire < heap[parentIndex].timeToFire then
heap[index], heap[parentIndex] = heap[parentIndex], heap[index]
index = parentIndex
else
break
end
end
end
 
local function HeapBubbleDown(index)
while 2 * index <= heap.lastIndex do
local leftIndex = 2 * index
local rightIndex = leftIndex + 1
local current = heap[index]
local leftChild = heap[leftIndex]
local rightChild = heap[rightIndex]
 
if not rightChild then
if leftChild.timeToFire < current.timeToFire then
heap[index], heap[leftIndex] = heap[leftIndex], heap[index]
index = leftIndex
else
break
end
else
if leftChild.timeToFire < current.timeToFire or
rightChild.timeToFire < current.timeToFire then
if leftChild.timeToFire < rightChild.timeToFire then
heap[index], heap[leftIndex] = heap[leftIndex], heap[index]
index = leftIndex
else
heap[index], heap[rightIndex] = heap[rightIndex], heap[index]
index = rightIndex
end
else
break
end
end
end
end
 
local function OnUpdate()
local schedule = heap[1]
while schedule and schedule.timeToFire < GetTime() do
if schedule.cancelled then
local last = heap.lastIndex
heap[1], heap[last] = heap[last], heap[1]
heap[heap.lastIndex] = nil
heap.lastIndex = heap.lastIndex - 1
HeapBubbleDown(1)
else
if schedule.func then
if schedule.args then
safecall(schedule.func, unpack(schedule.args))
else
safecall(schedule.func)
end
end
 
if schedule.repeating then
schedule.timeToFire = schedule.timeToFire + schedule.repeating
HeapBubbleDown(1)
else
local last = heap.lastIndex
heap[1], heap[last] = heap[last], heap[1]
heap[heap.lastIndex] = nil
heap.lastIndex = heap.lastIndex - 1
HeapBubbleDown(1)
timers[schedule.name] = nil
end
end
schedule = heap[1]
end
if not schedule then frame:Hide() end
end
frame:SetScript("OnUpdate", OnUpdate)
 
--------------------------------------------------------------------------------
-- :ScheduleTimer(name, func, delay, ...)
-- Notes:
-- * Schedule a timer to expire in delay seconds at which point it will call the callback func. name is an identifier for this timer.
-- * If you try to schedule a timer with the same name a second time, the old schedule will be overwritten.
-- Arguments:
-- name (variant) - The name of the timer to be scheduled. You can use this name to check if this timer's status and/or cancel it.
-- func (function or nil) - A function to be called when the timer expires, can be nil.
-- delay (number) - The number of seconds it takes for this timer to expire.
-- ... - Any additional arguments to pass to the callback.
-- Callback Signature:
-- func(...)
-- Example:
-- :ScheduleTimer("EncounterEnd", self.EncounterEnd, 10, self, 10)
-- :ScheduleTimer("EncounterEnd", nil, 10) -- why? used with :IsTimerScheduled("EncounterEnd")
--------------------------------------------------------------------------------
function SimpleTimer:ScheduleTimer(name, func, delay, ...)
argcheck(self, 1, "table")
argcheck(func, 3, "function", "nil")
argcheck(delay, 4, "number")
 
if SimpleTimer:IsTimerScheduled(name) then
SimpleTimer:CancelTimer(name)
end
 
local schedule = {}
timers[name] = schedule
schedule.timeToFire = GetTime() + delay
schedule.func = func
schedule.name = name
if select('#', ...) ~= 0 then
schedule.args = { ... }
end
 
if heap.lastIndex then
heap.lastIndex = heap.lastIndex + 1
else
heap.lastIndex = 1
end
heap[heap.lastIndex] = schedule
HeapBubbleUp(heap.lastIndex)
if not frame:IsShown() then
frame:Show()
end
end
 
--------------------------------------------------------------------------------
-- :ScheduleRepeatingTimer(name, func, delay, ...)
-- Notes:
-- * Schedule a repeating timer that expires every delay seconds.
-- * If you try to schedule a timer with the same name a second time, the old schedule will be overwritten.
-- Arguments:
-- name (variant) - The name of the timer to be scheduled. You can use this name to check if this timer's status and/or cancel it.
-- func (function) - A function to be called when the timer expires.
-- delay (number) - The number of seconds it takes for this timer to expire.
-- ... - Any additional arguments to pass to the callback.
-- Callback Signature:
-- func(...)
--------------------------------------------------------------------------------
function SimpleTimer:ScheduleRepeatingTimer(name, func, delay, ...)
argcheck(func, 3, "function")
SimpleTimer:ScheduleTimer(name, func, delay, ...)
timers[name].repeating = delay
end
 
--------------------------------------------------------------------------------
-- :IsTimerScheduled(name)
-- Notes:
-- * Returns if the timer with the name specified is scheduled or not and also returns the time remaining for it to expire.
-- Arguments:
-- name (variant) - The name of the timer to query.
-- Returns:
-- nil - if the timer is not scheduled.
-- true, seconds (number) - if the timer is scheduled. seconds is the number of seconds required for the timer to expire.
--------------------------------------------------------------------------------
function SimpleTimer:IsTimerScheduled(name)
argcheck(self, 1, "table")
local schedule = timers[name]
if schedule then
return true, schedule.timeToFire - GetTime()
end
end
 
--------------------------------------------------------------------------------
-- :CancelTimer(name)
-- Notes:
-- * Cancels the timer scheduled with name.
-- Arguments:
-- name (variant) - The name of the timer to cancel.
--------------------------------------------------------------------------------
function SimpleTimer:CancelTimer(name)
argcheck(self, 1, "table")
local schedule = timers[name]
if not schedule then return end
schedule.cancelled = true
timers[name] = nil
end
 
--------------------------------------------------------------------------------
-- Embed handling
--------------------------------------------------------------------------------
SimpleTimer.embeds = SimpleTimer.embeds or {}
 
local mixins = {
"ScheduleTimer", "ScheduleRepeatingTimer", "IsTimerScheduled", "CancelTimer",
}
 
--------------------------------------------------------------------------------
-- :Embed(target)
-- Notes:
-- * Embeds "ScheduleTimer", "ScheduleRepeatingTimer", "IsTimerScheduled", "CancelTimer"
-- Arguments:
-- target (table) - The table with which to export methods onto.
-- Returns:
-- The table provided, after embedding.
--------------------------------------------------------------------------------
function SimpleTimer:Embed(target)
SimpleTimer.embeds[target] = true
for _, v in pairs(mixins) do
target[v] = SimpleTimer[v]
end
return target
end
 
for addon in pairs(SimpleTimer.embeds) do
SimpleTimer:Embed(addon)
end
trunk/Libs/LibSimpleTimer-1.0/LibSimpleTimer-1.0.toc New file
0,0 → 1,18
## Interface: 30000
## LoadOnDemand: 1
## Title: Lib: SimpleTimer-1.0
## Notes: A Simple Timer
## Notes-zhTW: 提供簡單計時功能的函式庫
## Author: Whitetooth
## X-eMail: hotdogee [at] gmail [dot] com
## X-Credits: Dongle Development Team
## X-Category: Library
## X-License: LGPL v2.1
## X-Encoding: UTF-8
## X-Curse-Packaged-Version: r33
## X-Curse-Project-Name: LibSimpleTimer-1.0
## X-Curse-Project-ID: libsimpletimer-1-0
## X-Curse-Repository-ID: wow/libsimpletimer-1-0/mainline
 
LibStub\LibStub.lua
lib.xml
trunk/Libs/LibSimpleTimer-1.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibSimpleTimer-1.0/lib.xml New file
0,0 → 1,4
<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="LibSimpleTimer-1.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/LibFail-1.0/LibFail-1.0.toc New file
0,0 → 1,20
## Interface: 30300
## Title: Lib: Fail-1.0
## Notes: Fires events whenever a raid member "fails."
## Version: 1.0.248
## Author: Sylvanaar, Sztanpet, Rinu, Maat, MysticalOS
## X-Curse-Packaged-Version: r248
## X-Curse-Project-Name: LibFail-1.0
## X-Curse-Project-ID: libfail-1-0
## X-Curse-Repository-ID: wow/libfail-1-0/mainline
 
## OptionalDeps: Ace3, LibStub, CallBackHandler-1.0
## X-Embeds: LibStub, CallBackHandler-1.0
 
## LoadOnDemand: 1
 
## X-Credits: Veev-Medivh(US) author of FailBot, Maat author of EnsidiaFails
 
embeds.xml
 
lib.xml
\ No newline at end of file
trunk/Libs/LibFail-1.0/lib.xml New file
0,0 → 1,4
<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="LibFail-1.0.lua" />
</Ui>
\ No newline at end of file
trunk/Libs/LibFail-1.0/lib/includes.xml New file
0,0 → 1,8
<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="LibStub\LibStub.lua"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml" />
 
 
</Ui>
trunk/Libs/LibFail-1.0/lib/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,239
--[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 3
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}
 
local type = type
local pcall = pcall
local pairs = pairs
local assert = assert
local concat = table.concat
local loadstring = loadstring
local next = next
local select = select
local type = type
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local next, xpcall, eh = ...
 
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 = ...
repeat
xpcall(call, eh)
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 = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(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, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
 
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[select('#', ...) + 1](events[eventname], eventname, ...)
 
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 select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId"
if type(self)~="table" and type(self)~="string" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
end
 
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(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 select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
 
 
for i=1,select("#",...) do
local self = select(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.
 
trunk/Libs/LibFail-1.0/lib/CallbackHandler-1.0/CallbackHandler-1.0.xml New file
0,0 → 1,4
<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="CallbackHandler-1.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/LibFail-1.0/lib/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibFail-1.0/lib/LibStub/LibStub.toc New file
0,0 → 1,13
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
 
LibStub.lua
trunk/Libs/LibFail-1.0/LibFail-1.0.lua New file
0,0 → 1,2512
local MAJOR, MINOR = "LibFail-1.0", tonumber("248") or 999
 
assert(LibStub, MAJOR.." requires LibStub")
 
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
 
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
local callbacks = lib.callbacks
 
lib.frame = lib.frame or CreateFrame("Frame")
local frame = lib.frame
 
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
 
--- Fail Events.
--@description The list of supported events
--@class table
--@name fail_events
--@field 1 Fail_Deconstructor_Light
--@field 2 Fail_Deconstructor_Gravity
--@field 3 Fail_Frogger
--@field 4 Fail_Heigan_Dance
--@field 5 Fail_KelThuzad_VoidZone
--@field 6 Fail_Mimiron_BombBots
--@field 7 Fail_Mimiron_Rocket
--@field 8 Fail_Mimiron_Shock
--@field 9 Fail_Sapphiron_Breath
--@field 10 Fail_Sartharion_LavaWaves
--@field 11 Fail_Sartharion_VoidZone
--@field 12 Fail_Thaddius_Jump
--@field 13 Fail_Thaddius_PolaritySwitch
--@field 14 Fail_Thorim_LightningChain
--@field 15 Fail_Thorim_LightningCharge
--@field 16 Fail_Thorim_Smash
--@field 17 Fail_Vezax_ShadowCrash
--@field 18 Fail_Vezax_Saronite
--@field 19 Fail_Hodir_FlashFreeze
--@field 20 Fail_Vezax_Leech
--@field 21 Fail_Mimiron_LaserBarrage
--@field 22 Fail_Mimiron_Flames
--@field 23 Fail_Council_Overload
--@field 24 Fail_Hodir_Icicle
--@field 25 Fail_Grobbulus_PoisonCloud
--@field 26 Fail_Freya_NatureBomb
--@field 27 Fail_Thorim_Blizzard
--@field 28 Fail_Yogg_Sanity
--@field 29 Fail_Yogg_DeathRay
--@field 30 Fail_Razorscale_Flame
--@field 31 Fail_Kologarn_Eyebeam
--@field 32 Fail_Auriaya_Voidzone
--@field 33 Fail_Hodir_BitingCold
--@field 34 Fail_Malygos_Dot
--@field 35 Fail_Gormok_FireBomb
--@field 36 Fail_Acidmaw_SlimePool
--@field 37 Fail_Acidmaw_AcidicSpew
--@field 38 Fail_Acidmaw_ParalyticToxin
--@field 39 Fail_Dreadscale_MoltenSpew
--@field 40 Fail_Icehowl_Trample
--@field 41 Fail_Jaraxxus_FelInferno
--@field 42 Fail_Jaraxxus_LegionFlame
--@field 43 Fail_FactionChampions_Hellfire
--@field 44 Fail_Valkyr_Orb
--@field 45 Fail_Valkyr_Vortex
--@field 46 Fail_Anubarak_Impale
--@field 47 Fail_Mimiron_WaterSpray
--@field 48 Fail_Mimiron_ProximityMine
--@field 49 Fail_Mimiron_FrostBomb
--@field 50 Fail_Yogg_LunaticGaze
--@field 51 Fail_Algalon_BigBang
--@field 52 Fail_Mimiron_Siren
--@field 53 Fail_Koralon_MeteorFist
--@field 54 Fail_Horsemen_VoideZone
--@field 55 Fail_Horsemen_Mark
--@field 56 Fail_Onyxia_FlameBreath
--@field 57 Fail_Onyxia_TailSweep
--@field 58 Fail_Archavon_ChokingCloud
--@field 59 Fail_Emalon_LightningNova
--@field 60 Fail_Emalon_ChainLightning
--@field 61 Fail_Koralon_FlameCinder
--@field 62 Fail_Auriaya_SonicScreech
--@field 63 Fail_Onyxia_DeepBreath
--@field 64 Fail_Algalon_CosmicSmash
--@field 65 Fail_Mimiron_NapalmShell
--@field 66 Fail_Freya_UnstableEnergy
--@field 67 Fail_Council_RuneOfDeath
--@field 68 Fail_Grobbulus_MutatingInjection
--@field 69 Fail_Yogg_OminousCloud
--@field 70 Fail_Marrowgar_Coldflame
--@field 71 Fail_Rotface_StickyOoze
--@field 72 Fail_Rotface_OozeExplosion
--@field 73 Fail_Onyxia_WarderNova
--@field 74 Fail_Onyxia_WarderCleave
--@field 75 Fail_Onyxia_Cleave
--@field 76 Fail_Malygos_ArcaneBreath
--@field 77 Fail_Algalon_Blackhole
--@field 78 Fail_Yogg_Malady
--@field 79 Fail_Freya_GroundTremor
--@field 80 Fail_Ignis_FlameJets
--@field 81 Fail_Freya_BindLife
--@field 82 Fail_Deconstructor_Voidzone
--@field 83 Fail_Marrowgar_Whirlwind
--@field 84 Fail_Marrowgar_SaberLash
--@field 85 Fail_Festergut_VileGas
--@field 86 Fail_Festergut_PungentBlight
--@field 87 Fail_Sartharion_Breath
--@field 88 Fail_Sartharion_TailLash
--@field 89 Fail_Deathwhisper_DeathNDecay
--@field 90 Fail_Sapphiron_TailSweep
--@field 91 Fail_Sapphiron_Cleave
--@field 92 Fail_Sindragosa_TailSmash
--@field 93 Fail_Sindragosa_FrostBreath
--@field 94 Fail_Sindragosa_BlisteringCold
--@field 96 Fail_Sindragosa_Cleave
--@field 97 Fail_Sindragosa_Instability
--@field 98 Fail_Sindragosa_FrostBomb
--@field 99 Fail_Sindragosa_IceTomb
--@field 100 Fail_Professor_MutatedSlime
--@field 101 Fail_LanaThel_UncontrollableFrenzy
--@field 102 Fail_LanaThel_BloodboltSplash
--@field 103 Fail_BloodPrinces_SystemicShockVortex
--@field 104 Fail_LanaThel_DeliriousSlash
--@field 105 Fail_Gunship_Explosion
--@field 106 Fail_Gunship_Explosion_Knockback
--@field 107 Fail_FactionChampions_Bladestorm
--@field 108 Fail_Saurfang_Rune
--@field 109 Fail_Saurfang_Beasts
--@field 110 Fail_Deathwhisper_Shade
--@field 111 Fail_Professor_MalleableGoo
--@field 112 Fail_Rotface_SlimeSpray
--@field 113 Fail_BloodPrinces_Flames
--@field 114 Fail_LanaThel_Pact
--@field 115 Fail_LanaThel_SwarmingShadows
--@field 116 Fail_ColdflameTrap
--@field 117 Fail_Professor_ChokingGas
--@field 118 Fail_Valithria_ColumnofFrost
--@field 119 Fail_TheLichKing_IceBurst
--@field 120 Fail_Sindragosa_ChilledtotheBone
--@field 121 Fail_TheLichKing_RemorselessWinter
--@field 122 Fail_TheLichKing_NecroticPlague
--@field 123 Fail_TheLichKing_ShadowTrap
--@field 124 Fail_Festergut_MalleableGoo
--@field 125 Fail_TheLichKing_Defile
--@field 126 Fail_TheLichKing_Shockwave
--@field 127 Fail_TheLichKing_SpiritBomb
--@field 128 Fail_Deathwhisper_ShadeExplosion
--@field 129 Fail_Halion_TwilightCutter
--@field 129 Fail_Halion_MeteorStrike
local fail_events = {
"Fail_Deconstructor_Light",
"Fail_Deconstructor_Gravity",
"Fail_Frogger",
"Fail_Heigan_Dance",
"Fail_KelThuzad_VoidZone",
"Fail_Mimiron_BombBots",
"Fail_Mimiron_Rocket",
"Fail_Mimiron_Shock",
"Fail_Sapphiron_Breath",
"Fail_Sartharion_LavaWaves",
"Fail_Sartharion_VoidZone",
"Fail_Thaddius_Jump",
"Fail_Thaddius_PolaritySwitch",
"Fail_Thorim_LightningChain",
"Fail_Thorim_LightningCharge",
"Fail_Thorim_Smash",
"Fail_Vezax_ShadowCrash",
"Fail_Vezax_Saronite",
"Fail_Vezax_Leech",
"Fail_Hodir_FlashFreeze",
"Fail_Mimiron_LaserBarrage",
"Fail_Mimiron_Flames",
"Fail_Council_Overload",
"Fail_Hodir_Icicle",
"Fail_Grobbulus_PoisonCloud",
"Fail_Freya_NatureBomb",
"Fail_Thorim_Blizzard",
"Fail_Yogg_Sanity",
"Fail_Yogg_DeathRay",
"Fail_Razorscale_Flame",
"Fail_Kologarn_Eyebeam",
"Fail_Auriaya_Voidzone",
"Fail_Hodir_BitingCold",
"Fail_Malygos_Dot",
"Fail_Gormok_FireBomb",
"Fail_Acidmaw_SlimePool",
"Fail_Acidmaw_AcidicSpew",
"Fail_Acidmaw_ParalyticToxin",
"Fail_Dreadscale_MoltenSpew",
"Fail_Icehowl_Trample",
"Fail_Jaraxxus_FelInferno",
"Fail_Jaraxxus_LegionFlame",
"Fail_FactionChampions_Hellfire",
"Fail_Valkyr_Orb",
"Fail_Valkyr_Vortex",
"Fail_Anubarak_Impale",
"Fail_Mimiron_WaterSpray",
"Fail_Mimiron_ProximityMine",
"Fail_Mimiron_FrostBomb",
"Fail_Yogg_LunaticGaze",
"Fail_Algalon_BigBang",
"Fail_Mimiron_Siren",
"Fail_Koralon_MeteorFist",
"Fail_Horsemen_VoideZone",
"Fail_Horsemen_Mark",
"Fail_Onyxia_FlameBreath",
"Fail_Onyxia_TailSweep",
"Fail_Archavon_ChokingCloud",
"Fail_Emalon_LightningNova",
"Fail_Emalon_ChainLightning",
"Fail_Koralon_FlameCinder",
"Fail_Auriaya_SonicScreech",
"Fail_Onyxia_DeepBreath",
"Fail_Algalon_CosmicSmash",
"Fail_Mimiron_NapalmShell",
"Fail_Freya_UnstableEnergy",
"Fail_Council_RuneOfDeath",
"Fail_Grobbulus_MutatingInjection",
"Fail_Yogg_OminousCloud",
"Fail_Marrowgar_Coldflame",
"Fail_Rotface_StickyOoze",
"Fail_Rotface_OozeExplosion",
"Fail_Onyxia_WarderNova",
"Fail_Onyxia_WarderCleave",
"Fail_Onyxia_Cleave",
"Fail_Malygos_ArcaneBreath",
"Fail_Algalon_Blackhole",
"Fail_Yogg_Malady",
"Fail_Freya_GroundTremor",
"Fail_Ignis_FlameJets",
"Fail_Freya_BindLife",
"Fail_Deconstructor_Voidzone",
"Fail_Marrowgar_Whirlwind",
"Fail_Marrowgar_SaberLash",
"Fail_Festergut_VileGas",
"Fail_Festergut_PungentBlight",
"Fail_Sartharion_Breath",
"Fail_Sartharion_TailLash",
"Fail_Deathwhisper_DeathNDecay",
"Fail_Sapphiron_TailSweep",
"Fail_Sapphiron_Cleave",
"Fail_Sindragosa_TailSmash",
"Fail_Sindragosa_FrostBreath",
"Fail_Sindragosa_BlisteringCold",
"Fail_Sindragosa_Cleave",
"Fail_Sindragosa_Instability",
"Fail_Sindragosa_FrostBomb",
"Fail_Sindragosa_IceTomb",
"Fail_Professor_MutatedSlime",
"Fail_LanaThel_UncontrollableFrenzy",
"Fail_LanaThel_BloodboltSplash",
"Fail_BloodPrinces_SystemicShockVortex",
"Fail_LanaThel_DeliriousSlash",
"Fail_Gunship_Explosion",
"Fail_Gunship_Explosion_Knockback",
"Fail_FactionChampions_Bladestorm",
"Fail_Saurfang_Rune",
"Fail_Saurfang_Beasts",
"Fail_Deathwhisper_Shade",
"Fail_Professor_MalleableGoo",
"Fail_Rotface_SlimeSpray",
"Fail_BloodPrinces_Flames",
"Fail_LanaThel_Pact",
"Fail_LanaThel_SwarmingShadows",
"Fail_ColdflameTrap",
"Fail_Professor_ChokingGas",
"Fail_Valithria_ColumnofFrost",
"Fail_TheLichKing_IceBurst",
"Fail_Sindragosa_ChilledtotheBone",
"Fail_TheLichKing_RemorselessWinter",
"Fail_TheLichKing_NecroticPlague",
"Fail_TheLichKing_ShadowTrap",
"Fail_Festergut_MalleableGoo",
"Fail_TheLichKing_Defile",
"Fail_TheLichKing_Shockwave",
"Fail_TheLichKing_SpiritBomb",
"Fail_Deathwhisper_ShadeExplosion",
"Fail_Halion_TwilightCutter",
"Fail_Halion_MeteorStrike",
}
 
--[===[@debug@
function lib:Test(overrideName)
local e = math.floor(math.random() * #fail_events) + 1
local p = math.floor(math.random() * 5) + 1
 
self:FailEvent(fail_events[e], overrideName or "Test"..p, lib.FAIL_TYPE_MOVING)
end
--@end-debug@]===]
 
local zones_with_fails = {
["The Ruby Sanctum"] = {
"Fail_Halion_TwilightCutter",
"Fail_Halion_MeteorStrike",
},
["Icecrown Citadel"] = {
"Fail_Rotface_StickyOoze",
"Fail_Rotface_OozeExplosion",
"Fail_Marrowgar_Whirlwind",
"Fail_Marrowgar_Coldflame",
"Fail_Marrowgar_SaberLash",
"Fail_Festergut_VileGas",
"Fail_Festergut_PungentBlight",
"Fail_Deathwhisper_DeathNDecay",
"Fail_Sindragosa_TailSmash",
"Fail_Sindragosa_FrostBreath",
"Fail_Sindragosa_BlisteringCold",
"Fail_Sindragosa_Cleave",
"Fail_Sindragosa_Instability",
"Fail_Sindragosa_FrostBomb",
"Fail_Sindragosa_IceTomb",
"Fail_Professor_MutatedSlime",
"Fail_LanaThel_UncontrollableFrenzy",
"Fail_LanaThel_BloodboltSplash",
"Fail_BloodPrinces_SystemicShockVortex",
"Fail_LanaThel_DeliriousSlash",
"Fail_Gunship_Explosion",
"Fail_Gunship_Explosion_Knockback",
"Fail_Saurfang_Rune",
"Fail_Saurfang_Beasts",
"Fail_Deathwhisper_Shade",
"Fail_Professor_MalleableGoo",
"Fail_Rotface_SlimeSpray",
"Fail_BloodPrinces_Flames",
"Fail_LanaThel_Pact",
"Fail_LanaThel_SwarmingShadows",
"Fail_ColdflameTrap",
"Fail_Professor_ChokingGas",
"Fail_Valithria_ColumnofFrost",
"Fail_TheLichKing_IceBurst",
"Fail_Sindragosa_ChilledtotheBone",
"Fail_TheLichKing_RemorselessWinter",
"Fail_TheLichKing_NecroticPlague",
"Fail_TheLichKing_ShadowTrap",
"Fail_Festergut_MalleableGoo",
"Fail_TheLichKing_Defile",
"Fail_TheLichKing_Shockwave",
"Fail_TheLichKing_SpiritBomb",
"Fail_Deathwhisper_ShadeExplosion",
},
["Onyxia's Lair"] = {
"Fail_Onyxia_FlameBreath",
"Fail_Onyxia_TailSweep",
"Fail_Onyxia_DeepBreath",
"Fail_Onyxia_WarderNova",
"Fail_Onyxia_WarderCleave",
"Fail_Onyxia_Cleave",
},
["Trial of the Crusader"] = {
"Fail_Gormok_FireBomb",
"Fail_Acidmaw_SlimePool",
"Fail_Acidmaw_AcidicSpew",
"Fail_Acidmaw_ParalyticToxin",
"Fail_Dreadscale_MoltenSpew",
"Fail_Icehowl_Trample",
"Fail_Jaraxxus_FelInferno",
"Fail_Jaraxxus_LegionFlame",
"Fail_FactionChampions_Hellfire",
"Fail_Valkyr_Orb",
"Fail_Valkyr_Vortex",
"Fail_Anubarak_Impale",
"Fail_FactionChampions_Bladestorm",
},
Ulduar = {
"Fail_Deconstructor_Light",
"Fail_Deconstructor_Gravity",
"Fail_Hodir_FlashFreeze",
"Fail_Hodir_BitingCold",
"Fail_Hodir_Icicle",
"Fail_Mimiron_BombBots",
"Fail_Mimiron_Rocket",
"Fail_Mimiron_Shock",
"Fail_Mimiron_LaserBarrage",
"Fail_Mimiron_Flames",
"Fail_Thorim_LightningChain",
"Fail_Thorim_LightningCharge",
"Fail_Thorim_Smash",
"Fail_Thorim_Blizzard",
"Fail_Vezax_Leech",
"Fail_Vezax_ShadowCrash",
"Fail_Vezax_Saronite",
"Fail_Council_Overload",
"Fail_Freya_NatureBomb",
"Fail_Yogg_Sanity",
"Fail_Yogg_DeathRay",
"Fail_Razorscale_Flame",
"Fail_Kologarn_Eyebeam",
"Fail_Auriaya_Voidzone",
"Fail_Mimiron_WaterSpray",
"Fail_Mimiron_ProximityMine",
"Fail_Mimiron_FrostBomb",
"Fail_Yogg_LunaticGaze",
"Fail_Algalon_BigBang",
"Fail_Mimiron_Siren",
"Fail_Auriaya_SonicScreech",
"Fail_Algalon_CosmicSmash",
"Fail_Mimiron_NapalmShell",
"Fail_Freya_UnstableEnergy",
"Fail_Council_RuneOfDeath",
"Fail_Yogg_OminousCloud",
"Fail_Algalon_Blackhole",
"Fail_Yogg_Malady",
"Fail_Freya_GroundTremor",
"Fail_Ignis_FlameJets",
"Fail_Freya_BindLife",
"Fail_Deconstructor_Voidzone",
},
Naxxramas = {
"Fail_Frogger",
"Fail_Heigan_Dance",
"Fail_KelThuzad_VoidZone",
"Fail_Sapphiron_Breath",
"Fail_Thaddius_Jump",
"Fail_Thaddius_PolaritySwitch",
"Fail_Horsemen_VoideZone",
"Fail_Horsemen_Mark",
"Fail_Grobbulus_MutatingInjection",
"Fail_Grobbulus_PoisonCloud",
"Fail_Sapphiron_TailSweep",
"Fail_Sapphiron_Cleave",
},
["The Obsidian Sanctum"] = {
"Fail_Sartharion_LavaWaves",
"Fail_Sartharion_VoidZone",
"Fail_Sartharion_Breath",
"Fail_Sartharion_TailLash",
},
["Eye of Eternity"] = {
"Fail_Malygos_Dot",
"Fail_Malygos_ArcaneBreath",
},
["Vault of Archavon"] = {
"Fail_Koralon_MeteorFist",
"Fail_Archavon_ChokingCloud",
"Fail_Emalon_LightningNova",
"Fail_Emalon_ChainLightning",
"Fail_Koralon_FlameCinder",
}
}
 
local fails_where_tanks_dont_fail = {
"Fail_Onyxia_FlameBreath",
"Fail_Onyxia_WarderNova",
"Fail_Onyxia_WarderCleave",
"Fail_Onyxia_Cleave",
"Fail_Acidmaw_AcidicSpew",
"Fail_Dreadscale_MoltenSpew",
"Fail_Mimiron_BombBots",
"Fail_Yogg_OminousCloud",
"Fail_Razorscale_Flame",
"Fail_Mimiron_ProximityMine",
"Fail_Koralon_MeteorFist",
"Fail_Emalon_LightningNova",
"Fail_Malygos_ArcaneBreath",
"Fail_Marrowgar_SaberLash",
"Fail_Sartharion_Breath",
"Fail_Sapphiron_Cleave",
"Fail_Sindragosa_FrostBreath",
"Fail_Sindragosa_BlisteringCold",
"Fail_Sindragosa_Cleave",
"Fail_Auriaya_SonicScreech",
"Fail_LanaThel_DeliriousSlash",
"Fail_Deathwhisper_Shade",
"Fail_Rotface_SlimeSpray",
"Fail_TheLichKing_NecroticPlague",
"Fail_TheLichKing_Shockwave",
"Fail_Deathwhisper_ShadeExplosion",
"Fail_Marrowgar_Coldflame",
"Fail_Festergut_MalleableGoo",
}
 
-- Spell id's to use for default localizations
local event_spellids = {
Fail_Acidmaw_AcidicSpew = 66819,
Fail_Acidmaw_ParalyticToxin = 67618,
Fail_Acidmaw_SlimePool = 66881,
Fail_Algalon_BigBang = 64584,
Fail_Algalon_CosmicSmash = 62311,
Fail_Anubarak_Impale = 67860,
Fail_Archavon_ChokingCloud = 58965,
Fail_Auriaya_SonicScreech = 64688,
Fail_Auriaya_Voidzone = 64459,
Fail_Council_Overload = 61878,
Fail_Council_RuneOfDeath = 63490,
Fail_Deconstructor_Light = 65120,
Fail_Deconstructor_Gravity = 64233,
Fail_Dreadscale_MoltenSpew = 66820,
Fail_Emalon_ChainLightning = 64213,
Fail_Emalon_LightningNova = 65279,
Fail_FactionChampions_Hellfire = 65817,
Fail_Freya_NatureBomb = 64650,
Fail_Freya_UnstableEnergy = 62865,
Fail_Frogger = 28433,
Fail_Gormok_FireBomb = 67472,
Fail_Grobbulus_MutatingInjection = 28169,
Fail_Grobbulus_PoisonCloud = 28158,
Fail_Heigan_Dance = 29371,
Fail_Hodir_BitingCold = 62038,
Fail_Hodir_FlashFreeze = 61969,
Fail_Hodir_Icicle = 62457,
Fail_Horsemen_Mark = 28836,
Fail_Horsemen_VoideZone = 28865,
Fail_Icehowl_Trample = 66734,
Fail_Jaraxxus_FelInferno = 68718,
Fail_Jaraxxus_LegionFlame = 67072,
Fail_KelThuzad_VoidZone = 27812,
Fail_Kologarn_Eyebeam = 63976,
Fail_Koralon_FlameCinder = 67332,
Fail_Koralon_MeteorFist = 68161,
Fail_Malygos_Dot = 56092,
Fail_Mimiron_BombBots = 63811,
Fail_Mimiron_Flames = 64566,
Fail_Mimiron_FrostBomb = 65333,
Fail_Mimiron_LaserBarrage = 63293,
Fail_Mimiron_NapalmShell = 65026,
Fail_Mimiron_ProximityMine = 63009,
Fail_Mimiron_Rocket = 63041,
Fail_Mimiron_Shock = 63631,
Fail_Mimiron_Siren = 64616,
Fail_Mimiron_WaterSpray = 64619,
Fail_Onyxia_DeepBreath = 17086,
Fail_Onyxia_FlameBreath = 68970,
Fail_Onyxia_TailSweep = 69286,
Fail_Onyxia_WarderCleave = 15284,
Fail_Onyxia_WarderNova = 68958,
Fail_Onyxia_Cleave = 68868,
Fail_Razorscale_Flame = 64733,
Fail_Rotface_OozeExplosion = 69839,
Fail_Rotface_StickyOoze = 69778,
Fail_Sapphiron_Breath = 28524,
Fail_Sartharion_LavaWaves = 57491,
Fail_Sartharion_VoidZone = 57581,
Fail_Sartharion_Breath = 56908,
Fail_Sartharion_TailLash = 56910,
Fail_Thaddius_Jump = 28801,
Fail_Thaddius_PolaritySwitch = 28089, -- 'polarity switch' spell id
Fail_Thorim_Blizzard = 62602,
Fail_Thorim_LightningChain = 64390,
Fail_Thorim_LightningCharge = 62466,
Fail_Thorim_Smash = 62465,
Fail_Valkyr_Orb = 67174,
Fail_Valkyr_Vortex = 67155,
Fail_Vezax_Leech = 63278,
Fail_Vezax_Saronite = 63338,
Fail_Vezax_ShadowCrash = 62659,
Fail_Yogg_DeathRay = 63884,
Fail_Yogg_LunaticGaze = 64168,
Fail_Yogg_OminousCloud = 60977,
Fail_Yogg_Sanity = 63120,
Fail_Malygos_ArcaneBreath = 56272,
Fail_Algalon_Blackhole = 62169,
Fail_Yogg_Malady = 63881,
Fail_Freya_GroundTremor = 62859,
Fail_Ignis_FlameJets = 62681,
Fail_Freya_BindLife = 63559,
Fail_Deconstructor_Voidzone = 64206,
Fail_Marrowgar_Whirlwind = 69075,
Fail_Marrowgar_Coldflame = 69138, -- the spellid of the summond "npc" that cralls, not the damage dealing spell
Fail_Marrowgar_SaberLash = 69055,
Fail_Festergut_VileGas = 71218,
Fail_Festergut_PungentBlight = 71219,
Fail_Deathwhisper_DeathNDecay = 71001,
Fail_Sapphiron_TailSweep = 55696,
Fail_Sapphiron_Cleave = 19983,
Fail_Sindragosa_TailSmash = 71077,
Fail_Sindragosa_FrostBreath = 69649,
Fail_Sindragosa_BlisteringCold = 70123,
Fail_Sindragosa_Cleave = 19983,
Fail_Sindragosa_Instability = 69766,
Fail_Sindragosa_FrostBomb = 69846,
Fail_Sindragosa_IceTomb = 70157,
Fail_Professor_MutatedSlime = 72456,
Fail_LanaThel_UncontrollableFrenzy = 70923,
Fail_LanaThel_BloodboltSplash = 71481,
Fail_BloodPrinces_SystemicShockVortex = 72815,
Fail_LanaThel_DeliriousSlash = 71624,
Fail_Gunship_Explosion = 69680,
Fail_Gunship_Explosion_Knockback = 69689,
Fail_FactionChampions_Bladestorm = 65946,
Fail_Saurfang_Rune = 72410,
Fail_Saurfang_Beasts = 72173, --the spellid of Call Blood Beast, not the actual fail.
Fail_Deathwhisper_Shade = 71426, --the spellid of Summon Spirit, not the actual fail.
Fail_Professor_MalleableGoo = 72458,
Fail_Rotface_SlimeSpray = 73190,
Fail_BloodPrinces_Flames = 72789,
Fail_LanaThel_Pact = 71341,
Fail_LanaThel_SwarmingShadows = 72635,
Fail_ColdflameTrap = 70461,
Fail_Professor_ChokingGas = 72620,
Fail_Valithria_ColumnofFrost = 72020,
Fail_TheLichKing_IceBurst = 73773,
Fail_Sindragosa_ChilledtotheBone = 70106,
Fail_TheLichKing_RemorselessWinter = 74270,
Fail_TheLichKing_NecroticPlague = 73913,
Fail_TheLichKing_ShadowTrap = 73529,
Fail_Festergut_MalleableGoo = 72550,
Fail_TheLichKing_Defile = 73708,
Fail_TheLichKing_Shockwave = 73794,
Fail_TheLichKing_SpiritBomb = 73572,
Fail_Deathwhisper_ShadeExplosion = 71544,
Fail_Halion_TwilightCutter = 77845,
Fail_Halion_MeteorStrike = 75952
}
 
--[===[@debug@
--FAIL = lib
function lib:TestEventIds()
for k,v in pairs(event_spellids) do
local spell = GetSpellInfo(v) or ""
print(k.." = "..spell)
end
end
--@end-debug@]===]
 
--- Get a list of supported events.
-- @see fail_events
-- @return a table of event names which can be fired
function lib:GetSupportedEvents() return fail_events end
 
--- Get a list of supported events in the current zone
-- @see fail_events
-- @return a table of event names which can be fired
function lib:GetSupportedZoneEvents(name) return zones_with_fails[name] end
 
--- Get a spell id which can be used for a default event string by calling GetSpellInfo()
-- @see fail_events
-- @param event_name the event name
-- @return a spell id represting this failure
function lib:GetEventSpellId(event_name) return event_spellids[event_name] end
 
--- Get a list of events where tanks do not fail, it is the responsibility of the hosting addon to determine who constitutes as a tank and ignore the event fired
-- @see fail_events
-- @return a table of event names which can be fired
function lib:GetFailsWhereTanksDoNotFail() return fails_where_tanks_dont_fail end
 
-- mainly for the Faction Champions - Hellfire event but could be usefull
local snare_effects = {
[1] = GetSpellInfo(65857), -- Entangling Roots
[2] = GetSpellInfo(66071), -- Natures Grasp
[3] = GetSpellInfo(65545), -- Psychic Horror
[4] = GetSpellInfo(65543), -- Psychic Scream
[5] = GetSpellInfo(65792), -- Frost Nova
[6] = GetSpellInfo(65809), -- Fear
[7] = GetSpellInfo(66613), -- Hammer of Justice
[8] = GetSpellInfo(65930), -- Intimidating Shout
[9] = GetSpellInfo(65880), -- Frost Trap
[10] = GetSpellInfo(66207), -- Wing Clip
[11] = GetSpellInfo(66020), -- Chains of Ice
--- ICC
[12] = GetSpellInfo(71615), -- Tear Gas -- Professor Putricide
[13] = GetSpellInfo(70447), -- Volatile Ooze Adhesive -- Professor Putricide
}
 
function lib:IsSnared(target)
for _, debuff in ipairs(snare_effects) do
if debuff == UnitDebuff(target, debuff) then return true end
end
 
return false
end
 
function lib:SaurfangCheck()
local bossId = lib:findTargetByGUID(37813)
if not bossId then return end
local target = UnitName(bossId .. "target")
if target then
if UnitIsUnit(target, lib.SaurfangTarget) then -- after 1 sec or many sec target is still same (2nd tank is failing)
lib.SaurfangTimer = lib.SaurfangTimer + 1 -- increase the variable so we know how much he is failing
lib:ScheduleTimer("SaurfangCheck", lib.SaurfangCheck, 1) -- check again in 1 sec if he is still failing
else -- after 1 sec or many sec we got a new target someone either didnt fail at 1st check or this is not the 1st check so someone already failed time to report it
if lib.SaurfangTimer > 1 then -- not the 1st check aka someone failed
lib:FailEvent("Fail_Saurfang_Rune", lib.SaurfangTarget, lib.FAIL_TYPE_SWITCHING)
lib.SaurfangTimer = 0 -- reset the timer after reporting
end -- do nothing if we got a new target at the 1st check
end
end
end
 
function lib:GetMobId(GUID)
if not GUID then return end
 
return tonumber(GUID:sub(-12, -7), 16)
end
 
function lib:findTargetByGUID(id)
local idType = type(id)
for i, unit in next, lib.targetlist do
if UnitExists(unit) and not UnitIsPlayer(unit) then
local unitId = UnitGUID(unit)
if idType == "number" then unitId = tonumber(unitId:sub(-12, -7), 16) end
if unitId == id then return unit end
end
end
end
 
function lib:InitVariables()
if not self.active then return end
 
self.ChargeCounter = {}
self.MalygosAlive = true
self.BigbangCasting = false
self.ThreePeopleHugging = false -- emalon chain lightning thing, needs a better name
self.VezaxLeechTarget = nil
self.DeathTime = 0
self.RaidTable = {} -- Mostly for the Auriaya fail, but could be usefull
self.SindragosaSingleBeacon = 0
self.SindragosaBeaconTarget = nil
self.TheLichKingNecroticPlagueTarget = {}
self.TheLichKingNecroticPlagueDispelCounter = 0
self.TheLichKingShadowTrapTarget = nil
self.DefileCastStart = 0
self.SaurfangTimer = 0
self.SaurfangTarget = nil
 
self.LastEvent = {}
 
self.targetlist = {"target", "targettarget", "focus", "focustarget", "mouseover", "mouseovertarget"}
for i = 1, 4 do self.targetlist[#self.targetlist+1] = string.format("boss%d", i) end
for i = 1, 4 do self.targetlist[#self.targetlist+1] = string.format("party%dtarget", i) end
for i = 1, 40 do self.targetlist[#self.targetlist+1] = string.format("raid%dtarget", i) end
 
-- Last whatever
for i=1, #fail_events do
self.LastEvent[fail_events[i]] = {}
end
 
end
 
function lib:InitRaidTable()
if next(self.RaidTable) then return end
local difficulty = GetRaidDifficulty()
 
for raidindex = 1, GetNumRaidMembers() do
local name, _, group, _, _, _, _, online = GetRaidRosterInfo(raidindex)
 
if difficulty <= 2 and group <= 2 and online then -- 10 man
self.RaidTable[name] = true
elseif group <= 5 and online then -- 25 man
self.RaidTable[name] = true
end
end
end
 
do
frame:Hide()
frame:SetScript("OnUpdate", function(self, elapsed)
for name, timer in pairs(lib.timers) do
timer.elapsed = timer.elapsed + elapsed
if timer.elapsed > timer.delay then
timer.func()
lib:CancelTimer(name)
end
end
end)
end
 
function lib:ScheduleTimer(name, func, delay)
if not self.timers then self.timers = {} end
self.timers[name] = {
elapsed = 0,
func = func,
delay = delay,
}
 
if not frame:IsShown() then frame:Show() end
end
 
function lib:CancelTimer(name)
if not name then
self.timers = {}
return frame:Hide()
end
 
self.timers[name] = nil
if not next(self.timers) then self:CancelTimer() end
end
 
function lib:IsTimerRunning(name)
return (self.timers and self.timers[name]) and true or false
end
 
lib.FAIL_TYPE_NOTMOVING = "notmoving" -- fails at not moving with probably something on him that triggers on movement
lib.FAIL_TYPE_MOVING = "moving" -- fails at moving out of shit
lib.FAIL_TYPE_NOTSPREADING = "notspreading" -- fails at standing together (think auriaya)
lib.FAIL_TYPE_SPREADING = "spreading" -- fails at not having enough distance between people
lib.FAIL_TYPE_DISPELLING = "dispelling" -- fails at not dispelling something you should be dispelling (not very usable yes, but for completeness)
lib.FAIL_TYPE_NOTDISPELLING = "notdispelling" -- fails at dispelling something you should NOT be dispelling
lib.FAIL_TYPE_WRONGPLACE = "wrongplace" -- being in the wrong place in the wrong time (cleave, etc)
lib.FAIL_TYPE_NOTCASTING = "notcasting" -- casting spells when you shouldnt have
lib.FAIL_TYPE_NOTATTACKING = "notattacking" -- attacking when you shouldnt have
lib.FAIL_TYPE_CASTING = "casting" -- not casting spells when you should have (think malygos phase3)
lib.FAIL_TYPE_SWITCHING = "switching" -- not taunting/switching tanks when you're supposed to
 
lib.BLOODPRINCES_FLAMES = 25000 -- make 25k default for achievment
lib.THADDIUS_JUMP_WINDOW = 120
lib.THADDIUS_JUMP_RETRY_WINDOW = 5
lib.FROGGER_DEATH_WINDOW = 4
lib.YOGGSARON_GAZE_THRESHOLD = 15 -- after how many ticks do we fail?
lib.VEZAX_LEECH_THRESHOLD = 400000 -- how much heal is "acceptable"
lib.EMALON_NOVA_THRESHOLD = 15000 -- on being hit by lightning nova, above what dmg does it take for it to be a fail (think DK-s with AMS)
lib.ONYXIA_DEEPBREATH_THRESHOLD = 5000 -- same as above
lib.COUNCIL_OVERLOAD_THRESHOLD = 4000 -- ^
lib.ALGALON_SMASH_THRESHOLD = 7000
lib.COUNCIL_RUNE_THRESHOLD = 3 -- the player got 3 seconds to move out of Rune of Death
lib.SINDRAGOSA_FROSTBOMB_THRESHOLD = 5000
lib.SINDRAGOSA_BLISTERINGCOLD_THRESHOLD = 10000
lib.HODIR_COLD_THRESHOLD = 2 -- stacks needed for a fail
 
do
local _, etype, f
 
frame:SetScript("OnEvent", function (self, event, ...)
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
_, etype = ...
if etype == "SPELL_MISSED" then -- lets hack the misses onto the damage event
local timestamp, _, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, missType, amountMissed = ...
local damage, overkill = 0, 0
 
lib.SPELL_DAMAGE(lib, timestamp, etype, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, damage, overkill, missType, amountMissed)
 
return
end
 
f = lib[etype]
 
if f then
f(lib, ...)
end
 
return
end
 
f = lib[event]
 
if f then
f(lib, ...)
end
 
end)
end
 
function lib:FailEvent(failname, playername, failtype, ...)
callbacks:Fire(failname, playername, failtype, ...)
callbacks:Fire("AnyFail", failname, playername, failtype, ...)
end
 
function lib:GoActive()
if self.active then return end
 
frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")
frame:RegisterEvent("CHAT_MSG_MONSTER_EMOTE")
self:InitVariables()
 
self.active = true
 
callbacks:Fire("Fail_Active")
end
 
function lib:GoInactive()
if not self.active then return end
 
self:InitVariables()
 
self.active = nil
 
frame:RegisterEvent("RAID_ROSTER_UPDATE")
frame:UnregisterEvent("CHAT_MSG_MONSTER_EMOTE")
frame:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
frame:UnregisterEvent("PLAYER_REGEN_ENABLED")
 
callbacks:Fire("Fail_Inactive")
end
 
lib.active = true
lib:GoInactive()
 
function lib:PLAYER_ENTERING_WORLD(...)
if GetNumRaidMembers() > 0 then
self:GoActive()
else
self:GoInactive()
end
end
 
function lib:RAID_ROSTER_UPDATE(...)
if GetNumRaidMembers() > 0 then
self:GoActive()
else
self:GoInactive()
end
end
 
function lib:PLAYER_REGEN_ENABLED()
self:InitVariables()
end
 
local ominous_cloud_name = GetSpellInfo(60977)
function lib:CHAT_MSG_MONSTER_EMOTE(message, sourceName, language, channelName, destName, ...)
-- Yogg-Saron - Ominous Cloud (spawning new mobs in phase 1)
if sourceName:find(ominous_cloud_name) then
self:FailEvent("Fail_Yogg_OminousCloud", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
local onyxia_breath_name = GetSpellInfo(18351)
function lib:SPELL_DAMAGE(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, damage, overkill)
-- Guardian activities ignored after this point
--5/7 21:13:33.865 SPELL_DAMAGE,0xF1300079F0003A98,"Mirror Image",0x2114,0xF130008092003842,"Elder Stonebark",0xa48,59637,"Fire Blast",0x4,139,0,4,0,0,0,nil,nil,nil
--5/7 21:13:36.092 SPELL_HEAL,0x01800000007C56B2,"Blackknite",0x512,0xF1300079F0003A97,"Mirror Image",0x2114,54968,"Glyph of Holy Light",0x2,1240,1240,nil
if bit.band(sourceFlags or 0, COMBATLOG_OBJECT_TYPE_GUARDIAN) > 0 or bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_GUARDIAN) > 0 or not spellId then return end
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
damage = damage ~= "ABSORB" and damage or 0
overkill = overkill or 0
 
-- Malygos - Arcane Breath(the cone attack, credits to mysticalos and Aviana)
if (spellId == 56272 or spellId == 60072) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Malygos_ArcaneBreath", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Halion - Twilight Cutter
if (spellId == 74769 or spellId == 77844 or spellId == 77845 or spellId == 77846) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Halion_TwilightCutter", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Halion - Meteor Strike (first 4 are impact, you died cause you let meteor land on you, rest are from standing in fire after impact. Seems to have various spellids for range from center)
if (spellId == 74648 or spellId == 75877 or spellId == 75878 or spellId == 75879
or spellId == 75952 or spellId == 75951 or spellId == 75950 or spellId == 75949 or spellId == 75948 or spellId == 75947) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Halion_MeteorStrike", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Icecrown Citadel
 
-- The Lich King - Shockwave
if (spellId == 73794 or spellId == 73795 or spellId == 72149 or spellId == 73796) and is_playerevent then
self:FailEvent("Fail_TheLichKing_Shockwave", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- The Lich King - Defile
 
if (spellId == 73708 or spellId == 73709 or spellId == 72754 or spellId == 73710) and is_playerevent then
if (((timestamp - self.DefileCastStart) > 3.3) and ((timestamp - self.DefileCastStart) < 5)) then -- cast time is 2 sec, and we are only interested in fails at the first 3 sec, after that its just all spam, but lets give you 1.3 sec to move out
self:FailEvent("Fail_TheLichKing_Defile", destName, self.FAIL_TYPE_NOTMOVING)
end
 
return
end
 
-- The Lich King - Spirit Bomb
if (spellId == 73804 or spellId == 73805) and is_playerevent then
self:FailEvent("Fail_TheLichKing_SpiritBomb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
 
-- The Lich King - Shadow Trap
if spellId == 73529 and is_playerevent then
if self.LastEvent.Fail_TheLichKing_ShadowTrap[destName] == nil then
self:FailEvent("Fail_TheLichKing_ShadowTrap", destName, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_TheLichKing_ShadowTrap[destName] = timestamp
else
if (timestamp - self.LastEvent.Fail_TheLichKing_ShadowTrap[destName]) > 5 then
self:FailEvent("Fail_TheLichKing_ShadowTrap", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_TheLichKing_ShadowTrap[destName] = timestamp
 
return
end
 
-- Frogger like fail for the Coldflame Trap after Deathbringers Rise
if spellId == 70461 and is_playerevent and overkill > 0 then
self:FailEvent("Fail_ColdflameTrap", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Gunship -- Explosion Knockback (heroic only)
if (spellId == 69688 or spellId == 69689) and is_playerevent then
self:FailEvent("Fail_Gunship_Explosion_Knockback", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Gunship -- Explosion (it's still avoidable so optional fail for normal mode)
if (spellId == 69680 or spellId == 69687) and is_playerevent then
self:FailEvent("Fail_Gunship_Explosion", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
--11/13 19:42:32.500 SPELL_DAMAGE,0x0100000000004105,"Fenitalol",0x514,0x010000000004AB38,"Belth",0x514,72815,"Systemic Shock Vortex",0x1,4477,227,1,0,0,0,nil,nil,nil
-- Blood Princes -- Systemic Shock Vortex
if (spellId == 72815 or spellId == 72816 or spellId == 72817 or spellId == 72038) and is_playerevent and overkill > 0 then
if bit.band(sourceFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0 then
self:FailEvent("Fail_BloodPrinces_SystemicShockVortex", destName, self.FAIL_TYPE_NOTSPREADING)
end
 
return
end
 
-- Blood Princes -- Flames
if spellId == 72789 and is_playerevent and damage > self.BLOODPRINCES_FLAMES then
self:FailEvent("Fail_BloodPrinces_Flames", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Blood Queen Lana'thel -- Swarming Shadows
if (spellId == 71268 or spellId == 72635 or spellId == 72636 or spellId == 72637) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_LanaThel_SwarmingShadows", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Blood Queen Lana'thel - Pact of the Darkfallen
if spellId == 71341 and is_playerevent and overkill > 0 then
self:FailEvent("Fail_LanaThel_Pact", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Blood Queen Lana'thel - Bloodbolt Splash
if (spellId == 71447 or spellId == 71481 or spellId == 71482 or spellId == 71483) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_LanaThel_BloodboltSplash", destName, self.FAIL_TYPE_NOTSPREADING)
 
return
end
 
-- Valithria Dreamwalker - Column of Frost
if (spellId == 70702 or spellId == 71746 or spellId == 72019 or spellId == 72020) and is_playerevent then
self:FailEvent("Fail_Valithria_ColumnofFrost", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Festergut - Pungent Blight
if (spellId == 71219 or spellId == 69195) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Festergut_PungentBlight", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Lady Deathwhisper Vengeful Shades Explosion(Melee are responsible for not standing in this if they target a tank.)
-- Tanks exempt though because a tank isn't going to kite the boss or adds around room just to dodge these
if (spellId == 71544 or spellId == 72010 or spellId == 72011 or spellId == 72012) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Deathwhisper_ShadeExplosion", destName, self.FAIL_TYPE_MOVING)
 
self.LastEvent.Fail_Deathwhisper_ShadeExplosion[destName] = timestamp
 
return
end
 
 
-- Lord Marrowgar - Whirlwind
if (spellId == 69075 or (spellId >= 70834 and spellId <= 70836)) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Marrowgar_Whirlwind", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Lord Marrowgar - Saber Lash (69055 trash mobs leading to marrowgar, other 2 marrowgar. Leaving all 3 since announcing fails on the trash still amusing)
if (spellId == 69055 or spellId == 70814 or spellId == 71021) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Marrowgar_SaberLash", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Rotface - Sticky Ooze (the slime pools)
if (spellId == 69778 or spellId == 71208 or spellId == 69776 or spellId == 69774) and is_playerevent then
if self.LastEvent.Fail_Rotface_StickyOoze[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Rotface_StickyOoze[destName]) > 3 then
self:FailEvent("Fail_Rotface_StickyOoze", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Rotface_StickyOoze[destName] = timestamp
 
return
end
 
-- Rotface - Slime Spray
if (spellId == 69507 or spellId == 71213 or spellId == 73189 or spellId == 73190) and is_playerevent then
if self.LastEvent.Fail_Rotface_SlimeSpray[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Rotface_SlimeSpray[destName]) > 3 then
self:FailEvent("Fail_Rotface_SlimeSpray", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Rotface_SlimeSpray[destName] = timestamp
 
return
end
 
-- Rotface - Unstable Ooze Explosion
if (spellId == 69839 or spellId == 71209 or spellId == 69833 or spellId == 69832) and is_playerevent then
self:FailEvent("Fail_Rotface_OozeExplosion", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sindragosa - Tail Smash
if (spellId == 71077) and is_playerevent then
self:FailEvent("Fail_Sindragosa_TailSmash", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sindragosa - Frost Breath
if (spellId == 69649 or spellId == 71056 or spellId == 71057 or spellId == 71058
or spellId == 73061 or spellId == 73062 or spellId == 73063 or spellId == 73064) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Sindragosa_FrostBreath", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Sindragosa - Blistering Cold
if (spellId == 70123 or spellId == 71047 or spellId == 71048 or spellId == 71049) and is_playerevent and damage > self.SINDRAGOSA_BLISTERINGCOLD_THRESHOLD then
self:FailEvent("Fail_Sindragosa_BlisteringCold", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sindragosa - Cleave
if spellId == 19983 and is_playerevent and overkill > 0 then
if self:GetMobId(sourceGUID) ~= 36853 then return end
 
self:FailEvent("Fail_Sindragosa_Cleave", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Sindragosa - Frost Bomb
if (spellId == 69845 or spellId == 71053 or spellId == 71054 or spellId == 71055) and is_playerevent and damage > self.SINDRAGOSA_FROSTBOMB_THRESHOLD then
self:FailEvent("Fail_Sindragosa_FrostBomb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sindragosa - Backlash (the damage part of Unchained Magic/Instability stacks)
if (spellId == 69770 or spellId == 71044) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Sindragosa_Instability", destName, self.FAIL_TYPE_NOTCASTING)
 
return
end
 
-- Sindragosa - Backlash-Heroic (This damages you AND anyone near you. this fail means you killed everyone near you) UNTESTED
if (spellId == 71045 or spellId == 71046) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Sindragosa_Instability", sourceName, self.FAIL_TYPE_NOTCASTING)
 
return
end
 
-- Saurfang Rune of Blood (More than 1 heal per taunt, 1 is super hard to avoid no matter how fast you taunt)
if (spellId == 72409 or spellId == 72447 or spellId == 72448 or spellId == 72449) and is_playerevent then
 
self.SaurfangTarget = destName
lib:ScheduleTimer("SaurfangCheck", lib.SaurfangCheck, 1) -- start the check in 1 sec
 
return
 
end
 
-- The Lich King - Ice Burst
if spellId == 73773 and is_playerevent then
self:FailEvent("Fail_TheLichKing_IceBurst", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- The Lich King - Remorseless Winter
if (spellId == 68981 or spellId == 68983 or spellId == 73791 or spellId == 73792 or spellId == 73793) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_TheLichKing_RemorselessWinter", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Professor - Mutated Slime
if spellId == 72456 and is_playerevent and damage > 0 then--Only one spellid seems needed, it seems the other IDs are server side and only thing sent to combat log is a dummyID for any difficulty
if self:IsSnared(destName) then return end
if self.LastEvent.Fail_Professor_MutatedSlime[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Professor_MutatedSlime[destName])
if (((deltaT) > 3) and ((deltaT) < 9)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Professor_MutatedSlime", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Professor_MutatedSlime[destName] = timestamp
end
end
 
self.LastEvent.Fail_Professor_MutatedSlime[destName] = timestamp
 
return
end
 
-- Festergut Heroic -- Malleable goo (Debuff)
if (spellId == 72549 or spellId == 72550) and is_playerevent and (damage > 10000 or overkill > 0) then
if self.LastEvent.Fail_Festergut_MalleableGoo[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Festergut_MalleableGoo[destName]) > 3 then
self:FailEvent("Fail_Festergut_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Festergut_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Festergut_MalleableGoo[destName] = timestamp
 
return
end
 
-- Professor - Malleable Goo (Debuff)
if (spellId == 70853 or spellId == 72458 or spellId == 72873 or spellId == 72874) and is_playerevent and (damage > 10000 or overkill > 0) then
if self:IsSnared(destName) then return end
if self.LastEvent.Fail_Professor_MalleableGoo[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Professor_MalleableGoo[destName]) > 3 then
self:FailEvent("Fail_Professor_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Professor_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Professor_MalleableGoo[destName] = timestamp
 
return
end
 
-- Professor - Choking Gas (Damage)
if (spellId == 72460 or spellId == 72619 or spellId == 72620 or spellId == 71278
or spellId == 71279 or spellId == 72459 or spellId == 72621 or spellId == 72622) and is_playerevent and overkill > 0 then
if self:IsSnared(destName) then return end
self:FailEvent("Fail_Professor_ChokingGas", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- VAULT OF ARCHAVON
 
-- Emalon - Lightning Nova
if (spellId == 65279 or spellId == 64216) and is_playerevent and damage >= self.EMALON_NOVA_THRESHOLD then
self:FailEvent("Fail_Emalon_LightningNova", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Emalon - Chain Lightning
if (spellId == 64213 or spellId == 64215) and is_playerevent then
if damage >= 10000 then -- at least 3 ppl hugging, and I think highest damage appears in combat log first always (Maat @Ensidiafails)
self.ThreePeopleHugging = true
self:ScheduleTimer("EmalonChainLightning", function() lib.ThreePeopleHugging = false end, 3)
end
if self.ThreePeopleHugging then
if self.LastEvent.Fail_Emalon_ChainLightning.time ~= nil then
if (timestamp - self.LastEvent.Fail_Emalon_ChainLightning.time) < 1 then
self:FailEvent("Fail_Emalon_ChainLightning", destName, self.FAIL_TYPE_NOTSPREADING)
end
end
 
self.LastEvent.Fail_Emalon_ChainLightning.time = timestamp
 
end
 
return
end
 
-- Koralon - Flame Cinder
if (spellId == 67332 or spellId == 66684) and is_playerevent then
if self.LastEvent.Fail_Koralon_FlameCinder[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Koralon_FlameCinder[destName])
if (((deltaT) > 2) and ((deltaT) < 6)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Koralon_FlameCinder", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Koralon_FlameCinder[destName] = timestamp
end
end
 
self.LastEvent.Fail_Koralon_FlameCinder[destName] = timestamp
 
return
end
 
-- ONYXIA'S LAIR
 
-- Onyxian Lair Guard - Blast Nova
if spellId == 68958 and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Onyxia_WarderNova", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Onyxian Warder - Cleave
--10/21 21:44:57.024 SPELL_DAMAGE,0xF130002F610053DF,"Onyxian Warder",0xa48,0x05000000025092DE,"Nopher",0x514,15284,"Cleave",0x1,8816,0,1,0,0,2120,nil,nil,nil
if spellId == 15284 and overkill > 0 and is_playerevent then
if self:GetMobId(sourceGUID) ~= 12129 then return end
 
self:FailEvent("Fail_Onyxia_WarderCleave", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Onyxia - Cleave
if spellId == 68868 and overkill > 0 and is_playerevent then
if UnitDebuff(destName, GetSpellInfo(18431)) then return end -- target afflicted by fear, dont fail it
self:FailEvent("Fail_Onyxia_Cleave", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Onyxia - Deep Breath (when flying)
-- The deal with the spellIds is that it depends on WHERE onyxia is, from that point
-- every breath has 8 corresponding spellIds (the farther you are the less dmg, well
-- those are seperate spells, there are ~90 spellids, so we check for the name instead (idea by mysticalos))
if spellName == onyxia_breath_name and is_playerevent then
if overkill > 0 or damage >= self.ONYXIA_DEEPBREATH_THRESHOLD then
if self.LastEvent.Fail_Onyxia_DeepBreath[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Onyxia_DeepBreath[destName]) > 5 then
self:FailEvent("Fail_Onyxia_DeepBreath", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Onyxia_DeepBreath", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Onyxia_DeepBreath[destName] = timestamp
end
 
return
end
 
-- Onyxia - Flame Breath (the cone attack)
if (spellId == 68970 or spellId == 18435) and is_playerevent then -- not a fail for tanks, but we dont care about that here
if UnitDebuff(destName, GetSpellInfo(18431)) then return end -- target afflicted by fear, dont fail it
self:FailEvent("Fail_Onyxia_FlameBreath", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Onyxia - Tail Sweep
if (spellId == 69286 or spellId == 68867) and is_playerevent then
if UnitDebuff(destName, GetSpellInfo(18431)) then return end -- target afflicted by fear, dont fail it
self:FailEvent("Fail_Onyxia_TailSweep", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- TRIAL OF THE CRUSADER
 
-- Northrend Beasts - Gormok - Fire Bomb
if spellId == 66317 and is_playerevent then -- the initial damage from whence you have 2 seconds to move
self.LastEvent.Fail_Gormok_FireBomb[destName] = timestamp
 
return
elseif (spellId == 67472 or spellId == 66320 or spellId == 67475 or spellId == 67473) and is_playerevent then
if not self.LastEvent.Fail_Gormok_FireBomb[destName] then
-- no initial damage, so the failer managed to go into the flame on the ground, good job
self.LastEvent.Fail_Gormok_FireBomb[destName] = timestamp
end
if (timestamp - self.LastEvent.Fail_Gormok_FireBomb[destName]) > 2 then
self:FailEvent("Fail_Gormok_FireBomb", destName, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_Gormok_FireBomb[destName] = timestamp -- so as not to spam
end
 
return
end
 
-- Northrend Beasts - Acidmaw - Slime Pool (only trigger on damage, touching the slime pool should'nt be a fail)
if (spellId == 66881 or spellId == 67638 or spellId == 67639 or spellId == 67640) and is_playerevent then
if UnitDebuff(destName, GetSpellInfo(67618)) then return end -- Paralytic Toxin (if the dude can't move, let's not fail him/her)
 
if self.LastEvent.Fail_Acidmaw_SlimePool[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Acidmaw_SlimePool[destName]) > 3 then
self:FailEvent("Fail_Acidmaw_SlimePool", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Acidmaw_SlimePool", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Acidmaw_SlimePool[destName] = timestamp
 
return
end
 
-- Northrend Beasts - Dreadscale - Molten Spew (the cone attack (breath))
if (spellId == 66820 or spellId == 67635 or spellId == 67636 or spellId == 67637) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Dreadscale_MoltenSpew", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Northrend Beasts - Acidmaw - Acidic Spew (the cone attack (breath))
if (spellId == 66819 or spellId == 67609 or spellId == 67610 or spellId == 67611) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Acidmaw_AcidicSpew", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Northrend Beasts - Icehowl - Trample
if spellId == 66734 and is_playerevent then
self:FailEvent("Fail_Icehowl_Trample", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Lord Jaraxxus - Legion Flame
if (spellId == 67072 or spellId == 67070 or spellId == 66877 or spellId == 67071) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Jaraxxus_LegionFlame", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Lord Jaraxxus - Fel Inferno
if (spellId == 68718 or spellId == 66496 or spellId == 68716 or spellId == 68717) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Jaraxxus_FelInferno", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Faction Champions - Hellfire
if (spellId == 65817 or spellId == 68142 or spellId == 68143 or spellId == 68144) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_FactionChampions_Hellfire", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Faction Champions - Bladestorm
if spellId == 65946 and is_playerevent and overkill > 0 then
self:FailEvent("Fail_FactionChampions_Bladestorm", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Twin Val'kyr - Unleashed Light / Dark (the orbs, only from heroic)
if (spellId == 67174 or spellId == 67240 or spellId == 67173 or spellId == 67239) and is_playerevent and damage > 0 and overkill > 0 then
self:FailEvent("Fail_Valkyr_Orb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
-- Twin Val'kyr - Unleashed Light / Dark (the rest of the orbs)
elseif (spellId == 65808 or spellId == 67172 or spellId == 65795 or spellId == 67238) and is_playerevent and damage > 0 and overkill > 0 then
self:FailEvent("Fail_Valkyr_Orb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Twin Val'kyr - Light / Dark Vortex - Non-Heroic (it's a fail only on death)
-- When you have the correct color you resist the vortex with 100% chance
-- but because we hax the SPELL_MISS event onto the SPELL_DAMAGE event, we must
-- check for the damage done
if (spellId == 67155 or spellId == 67203 or spellId == 66048 or spellId == 66059) and damage > 0 and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Valkyr_Vortex", destName, self.FAIL_TYPE_NOTMOVING)
 
return
-- Twin Val'kyr - Light / Dark Vortex - Heroic
elseif (spellId == 67205 or spellId == 67157 or spellId == 67156 or spellId == 67204) and damage > 0 and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Valkyr_Vortex", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Anub'arak - Impale
if (spellId == 65919 or spellId == 67860 or spellId == 67858 or spellId == 67859) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Anubarak_Impale", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- ULDUAR
 
-- Kologarn Eyebeam
if (spellId == 63976 or spellId == 63346) and is_playerevent then
if self.LastEvent.Fail_Kologarn_Eyebeam[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Kologarn_Eyebeam[destName]) > 5 then
self:FailEvent("Fail_Kologarn_Eyebeam", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Kologarn_Eyebeam", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Kologarn_Eyebeam[destName] = timestamp
 
return
end
 
-- Auriaya - Sonic Screech (not standing in it is a fail)
-- Look in CAST_START for the details
if (spellId == 64688 or spellId == 64422) and is_playerevent then
self.RaidTable[destName] = false
 
return
end
 
-- Auriaya Void Zone (not a fail if stunned by the kitty)
if (spellId == 64459 or spellId == 64675) and is_playerevent then
if UnitDebuff(destName, GetSpellInfo(64386)) then return end
if self.LastEvent.Fail_Auriaya_Voidzone[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Auriaya_Voidzone[destName])
if (((deltaT) > 3) and ((deltaT) < 9)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Auriaya_Voidzone", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Auriaya_Voidzone[destName] = timestamp
end
end
 
self.LastEvent.Fail_Auriaya_Voidzone[destName] = timestamp
 
return
end
 
-- Razorscale Flame
if (spellId == 64733 or spellId == 64704) and is_playerevent then
if self.LastEvent.Fail_Razorscale_Flame[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Razorscale_Flame[destName])
if (((deltaT) > 2) and ((deltaT) < 6)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Razorscale_Flame", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Razorscale_Flame[destName] = timestamp
end
end
 
self.LastEvent.Fail_Razorscale_Flame[destName] = timestamp
 
return
end
 
-- Yogg Saron Death Ray
if (spellId == 63884 or spellId == 63891) and is_playerevent then
if self.LastEvent.Fail_Yogg_DeathRay[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Yogg_DeathRay[destName]) > 5 then
self:FailEvent("Fail_Yogg_DeathRay", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Yogg_DeathRay", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Yogg_DeathRay[destName] = timestamp
 
return
end
 
-- Yogg-Saron - Lunatic Gaze
if (spellId == 64168 or spellId == 64164) and is_playerevent then
if not self.LastEvent.Fail_Yogg_LunaticGaze[destName] then self.LastEvent.Fail_Yogg_LunaticGaze[destName] = 1 end
 
if spellId == 64168 then -- Yogg-Saron's lunatic gaze, not so serious
self.LastEvent.Fail_Yogg_LunaticGaze[destName] = self.LastEvent.Fail_Yogg_LunaticGaze[destName] + 1
else -- Laughing Skull's lunatic gaze, more serious
self.LastEvent.Fail_Yogg_LunaticGaze[destName] = self.LastEvent.Fail_Yogg_LunaticGaze[destName] + 2
end
 
if self.LastEvent.Fail_Yogg_LunaticGaze[destName] >= self.YOGGSARON_GAZE_THRESHOLD then
self.LastEvent.Fail_Yogg_LunaticGaze[destName] = 0
self:FailEvent("Fail_Yogg_LunaticGaze", destName, self.FAIL_TYPE_NOTMOVING)
end
 
return
end
 
-- Algalon - Cosmic Smash
if (spellId == 62311 or spellId == 64596) and is_playerevent and damage >= self.ALGALON_SMASH_THRESHOLD then
if self.LastEvent.Fail_Algalon_CosmicSmash[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Algalon_CosmicSmash[destName]) > 2 then
self:FailEvent("Fail_Algalon_CosmicSmash", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Algalon_CosmicSmash", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Algalon_CosmicSmash[destName] = timestamp
 
return
end
 
-- Algalon - Big Bang
if (spellId == 64584 or spellId == 64443) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Algalon_BigBang", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Freya Nature Bomb
if (spellId == 64650 or spellId == 64587) and is_playerevent then
if UnitDebuff(destName, GetSpellInfo(62861)) then return end
 
self:FailEvent("Fail_Freya_NatureBomb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Hodir Icicle (aka Ice Shards)
if (spellId == 62457 or spellId == 65370) and is_playerevent then
self:FailEvent("Fail_Hodir_Icicle", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- EnsidiaFails - Maat
-- Hodir Biting Cold
if (spellId == 62038 or spellId == 62188) and is_playerevent then
local stack = select(4, UnitDebuff(destName, GetSpellInfo(62039)))
 
if stack ~= nil and stack > self.HODIR_COLD_THRESHOLD then
if self.LastEvent.Fail_Hodir_BitingCold[destName] == nil or (timestamp - self.LastEvent.Fail_Hodir_BitingCold[destName]) > 5 then
self:FailEvent("Fail_Hodir_BitingCold", destName, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_Hodir_BitingCold[destName] = timestamp
end
end
 
return
end
 
-- Council Overload
if (spellId == 61878 or spellId == 63480) and is_playerevent and damage >= self.COUNCIL_OVERLOAD_THRESHOLD then -- DKs with AMS shouln't fail
if self:GetMobId(sourceGUID) ~= 32857 then return end
 
self:FailEvent("Fail_Council_Overload", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- XT-002 Deconstructor: Light Bomb
if (spellId == 65120 or spellId == 63023) and sourceGUID ~= destGUID and is_playerevent then
if self.LastEvent.Fail_Deconstructor_Light[sourceName] ~= nil then
if (timestamp - self.LastEvent.Fail_Deconstructor_Light[sourceName]) > 9 then--Reset timestamp if you were out of it for a while to prevent instant fails from outdated timestamps from earlier fight.
self.LastEvent.Fail_Deconstructor_Light[sourceName] = timestamp
elseif (timestamp - self.LastEvent.Fail_Deconstructor_Light[sourceName]) > 3 then
self:FailEvent("Fail_Deconstructor_Light", sourceName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Deconstructor_Light[sourceName] = timestamp
 
return
end
 
-- XT-002 Deconstructor: Gravity Bomb (bomb part)
if (spellId == 64233 or spellId == 63025) and sourceGUID ~= destGUID and is_playerevent then
if self.LastEvent.Fail_Deconstructor_Gravity[sourceName] ~= nil then
self:FailEvent("Fail_Deconstructor_Gravity", sourceName, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_Deconstructor_Gravity[sourceName] = nil
end
 
return
end
 
-- XT-002 Deconstructor - Void Zone (on heroic, what the gravity bomb leaves behind)
--5/7 18:19:04.078 SPELL_DAMAGE,0xF1300084D1002E23,"Void Zone",0xa48,0x0300000001D3239F,"Diomache",0x514,64208,"Consumption",0x20,6258,0,32,0,0,0,nil,nil,nil
if (spellId == 64208 or spellId == 64206) and is_playerevent then
self:FailEvent("Fail_Deconstructor_Voidzone", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Failbot - Viiv
-- 4/16 22:06:17.885 SPELL_DAMAGE,0xF1300081F702D928,"General Vezax",0x10a48,0x05000000027FCDFE,"Kosie",0x514,62659,"Shadow Crash",0x20,9413,0,32,2285,0,0,nil,nil,nil
-- Vezax Shadow Crash
if (spellId == 62659 or spellId == 63277) and is_playerevent and damage > 0 then
self:FailEvent("Fail_Vezax_ShadowCrash", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Vezax Saronite Vapor Suicide
if spellId == 63338 and is_playerevent then
self.LastEvent.Fail_Vezax_Saronite[destName] = timestamp
 
return
end
 
-- Failbot - Viiv
-- 4/16 18:20:24.295 SPELL_DAMAGE,0xF130008061018374,"Thorim",0x8010a48,0x0500000001E8AF39,"Thefeint",0x514,62466,"Lightning Charge",0x8,8977,0,8,3966,0,0,nil,nil,nil
-- Thorim Lightning Charge
if spellId == 62466 and is_playerevent then
if self:GetMobId(sourceGUID) ~= 32865 then return end -- it's not from Thorim
self:FailEvent("Fail_Thorim_LightningCharge", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Thorim Chain Lightning
if (spellId == 64390 or spellId == 62131) and is_playerevent then
if damage > 10000 then
self.ThreePeopleHugging = true
self:ScheduleTimer("ThorimChainLightning", function() lib.ThreePeopleHugging = false end, 3)
end
 
if self.ThreePeopleHugging then
if self.LastEvent.Fail_Thorim_LightningChain[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Thorim_LightningChain[destName]) < 1 then
self:FailEvent("Fail_Thorim_LightningChain", destName, self.FAIL_TYPE_NOTSPREADING)
end
end
 
self.LastEvent.Fail_Thorim_LightningChain[destName] = timestamp
 
end
 
return
end
 
-- 4/16 01:06:26.414 SPELL_DAMAGE,0x0000000000000000,nil,0x80000000,0x05000000027ECA9C,"Cn",0x514,62465,"Runic Smash",0x4,6544,0,4,3116,0,0,nil,nil,nil
-- Thorim Hallway Smash
if spellId == 62465 and is_playerevent then
self:FailEvent("Fail_Thorim_Smash", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Failbot - Viiv
-- 4/16 18:50:56.578 SPELL_DAMAGE,0x0000000000000000,nil,0x80000000,0x05000000027ECB89,"Logicalness",0x514,64875,"Sapper Explosion",0x40,67542,45099,64,28421,0,0,nil,nil,nil
-- Mimiron Trash - Sapper Explosion
if spellId == 64875 and is_playerevent then
self:FailEvent("Fail_Boss_Sapper", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Mimiron - Flames
if spellId == 64566 and is_playerevent and damage > 0 then
if self.LastEvent.Fail_Mimiron_Flames[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Mimiron_Flames[destName])
if (((deltaT) > 3) and ((deltaT) < 9)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Mimiron_Flames", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Mimiron_Flames[destName] = timestamp
end
end
 
self.LastEvent.Fail_Mimiron_Flames[destName] = timestamp
 
return
end
 
-- Mimiron - Napalm Shell
-- Two or more people getting damage usually triggers this
if (spellId == 65026 or spellId == 63666) and is_playerevent then
if self.LastEvent.Fail_Mimiron_NapalmShell[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Mimiron_NapalmShell[destName]) < 1 then
self:FailEvent("Fail_Mimiron_NapalmShell", destName, self.FAIL_TYPE_MOVING)
end
end
 
self.LastEvent.Fail_Mimiron_NapalmShell[destName] = timestamp
 
return
end
 
 
-- Mimiron - Water Spray
if spellId == 64619 and is_playerevent then
self:FailEvent("Fail_Mimiron_WaterSpray", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Mimiron - Proximity Mine (should check for sourcename == proximity mine?)
if (spellId == 63009 or spellId == 66351) and is_playerevent then
if self:GetMobId(sourceGUID) ~= 34362 then return end -- Explosion not from mines
 
if self.LastEvent.Fail_Mimiron_ProximityMine[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Mimiron_ProximityMine[destName]) > 3 then
self:FailEvent("Fail_Mimiron_ProximityMine", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Mimiron_ProximityMine", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Mimiron_ProximityMine[destName] = timestamp
 
return
end
 
-- Mimiron - Frost Bomb
if (spellId == 65333 or spellId == 64626) and is_playerevent then
if self:GetMobId(sourceGUID) ~= 34149 then return end --Explosion not from Frost Bomb
 
self:FailEvent("Fail_Mimiron_FrostBomb", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Mimiron Laser Barrage
if spellId == 63293 and is_playerevent then
if self.LastEvent.Fail_Mimiron_LaserBarrage[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Mimiron_LaserBarrage[destName]) > 10 then
self:FailEvent("Fail_Mimiron_LaserBarrage", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Mimiron_LaserBarrage", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Mimiron_LaserBarrage[destName] = timestamp
 
return
end
 
-- Mimiron Rocket Strike
if spellId == 63041 and is_playerevent then
self:FailEvent("Fail_Mimiron_Rocket", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Failbot - Viiv
-- 4/16 13:35:12.750 SPELL_DAMAGE,0xF13000842C0094E3,"Bomb Bot",0xa48,0x05000000027ECCA5,"Naddia",0x512,63801,"Bomb Bot",0x4,20216,4025,4,5054,0,0,nil,nil,nil
-- Mimiron Bomb Bots
if spellId == 63801 and is_playerevent and damage > 0 then
self:FailEvent("Fail_Mimiron_BombBots", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- 3/13 21:17:23.756 SPELL_DAMAGE,0xF150008298002210,"Leviathan Mk II",0x10a48,0xF1300007AC0025A9,"Treant",0x1114,63631,"Shock Blast",0x8,97000,92908,8,0,0,0,nil,nil,nil
-- Mimiron Shock Blast
if spellId == 63631 and is_playerevent and damage > 0 then
self:FailEvent("Fail_Mimiron_Shock", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- OBSIDIAN SANCTUM
 
-- Sartharion Lava Waves: Flame Tsunami
if spellId == 57491 and is_playerevent and damage > 0 then
if self.LastEvent.Fail_Sartharion_LavaWaves[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Sartharion_LavaWaves[destName]) > 10 then
self:FailEvent("Fail_Sartharion_LavaWaves", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Sartharion_LavaWaves", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Sartharion_LavaWaves[destName] = timestamp
 
return
end
 
-- Sartharion - Void Zone
if (spellId == 57581 or spellId == 59128) and damage > 0 and is_playerevent then
self:FailEvent("Fail_Sartharion_VoidZone", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sartharion - Flame Breath
if (spellId == 56908 or spellId == 58956) and is_playerevent then
self:FailEvent("Fail_Sartharion_Breath", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Sartharion - Tail Lash
if (spellId == 56910 or spellId == 58957) and is_playerevent then
self:FailEvent("Fail_Sartharion_TailLash", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- NAXXRAMAS
 
-- Grobbulus - Poison (the cloud that the injection leaves behind)
-- When the Mutating Injection ends or Grobbulus thinks its time to take a shit under itself,
-- it SPELL_SUMMON's a Grobbulus Cloud (which is the cloud and it grows) and applies a buff to itself called Posion
-- Poison is what damages people, and that is why you don't get out of combat until all the clouds disappear
if (spellId == 28158 or spellId == 54362) and is_playerevent then
if self.LastEvent.Fail_Grobbulus_PoisonCloud[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Grobbulus_PoisonCloud[destName])
if (((deltaT) > 3) and ((deltaT) < 9)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Grobbulus_PoisonCloud", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Grobbulus_PoisonCloud[destName] = timestamp
end
end
 
self.LastEvent.Fail_Grobbulus_PoisonCloud[destName] = timestamp
 
return
end
 
-- The Four Horsemen - Void Zone
if spellId == 28865 and damage > 0 and is_playerevent then
if self.LastEvent.Fail_Horsemen_VoideZone[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Horsemen_VoideZone[destName]) > 3 then
self:FailEvent("Fail_Horsemen_VoideZone", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Horsemen_VoideZone", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Horsemen_VoideZone[destName] = timestamp
 
return
end
 
-- The Four Horsemen - Mark death
if spellId == 28836 and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Horsemen_Mark", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Heigan - Eruption (aka dance fail)
if spellId == 29371 and is_playerevent then
self:FailEvent("Fail_Heigan_Dance", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Kel'Thuzad - Void Blast (aka Void Zone)
if spellId == 27812 and is_playerevent then
self:FailEvent("Fail_KelThuzad_VoidZone", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sapphiron - Frost Breath
if (spellId == 28524 or spellId == 29318) and is_playerevent then
self:FailEvent("Fail_Sapphiron_Breath", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sartharion - Tail Sweep
if (spellId == 55696 or spellId == 55697) and is_playerevent then
self:FailEvent("Fail_Sapphiron_TailSweep", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Sartharion - Cleave
if spellId == 19983 and overkill > 0 and is_playerevent then
if self:GetMobId(sourceGUID) ~= 15989 then return end
 
self:FailEvent("Fail_Sapphiron_Cleave", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
if spellId == 28433 and is_playerevent then
if overkill > 0 then
self:FailEvent("Fail_Frogger", destName, self.FAIL_TYPE_WRONGPLACE)
else
self.LastEvent.Fail_Frogger[destName] = timestamp
end
 
return
end
 
-- Thaddius Polarity Switch
-- 28062 Positive Charge
-- 28085 Negative Charge
if spellId == 28062 or spellId == 28085 then
if self.ChargeCounter[sourceName] == nil then
self.ChargeCounter[sourceName] = 1
self.LastEvent.Fail_Thaddius_PolaritySwitch[sourceName] = timestamp
elseif (timestamp - self.LastEvent.Fail_Thaddius_PolaritySwitch[sourceName]) < 2 then
self.ChargeCounter[sourceName] = self.ChargeCounter[sourceName] + 1
self.LastEvent.Fail_Thaddius_PolaritySwitch[sourceName] = timestamp
else
self.ChargeCounter[sourceName] = 1
self.LastEvent.Fail_Thaddius_PolaritySwitch[sourceName] = timestamp
end
 
if self.ChargeCounter[sourceName] == 3 then
self:FailEvent("Fail_Thaddius_PolaritySwitch", sourceName, self.FAIL_TYPE_NOTMOVING)
end
 
return
end
end
 
function lib:SWING_DAMAGE(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, damage, overkill)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
damage = damage ~= "ABSORB" and damage or 0
overkill = overkill or 0
 
--12/26 20:27:36.560 SWING_DAMAGE,0xF13000966C005B92,"Blood Beast",0x10a48,0x040000000396C708,"Outofcontrol",0x2000514,5033,0,1,0,0,1258,nil,nil,nil
-- Saurfang Blood Beasts
if self:GetMobId(sourceGUID) == 38508 and is_playerevent and damage > 0 then
self:FailEvent("Fail_Saurfang_Beasts", destName, self.FAIL_TYPE_MOVING)
 
self.LastEvent.Fail_Saurfang_Beasts[destName] = timestamp
 
return
end
 
-- Lady Deathwhisper Vengeful Shades
-- The shade will swing (and hit or miss) its target after it catches up with it, then explode. Fail should be given to the player that failed to avoid the shade, not necessarily others within the explosion range (which is 20 yards in 25 heroic)
if self:GetMobId(sourceGUID) == 38222 and is_playerevent then
self:FailEvent("Fail_Deathwhisper_Shade", destName, self.FAIL_TYPE_MOVING)
 
self.LastEvent.Fail_Deathwhisper_Shade[destName] = timestamp
 
return
end
end
 
function lib:SWING_MISSED(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Lady Deathwhisper Vengeful Shades
-- The shade will swing (and hit or miss) its target after it catches up with it, then explode. Fail should be given to the player that failed to avoid the shade, not necessarily others within the explosion range (which is 20 yards in 25 heroic)
if self:GetMobId(sourceGUID) == 38222 and is_playerevent then
self:FailEvent("Fail_Deathwhisper_Shade", destName, self.FAIL_TYPE_MOVING)
 
self.LastEvent.Fail_Deathwhisper_Shade[destName] = timestamp
 
return
end
end
 
function lib:ENVIRONMENTAL_DAMAGE(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, dmgType)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Thaddius Falling
if (timestamp - self.DeathTime) < self.THADDIUS_JUMP_WINDOW and dmgType == "FALLING" and is_playerevent then
self:FailEvent("Fail_Thaddius_Jump", destName, self.FAIL_TYPE_MOVING)
 
self.LastEvent.Fail_Thaddius_Jump[destName] = timestamp
 
return
end
end
 
-- Thaddius Polarity Shift
function lib:SPELL_CAST_START(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool)
-- local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Auriaya - Sonic Screech
-- The raid table is initialized in this form: "playername" => true
-- in SPELL_DAMAGE above, we set those to false who get the damage
-- and check here for who is still true, we also reset the whole thing
-- so it can be reused in in the fight (InitRaidtable will return
-- if the table is already filled)
if spellId == 64688 or spellId == 64422 then
self:InitRaidTable()
self:ScheduleTimer("AuriayaScreech", function()
for name, failed in pairs(lib.RaidTable) do
if failed then
lib:FailEvent("Fail_Auriaya_SonicScreech", name, self.FAIL_TYPE_MOVING)
else
lib.RaidTable[name] = true
end
end
end, 4)
return
end
 
-- Algalon - Big Bang timer
if spellId == 64584 or spellId == 64443 then
self.BigbangCasting = true
self:ScheduleTimer("Algalon_BigBang", function() lib.BigbangCasting = false end, 8)
 
return
end
 
-- The Lich King - Defile timer
if spellId == 72762 then
self.DefileCastStart = timestamp
 
return
end
end
 
function lib:UNIT_DIED(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
local mobid = self:GetMobId(destGUID)
 
-- 15929 stalagg 15930 feugen for thaddius fails
if mobid == 15929 or mobid == 15930 then
self.DeathTime = timestamp
 
return
end
 
if self.LastEvent.Fail_Frogger[destName] then
if (timestamp - self.LastEvent.Fail_Frogger[destName]) < self.FROGGER_DEATH_WINDOW and is_playerevent then
self:FailEvent("Fail_Frogger", destName, self.FAIL_TYPE_WRONGPLACE)
end
 
self.LastEvent.Fail_Frogger[destName] = nil
 
return
end
 
-- Saronite Vapor Suicide (Fail_Vezax_Saronite) death within 2sec of saronite damage
if self.LastEvent.Fail_Vezax_Saronite[destName] then
if (timestamp - self.LastEvent.Fail_Vezax_Saronite[destName]) < 2 then
self:FailEvent("Fail_Vezax_Saronite", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Vezax_Saronite[destName] = nil
 
return
end
 
 
end
 
function lib:SPELL_PERIODIC_DAMAGE(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, damage, overkill)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
damage = damage ~= "ABSORB" and damage or 0
overkill = overkill or 0
 
-- Sindragosa - Chilled to the Bone (Melee debuff from attacking too much without clearing it)
if spellId == 70106 and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Sindragosa_ChilledtotheBone", destName, self.FAIL_TYPE_NOTATTACKING)
 
return
end
 
-- Lady Deathwhisper - Death and Decay
if (spellId == 71001 or spellId == 72108 or spellId == 72109 or spellId == 72110) and is_playerevent then
if self.LastEvent.Fail_Deathwhisper_DeathNDecay[destName] ~= nil then
local deltaT = (timestamp - self.LastEvent.Fail_Deathwhisper_DeathNDecay[destName])
if (((deltaT) > 3) and ((deltaT) < 9)) then--If >3 times threshold reset timestamp since it's probably from earlier fight and not genuine fail.
self:FailEvent("Fail_Deathwhisper_DeathNDecay", destName, self.FAIL_TYPE_NOTMOVING)
else
self.LastEvent.Fail_Deathwhisper_DeathNDecay[destName] = timestamp
end
end
 
self.LastEvent.Fail_Deathwhisper_DeathNDecay[destName] = timestamp
 
return
end
 
--[==[ -- Festergut - Vile Gas (disabled until a more reliable method is found)
if (spellId == 71218 or spellId == 69240 or spellId == 69244 or spellId == 69248) and is_playerevent then
if self.LastEvent.Fail_Festergut_VileGas[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Festergut_VileGas[destName]) > 3 then
self:FailEvent("Fail_Festergut_VileGas", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Festergut_VileGas[destName] = timestamp
 
return
end]==]
 
-- Archavon - Choking Cloud
if (spellId == 58965 or spellId == 61672) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Archavon_ChokingCloud", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Northrend Beasts - Acidmaw - Paralytic Toxin
if (spellId == 67618 or spellId == 67619 or spellId == 67620 or spellId == 66823) and overkill > 0 and is_playerevent then
self:FailEvent("Fail_Acidmaw_ParalyticToxin", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Freya - Unstable Energy
if (spellId == 62865 or spellId == 62451) and is_playerevent then
local hasroots = UnitDebuff(destName, GetSpellInfo(62861))
 
if self.LastEvent.Fail_Freya_UnstableEnergy[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Freya_UnstableEnergy[destName]) > 4 and not hasroots then
self:FailEvent("Fail_Freya_UnstableEnergy", destName, self.FAIL_TYPE_NOTMOVING)
end
elseif not hasroots then
self:FailEvent("Fail_Freya_UnstableEnergy", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Freya_UnstableEnergy[destName] = timestamp
 
return
end
 
-- Thorim Blizzard
if (spellId == 62602 or spellId == 62576) and is_playerevent then
if self.LastEvent.Fail_Thorim_Blizzard[destName] == nil then
self.LastEvent.Fail_Thorim_Blizzard[destName] = 0
end
 
self.LastEvent.Fail_Thorim_Blizzard[destName] = self.LastEvent.Fail_Thorim_Blizzard[destName] + 1
 
if self.LastEvent.Fail_Thorim_Blizzard[destName] == 2 then
self:FailEvent("Fail_Thorim_Blizzard", destName, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_Thorim_Blizzard[destName] = 0
end
 
return
end
 
-- The Iron Council - Rune of Death
if (spellId == 63490 or spellId == 62269) and is_playerevent then
if self.LastEvent.Fail_Council_RuneOfDeath[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Council_RuneOfDeath[destName]) > self.COUNCIL_RUNE_THRESHOLD then
self:FailEvent("Fail_Council_RuneOfDeath", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Council_RuneOfDeath[destName] = timestamp
 
return
end
 
-- Lord Marrowgar - Coldflame
if (spellId == 69146 or (spellId >= 70823 and spellId <= 70825)) and is_playerevent then
if self.LastEvent.Fail_Marrowgar_Coldflame[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Marrowgar_Coldflame[destName]) > 4 then--Reset timestamp if you were out of it for 2 times fail threshold to prevent instant fails from out of date timestamps.
self.LastEvent.Fail_Marrowgar_Coldflame[destName] = timestamp
elseif (timestamp - self.LastEvent.Fail_Marrowgar_Coldflame[destName]) > 2 then
self:FailEvent("Fail_Marrowgar_Coldflame", destName, self.FAIL_TYPE_NOTMOVING)
end
end
 
self.LastEvent.Fail_Marrowgar_Coldflame[destName] = timestamp
 
return
end
end
 
function lib:SPELL_HEAL(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, damage)
-- local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Vezax Mark of the Faceless
if spellId == 63278 then
if self.LastEvent.Fail_Vezax_Leech > self.VEZAX_LEECH_THRESHOLD then
self:FailEvent("Fail_Vezax_Leech", self.VezaxLeechTarget, self.FAIL_TYPE_NOTMOVING)
self.LastEvent.Fail_Vezax_Leech = 0
end
 
self.LastEvent.Fail_Vezax_Leech = self.LastEvent.Fail_Vezax_Leech + damage
 
return
end
end
 
function lib:SPELL_AURA_APPLIED(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, auraType)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Festergut Heroic -- Malleable goo (Debuff)
if (spellId == 72549 or spellId == 72550) and is_playerevent then
if self.LastEvent.Fail_Festergut_MalleableGoo[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Festergut_MalleableGoo[destName]) > 3 then
self:FailEvent("Fail_Festergut_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Festergut_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Festergut_MalleableGoo[destName] = timestamp
 
return
end
 
-- Professor - Malleable Goo (Debuff)
if (spellId == 70853 or spellId == 72458 or spellId == 72873 or spellId == 72874) and is_playerevent then
if self:IsSnared(destName) then return end
if self.LastEvent.Fail_Professor_MalleableGoo[destName] ~= nil then
if (timestamp - self.LastEvent.Fail_Professor_MalleableGoo[destName]) > 3 then
self:FailEvent("Fail_Professor_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
else
self:FailEvent("Fail_Professor_MalleableGoo", destName, self.FAIL_TYPE_NOTMOVING)
end
 
self.LastEvent.Fail_Professor_MalleableGoo[destName] = timestamp
 
return
end
 
-- Professor - Choking Gas (Debuff)
if (spellId == 72460 or spellId == 72619 or spellId == 72620 or spellId == 71278) and is_playerevent then
if self:IsSnared(destName) then return end
self:FailEvent("Fail_Professor_ChokingGas", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Blood Queen Lana'thel - Delirious Slash
if spellId == 71624 and is_playerevent then
self:FailEvent("Fail_LanaThel_DeliriousSlash", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
 
-- Blood Queen Lana'thel - Uncontrollable Frenzy
if (spellId == 70923 or spellId == 70924) then
self:FailEvent("Fail_LanaThel_UncontrollableFrenzy", destName, self.FAIL_TYPE_CASTING)
 
return
end
 
-- Sindragosa - Frost Beacon (detecting if only one people got it)
if spellId == 70126 and is_playerevent then
if self.SindragosaSingleBeacon ~= 0 then
self.SindragosaSingleBeacon = false
 
return
end
 
if self.SindragosaSingleBeacon == 0 then
self.SindragosaSingleBeacon = true
self.SindragosaBeaconTarget = destName
 
self:ScheduleTimer("Sindragosa_SingleBeacon", function() lib.SindragosaSingleBeacon = 0 end, 10)
end
 
-- Sindragosa - Ice Tomb (print the message only once)
elseif spellId == 70157 and is_playerevent then
if not self.SindragosaSingleBeacon or self:IsTimerRunning("Sindragosa_TombFail") or lib.SindragosaBeaconTarget == destName then return end
 
self:ScheduleTimer("Sindragosa_TombFail", function()
lib:FailEvent("Fail_Sindragosa_IceTomb", lib.SindragosaBeaconTarget, lib.FAIL_TYPE_NOTMOVING)
end, 0.2)
 
end
 
-- Vezax Mark of the Faceless
if spellId == 63276 and is_playerevent then
-- save the name of the player who gains mark of the faceless
self.VezaxLeechTarget = destName
self.LastEvent.Fail_Vezax_Leech = 0
 
return
end
 
-- Hodir Flash Freeze
if (spellId == 61969 or spellId == 61990) and is_playerevent and auraType ~= "BUFF" then
self:FailEvent("Fail_Hodir_FlashFreeze", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Yogg Saron Sanity Lost
if spellId == 63120 and is_playerevent then
self:FailEvent("Fail_Yogg_Sanity", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Yogg Saron Malady aka Death Coil
if spellId == 63881 and is_playerevent then
self:FailEvent("Fail_Yogg_Malady", destName, self.FAIL_TYPE_MOVING)
 
return
end
 
-- Thaddius Jump
if spellId == 28801 and (timestamp - self.DeathTime) < self.THADDIUS_JUMP_WINDOW and is_playerevent then
if self.LastEvent.Fail_Thaddius_Jump[destName] == nil then
self:FailEvent("Fail_Thaddius_Jump", destName, self.FAIL_TYPE_NOTMOVING)
elseif (timestamp - self.LastEvent.Fail_Thaddius_Jump[destName]) > self.THADDIUS_JUMP_RETRY_WINDOW then
self:FailEvent("Fail_Thaddius_Jump", destName, self.FAIL_TYPE_NOTMOVING)
end
 
return
end
 
-- Algalon - Black Hole (if big bang is not casting, it's a fail)
if spellId == 62169 and is_playerevent and not self.BigbangCasting then
self:FailEvent("Fail_Algalon_Blackhole", destName, self.FAIL_TYPE_MOVING)
 
return
end
 
-- Light Bomb
if (spellId == 65120 or spellId == 63023) and is_playerevent then
self.LastLight[destName] = timestamp
 
return
end
 
-- Mimiron - Deafening Siren
if spellId == 64616 and is_playerevent then
self:FailEvent("Fail_Mimiron_Siren", destName, self.FAIL_TYPE_NOTMOVING)
 
return
end
 
-- Koralon the Flame Watcher - Meteor Fist (a fail if a non-tank gets it, let "userspace" handle it)
if (spellId == 67333 or spellId == 66765) and is_playerevent and overkill > 0 then
self:FailEvent("Fail_Koralon_MeteorFist", destName, self.FAIL_TYPE_WRONGPLACE)
 
return
end
end
 
function lib:SPELL_INTERRUPT(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, extraSpellId)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Flame Jets -- Ignis
if spellId == 62681 and is_playerevent then
self:FailEvent("Fail_Ignis_FlameJets", destName, self.FAIL_TYPE_NOTCASTING)
 
return
end
 
-- Ground Tremor -- Freya and Elder
if (spellId == 62859 or spellId == 62437 or spellId == 62325 or spellId == 62932) and is_playerevent then
self:FailEvent("Fail_Freya_GroundTremor", destName, self.FAIL_TYPE_NOTCASTING)
 
return
end
end
 
function lib:SPELL_SUMMON(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName)
-- local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
--SPELL_SUMMON,0xF15000838601084D,"Aerial Command Unit",0xa48,0xF13000842C010A24,"Bomb Bot",0xa28,63811,"Bomb Bot",0x1
if spellId == 63811 then
-- could add the GUID for each bot if this doesnt work.
self.LastEvent.Fail_Mimiron_BombBots = timestamp + 30
 
return
end
end
 
--70337, 73912, 73913, 73914 are cast success IDs (from lich king)
--70338, 73785, 73786, 73787 are jump spellids (from another player, these don't show in combat log when they jump, only do damage)
function lib:SPELL_CAST_SUCCESS(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool)
-- The Lich King - Necrotic Plague
if spellId == 70337 or spellId == 73912 or spellId == 73913 or spellId == 73914 then
if self.LastEvent.TheLichKing_NecroticPlague and timestamp - self.LastEvent.TheLichKing_NecroticPlague > 35 then
self.TheLichKingNecroticPlagueDispelCounter = 0
self.TheLichKingNecroticPlagueTarget = {}
else
if self.TheLichKingNecroticPlagueDispelCounter > 1 then
for i=0, self.TheLichKingNecroticPlagueDispelCounter do
self:FailEvent("Fail_TheLichKing_NecroticPlague", self.TheLichKingNecroticPlagueTarget[i], self.FAIL_TYPE_NOTMOVING)
end
end
self.TheLichKingNecroticPlagueDispelCounter = 0
self.TheLichKingNecroticPlagueTarget = {}
end
self.LastEvent.TheLichKing_NecroticPlague = timestamp
end
end
 
local necrotic_plague = GetSpellInfo(73912)
function lib:SPELL_DISPEL(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool, extraSpellId, extraSpellName)
-- Grobbulus - Mutating Injection
if extraSpellId == 28169 then
self:FailEvent("Fail_Grobbulus_MutatingInjection", sourceName, self.FAIL_TYPE_NOTDISPELLING)
 
return
end
 
-- Bind Life - Freya Trash
if extraSpellId == 63559 then
self:FailEvent("Fail_Freya_BindLife", sourceName, self.FAIL_TYPE_NOTDISPELLING)
 
return
end
 
-- The Lich King - Necrotic Plague
if extraSpellName == necrotic_plague and is_playerevent then
if UnitHealthMax(destName) < 50000 then -- poor mans tank check (you really should't do LK Heroic if your tank has less than 50k HP)
self.TheLichKingNecroticPlagueTarget[self.TheLichKingNecroticPlagueDispelCounter] = destName
self.TheLichKingNecroticPlagueDispelCounter = self.TheLichKingNecroticPlagueDispelCounter + 1
end
end
end
 
function lib:SPELL_AURA_REMOVED(timestamp, type, sourceGUID, sourceName, sourceFlags, destGUID, destName, destFlags, spellId, spellName, spellSchool)
local is_playerevent = bit.band(destFlags or 0, COMBATLOG_OBJECT_TYPE_PLAYER) > 0
 
-- Malygos Phase3 Dot
-- fail when you let the dot expire
if (spellId == 56092 or spellId == 61621) and self.MalygosAlive then
local failer = nil
 
for raidid = 1, GetNumRaidMembers() do
local pet = format("%s%d", "raidpet", raidid);
 
if (UnitGUID(pet) == sourceGUID) then
if UnitHealth(pet) > 0 then
local member = format("%s%d", "raid", raidid);
failer = UnitName(member);
else
failer = nil;
end
end
end
 
if failer ~= nil then
self:FailEvent("Fail_Malygos_Dot", failer, self.FAIL_TYPE_CASTING)
end
 
return
end
 
-- Thaddius Jump
if spellId == 28801 and (timestamp - self.DeathTime) < self.THADDIUS_JUMP_WINDOW and is_playerevent then
self.LastEvent.Fail_Thaddius_Jump[destName] = timestamp
 
return
end
 
-- Light Bomb
if spellId == 65120 or spellId == 63026 then
self.LastEvent.Fail_Deconstructor_Light[destName] = nil
 
return
end
 
-- Gravity Bomb
if spellId == 64233 or spellId == 63025 then
self.LastEvent.Fail_Deconstructor_Gravity[destName] = timestamp
 
return
end
end
trunk/Libs/LibFail-1.0/embeds.xml New file
0,0 → 1,7
<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.blizzard.com/wow/ui/" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
 
<Include file="lib\includes.xml"/>
 
</Ui>
\ No newline at end of file
trunk/Libs/LibBabble-Boss-3.0/LibBabble-3.0.lua New file
0,0 → 1,292
-- LibBabble-3.0 is hereby placed in the Public Domain
-- Credits: ckknight
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2
 
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR)
if not LibBabble then
return
end
 
local data = LibBabble.data or {}
for k,v in pairs(LibBabble) do
LibBabble[k] = nil
end
LibBabble.data = data
 
local tablesToDB = {}
for namespace, db in pairs(data) do
for k,v in pairs(db) do
tablesToDB[v] = db
end
end
 
local function warn(message)
local _, ret = pcall(error, message, 3)
geterrorhandler()(ret)
end
 
local lookup_mt = { __index = function(self, key)
local db = tablesToDB[self]
local current_key = db.current[key]
if current_key then
self[key] = current_key
return current_key
end
local base_key = db.base[key]
local real_MAJOR_VERSION
for k,v in pairs(data) do
if v == db then
real_MAJOR_VERSION = k
break
end
end
if not real_MAJOR_VERSION then
real_MAJOR_VERSION = LIBBABBLE_MAJOR
end
if base_key then
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GetLocale()))
rawset(self, key, base_key)
return base_key
end
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key))
rawset(self, key, key)
return key
end }
 
local function initLookup(module, lookup)
local db = tablesToDB[module]
for k in pairs(lookup) do
lookup[k] = nil
end
setmetatable(lookup, lookup_mt)
tablesToDB[lookup] = db
db.lookup = lookup
return lookup
end
 
local function initReverse(module, reverse)
local db = tablesToDB[module]
for k in pairs(reverse) do
reverse[k] = nil
end
for k,v in pairs(db.current) do
reverse[v] = k
end
tablesToDB[reverse] = db
db.reverse = reverse
db.reverseIterators = nil
return reverse
end
 
local prototype = {}
local prototype_mt = {__index = prototype}
 
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will warn but allow the code to pass through.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BL = B:GetLookupTable()
assert(BL["Some english word"] == "Some localized word")
DoSomething(BL["Some english word that doesn't exist"]) -- warning!
-----------------------------------------------------------------------------]]
function prototype:GetLookupTable()
local db = tablesToDB[self]
 
local lookup = db.lookup
if lookup then
return lookup
end
return initLookup(self, {})
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_has = B:GetUnstrictLookupTable()
assert(B_has["Some english word"] == "Some localized word")
assert(B_has["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetUnstrictLookupTable()
local db = tablesToDB[self]
 
return db.current
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_hasBase = B:GetBaseLookupTable()
assert(B_hasBase["Some english word"] == "Some english word")
assert(B_hasBase["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetBaseLookupTable()
local db = tablesToDB[self]
 
return db.base
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word")
Returns:
A lookup table for localized to english words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BR = B:GetReverseLookupTable()
assert(BR["Some localized word"] == "Some english word")
assert(BR["Some localized word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetReverseLookupTable()
local db = tablesToDB[self]
 
local reverse = db.reverse
if reverse then
return reverse
end
return initReverse(self, {})
end
local blank = {}
local weakVal = {__mode='v'}
--[[---------------------------------------------------------------------------
Arguments:
string - the localized word to chek for.
Returns:
An iterator to traverse all English words that map to the given key
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for word in B:GetReverseIterator("Some localized word") do
DoSomething(word)
end
-----------------------------------------------------------------------------]]
function prototype:GetReverseIterator(key)
local db = tablesToDB[self]
local reverseIterators = db.reverseIterators
if not reverseIterators then
reverseIterators = setmetatable({}, weakVal)
db.reverseIterators = reverseIterators
elseif reverseIterators[key] then
return pairs(reverseIterators[key])
end
local t
for k,v in pairs(db.current) do
if v == key then
if not t then
t = {}
end
t[k] = true
end
end
reverseIterators[key] = t or blank
return pairs(reverseIterators[key])
end
--[[---------------------------------------------------------------------------
Returns:
An iterator to traverse all translations English to localized.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for english, localized in B:Iterate() do
DoSomething(english, localized)
end
-----------------------------------------------------------------------------]]
function prototype:Iterate()
local db = tablesToDB[self]
 
return pairs(db.current)
end
 
-- #NODOC
-- modules need to call this to set the base table
function prototype:SetBaseTranslations(base)
local db = tablesToDB[self]
local oldBase = db.base
if oldBase then
for k in pairs(oldBase) do
oldBase[k] = nil
end
for k, v in pairs(base) do
oldBase[k] = v
end
base = oldBase
else
db.base = base
end
for k,v in pairs(base) do
if v == true then
base[k] = k
end
end
end
 
local function init(module)
local db = tablesToDB[module]
if db.lookup then
initLookup(module, db.lookup)
end
if db.reverse then
initReverse(module, db.reverse)
end
db.reverseIterators = nil
end
 
-- #NODOC
-- modules need to call this to set the current table. if current is true, use the base table.
function prototype:SetCurrentTranslations(current)
local db = tablesToDB[self]
if current == true then
db.current = db.base
else
local oldCurrent = db.current
if oldCurrent then
for k in pairs(oldCurrent) do
oldCurrent[k] = nil
end
for k, v in pairs(current) do
oldCurrent[k] = v
end
current = oldCurrent
else
db.current = current
end
end
init(self)
end
 
for namespace, db in pairs(data) do
setmetatable(db.module, prototype_mt)
init(db.module)
end
 
-- #NODOC
-- modules need to call this to create a new namespace.
function LibBabble:New(namespace, minor)
local module, oldminor = LibStub:NewLibrary(namespace, minor)
if not module then
return
end
 
if not oldminor then
local db = {
module = module,
}
data[namespace] = db
tablesToDB[module] = db
else
for k,v in pairs(module) do
module[k] = nil
end
end
 
setmetatable(module, prototype_mt)
 
return module
end
trunk/Libs/LibBabble-Boss-3.0/LibBabble-Boss-3.0.lua New file
0,0 → 1,6397
--[[
Name: LibBabble-Boss-3.0
Revision: $Rev: 287 $
Maintainers: ckknight, nevcairiel, Ackis
Website: http://www.wowace.com/projects/libbabble-boss-3-0/
Dependencies: None
License: MIT
]]
 
local MAJOR_VERSION = "LibBabble-Boss-3.0"
local MINOR_VERSION = 90000 + tonumber(("$Rev: 287 $"):match("%d+"))
 
if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
local lib = LibStub("LibBabble-3.0"):New(MAJOR_VERSION, MINOR_VERSION)
if not lib then return end
 
local GAME_LOCALE = GetLocale()
 
lib:SetBaseTranslations {
Acidmaw = "Acidmaw",
Aeonus = "Aeonus",
["Aerial Command Unit"] = "Aerial Command Unit",
["Agathelos the Raging"] = "Agathelos the Raging",
Ahune = "Ahune",
["Akil'zon"] = "Akil'zon",
["Aku'mai"] = "Aku'mai",
["Al'ar"] = "Al'ar",
["Algalon the Observer"] = "Algalon the Observer",
["Alzzin the Wildshaper"] = "Alzzin the Wildshaper",
Amanitar = "Amanitar",
["Ambassador Flamelash"] = "Ambassador Flamelash",
["Ambassador Hellmaw"] = "Ambassador Hellmaw",
["Amnennar the Coldbringer"] = "Amnennar the Coldbringer",
["Ancient Stone Keeper"] = "Ancient Stone Keeper",
Anetheron = "Anetheron",
["Anger'rel"] = "Anger'rel",
Anomalus = "Anomalus",
["Antu'sul"] = "Antu'sul",
["Anub'arak"] = "Anub'arak",
["Anubisath Defender"] = "Anubisath Defender",
["Anubisath Guardian"] = "Anubisath Guardian",
["Anub'Rekhan"] = "Anub'Rekhan",
["Anub'shiah"] = "Anub'shiah",
Anzu = "Anzu",
["Arcane Watchman"] = "Arcane Watchman",
["Arcanist Doan"] = "Arcanist Doan",
Archaedas = "Archaedas",
["Archavon the Stone Watcher"] = "Archavon the Stone Watcher",
Archimonde = "Archimonde",
["Archivist Galford"] = "Archivist Galford",
["Archmage Arugal"] = "Archmage Arugal",
["Argent Confessor Paletress"] = "Argent Confessor Paletress",
["Arugal's Voidwalker"] = "Arugal's Voidwalker",
["Assault Bot"] = "Assault Bot",
["Atal'alarion"] = "Atal'alarion",
["Attumen the Huntsman"] = "Attumen the Huntsman",
Auriaya = "Auriaya",
Avalanchion = "Avalanchion",
["Avatar of Hakkar"] = "Avatar of Hakkar",
["Ayamiss the Hunter"] = "Ayamiss the Hunter",
Azgalor = "Azgalor",
["Azshir the Sleepless"] = "Azshir the Sleepless",
Azuregos = "Azuregos",
["Bael'Gar"] = "Bael'Gar",
Baelog = "Baelog",
Balnazzar = "Balnazzar",
["Baltharus the Warborn"] = "Baltharus the Warborn",
["Bannok Grimaxe"] = "Bannok Grimaxe",
["Baron Aquanis"] = "Baron Aquanis",
["Baron Charr"] = "Baron Charr",
["Baroness Anastari"] = "Baroness Anastari",
["Baron Geddon"] = "Baron Geddon",
["Baron Kazum"] = "Baron Kazum",
["Baron Rivendare"] = "Baron Rivendare",
["Baron Silverlaine"] = "Baron Silverlaine",
["Battleguard Sartura"] = "Battleguard Sartura",
["Bazil Thredd"] = "Bazil Thredd",
Bazzalan = "Bazzalan",
["Black Guard Swordsmith"] = "Black Guard Swordsmith",
["Blackheart the Inciter"] = "Blackheart the Inciter",
["Blindeye the Seer"] = "Blindeye the Seer",
["Blind Hunter"] = "Blind Hunter",
["Blood Guard Porung"] = "Blood Guard Porung",
["Bloodlord Mandokir"] = "Bloodlord Mandokir",
["Bloodmage Thalnos"] = "Bloodmage Thalnos",
["Blood Prince Council"] = "Blood Prince Council",
["Blood Princes"] = "Blood Princes",
["Blood-Queen Lana'thel"] = "Blood-Queen Lana'thel",
["Blood Steward of Kirtonos"] = "Blood Steward of Kirtonos",
Boahn = "Boahn",
["Bomb Bot"] = "Bomb Bot",
["Brain of Yogg-Saron"] = "Brain of Yogg-Saron",
["Brainwashed Noble"] = "Brainwashed Noble",
Broggok = "Broggok",
Brokentoe = "Brokentoe",
Bronjahm = "Bronjahm",
["Broodlord Lashlayer"] = "Broodlord Lashlayer",
["Bruegal Ironknuckle"] = "Bruegal Ironknuckle",
Brutallus = "Brutallus",
["Burning Felguard"] = "Burning Felguard",
["Buru the Gorger"] = "Buru the Gorger",
["Cache of the Firelord"] = "Cache of the Firelord",
["Cannon Master Willey"] = "Cannon Master Willey",
["Captain Greenskin"] = "Captain Greenskin",
["Captain Kromcrush"] = "Captain Kromcrush",
["Captain Skarloc"] = "Captain Skarloc",
["Celebras the Cursed"] = "Celebras the Cursed",
["Charlga Razorflank"] = "Charlga Razorflank",
["Chess Event"] = "Chess Event",
["Chest of The Seven"] = "Chest of The Seven",
["Chief Ukorz Sandscalp"] = "Chief Ukorz Sandscalp",
["Cho'Rush the Observer"] = "Cho'Rush the Observer",
Chromaggus = "Chromaggus",
["Chrono Lord Deja"] = "Chrono Lord Deja",
["Chrono-Lord Epoch"] = "Chrono-Lord Epoch",
Claw = "Claw",
["Coilfang Elite"] = "Coilfang Elite",
["Coilfang Strider"] = "Coilfang Strider",
["Commander Kolurg"] = "Commander Kolurg",
["Commander Sarannis"] = "Commander Sarannis",
["Commander Springvale"] = "Commander Springvale",
["Commander Stoutbeard"] = "Commander Stoutbeard",
["Constructor & Controller"] = "Constructor & Controller",
Cookie = "Cookie",
["Coren Direbrew"] = "Coren Direbrew",
["Cosmic Infuser"] = "Cosmic Infuser",
["Crimson Hammersmith"] = "Crimson Hammersmith",
["Crowd Pummeler 9-60"] = "Crowd Pummeler 9-60",
["Crystal Fang"] = "Crystal Fang",
["C'Thun"] = "C'Thun",
Cyanigosa = "Cyanigosa",
["Dalliah the Doomsayer"] = "Dalliah the Doomsayer",
["Dalronn the Controller"] = "Dalronn the Controller",
["Dark Iron Ambassador"] = "Dark Iron Ambassador",
["Darkmaster Gandling"] = "Darkmaster Gandling",
["Darkweaver Syth"] = "Darkweaver Syth",
["Deathbound Ward"] = "Deathbound Ward",
["Deathbringer Saurfang"] = "Deathbringer Saurfang",
["Death Knight Darkreaver"] = "Death Knight Darkreaver",
["Death Knight Understudy"] = "Death Knight Understudy",
["Deathspeaker High Priest"] = "Deathspeaker High Priest",
["Death Speaker Jargba"] = "Death Speaker Jargba",
["Deathstalker Visceri"] = "Deathstalker Visceri",
["Deathsworn Captain"] = "Deathsworn Captain",
Devastation = "Devastation",
["Deviate Faerie Dragon"] = "Deviate Faerie Dragon",
["Devourer of Souls"] = "Devourer of Souls",
["Dextren Ward"] = "Dextren Ward",
["Digmaster Shovelphlange"] = "Digmaster Shovelphlange",
["Doctor Theolen Krastinov"] = "Doctor Theolen Krastinov",
["Doom Lord Kazzak"] = "Doom Lord Kazzak",
["Doom'rel"] = "Doom'rel",
Doomwalker = "Doomwalker",
["Dope'rel"] = "Dope'rel",
Dorothee = "Dorothee",
["Drakkari Colossus"] = "Drakkari Colossus",
["Drakos the Interrogator"] = "Drakos the Interrogator",
Dreadscale = "Dreadscale",
Dreamscythe = "Dreamscythe",
["Dust Covered Chest"] = "Dust Covered Chest",
Dustwraith = "Dustwraith",
["Eadric the Pure"] = "Eadric the Pure",
["Earthcaller Halmgar"] = "Earthcaller Halmgar",
Ebonroc = "Ebonroc",
["Eck the Ferocious"] = "Eck the Ferocious",
["Edwin VanCleef"] = "Edwin VanCleef",
["Elder Brightleaf"] = "Elder Brightleaf",
["Elder Ironbranch"] = "Elder Ironbranch",
["Elder Nadox"] = "Elder Nadox",
["Elder Stonebark"] = "Elder Stonebark",
["Electrocutioner 6000"] = "Electrocutioner 6000",
["Emalon the Storm Watcher"] = "Emalon the Storm Watcher",
Emeriss = "Emeriss",
["Emperor Dagran Thaurissan"] = "Emperor Dagran Thaurissan",
["Emperor Vek'lor"] = "Emperor Vek'lor",
["Emperor Vek'nilash"] = "Emperor Vek'nilash",
Entropius = "Entropius",
["Eonar's Gift"] = "Eonar's Gift",
["Epoch Hunter"] = "Epoch Hunter",
Erekem = "Erekem",
["Eressea Dawnsinger"] = "Eressea Dawnsinger",
["Essence of Anger"] = "Essence of Anger",
["Essence of Desire"] = "Essence of Desire",
["Essence of Suffering"] = "Essence of Suffering",
Eviscerator = "Eviscerator",
["Exarch Maladaar"] = "Exarch Maladaar",
["Expedition Commander"] = "Expedition Commander",
["Eydis Darkbane"] = "Eydis Darkbane",
["Eye of C'Thun"] = "Eye of C'Thun",
["Faction Champions"] = "Faction Champions",
["Fallen Champion"] = "Fallen Champion",
Falric = "Falric",
["Falric and Marwyn"] = "Falric and Marwyn",
["Fankriss the Unyielding"] = "Fankriss the Unyielding",
["Fathom-Lord Karathress"] = "Fathom-Lord Karathress",
Felmyst = "Felmyst",
["Fenrus the Devourer"] = "Fenrus the Devourer",
["Feral Defender"] = "Feral Defender",
Festergut = "Festergut",
Feugen = "Feugen",
["Fineous Darkvire"] = "Fineous Darkvire",
Firemaw = "Firemaw",
["Fjola Lightbane"] = "Fjola Lightbane",
Flamegor = "Flamegor",
["Flame Leviathan"] = "Flame Leviathan",
["Foreman Thistlenettle"] = "Foreman Thistlenettle",
["Forgemaster Garfrost"] = "Forgemaster Garfrost",
["Four Horsemen Chest"] = "Four Horsemen Chest",
["Fras Siabi"] = "Fras Siabi",
Freya = "Freya",
["Gahz'ranka"] = "Gahz'ranka",
["Gahz'rilla"] = "Gahz'rilla",
["Gal'darah"] = "Gal'darah",
["Galgann Firehammer"] = "Galgann Firehammer",
Garr = "Garr",
["Garrosh Hellscream"] = "Garrosh Hellscream",
Gasher = "Gasher",
["Gatewatcher Gyro-Kill"] = "Gatewatcher Gyro-Kill",
["Gatewatcher Iron-Hand"] = "Gatewatcher Iron-Hand",
["Gathios the Shatterer"] = "Gathios the Shatterer",
Gehennas = "Gehennas",
Gelihast = "Gelihast",
Gelk = "Gelk",
["General Angerforge"] = "General Angerforge",
["General Bjarngrim"] = "General Bjarngrim",
["General Drakkisath"] = "General Drakkisath",
["General Rajaxx"] = "General Rajaxx",
["General Vezax"] = "General Vezax",
["General Zarithrian"] = "General Zarithrian",
["Ghamoo-ra"] = "Ghamoo-ra",
["Ghaz'an"] = "Ghaz'an",
["Ghok Bashguud"] = "Ghok Bashguud",
Gilnid = "Gilnid",
["Gizrul the Slavener"] = "Gizrul the Slavener",
["Gloom'rel"] = "Gloom'rel",
Gluth = "Gluth",
Glutton = "Glutton",
["Golemagg the Incinerator"] = "Golemagg the Incinerator",
["Golem Lord Argelmach"] = "Golem Lord Argelmach",
["Goraluk Anvilcrack"] = "Goraluk Anvilcrack",
["Gormok the Impaler"] = "Gormok the Impaler",
["Gorosh the Dervish"] = "Gorosh the Dervish",
["Gortok Palehoof"] = "Gortok Palehoof",
["Gothik the Harvester"] = "Gothik the Harvester",
["Grand Astromancer Capernian"] = "Grand Astromancer Capernian",
["Grand Champions"] = "Grand Champions",
["Grand Magus Telestra"] = "Grand Magus Telestra",
["Grandmaster Vorpil"] = "Grandmaster Vorpil",
Grandmother = "Grandmother",
["Grand Warlock Alythess"] = "Grand Warlock Alythess",
["Grand Warlock Nethekurse"] = "Grand Warlock Nethekurse",
["Grand Widow Faerlina"] = "Grand Widow Faerlina",
["Grethok the Controller"] = "Grethok the Controller",
["Gri'lek"] = "Gri'lek",
Grimlok = "Grimlok",
Grizzle = "Grizzle",
Grobbulus = "Grobbulus",
Grubbis = "Grubbis",
["Gruul the Dragonkiller"] = "Gruul the Dragonkiller",
["Guard Fengus"] = "Guard Fengus",
["Guardian of Yogg-Saron"] = "Guardian of Yogg-Saron",
["Guard Mol'dar"] = "Guard Mol'dar",
["Guard Slip'kik"] = "Guard Slip'kik",
["Gurtogg Bloodboil"] = "Gurtogg Bloodboil",
Gyth = "Gyth",
Hadronox = "Hadronox",
Hakkar = "Hakkar",
Halazzi = "Halazzi",
Halion = "Halion",
Halycon = "Halycon",
Hamhock = "Hamhock",
["Harbinger Skyriss"] = "Harbinger Skyriss",
["Hate'rel"] = "Hate'rel",
["Hazza'rah"] = "Hazza'rah",
Hazzas = "Hazzas",
["Headless Horseman"] = "Headless Horseman",
["Hearthsinger Forresten"] = "Hearthsinger Forresten",
["Hedrum the Creeper"] = "Hedrum the Creeper",
["Heigan the Unclean"] = "Heigan the Unclean",
["Hellfire Channeler"] = "Hellfire Channeler",
["Henry Stern"] = "Henry Stern",
["Herald Volazj"] = "Herald Volazj",
Herod = "Herod",
["Hex Lord Malacrass"] = "Hex Lord Malacrass",
["High Astromancer Solarian"] = "High Astromancer Solarian",
["High Botanist Freywinn"] = "High Botanist Freywinn",
["High Inquisitor Fairbanks"] = "High Inquisitor Fairbanks",
["High Inquisitor Whitemane"] = "High Inquisitor Whitemane",
["High Interrogator Gerstahn"] = "High Interrogator Gerstahn",
["High King Maulgar"] = "High King Maulgar",
["Highlord Mograine"] = "Highlord Mograine",
["Highlord Omokk"] = "Highlord Omokk",
["High Marshal Whirlaxis"] = "High Marshal Whirlaxis",
["High Nethermancer Zerevor"] = "High Nethermancer Zerevor",
["High Overlord Saurfang"] = "High Overlord Saurfang",
["High Priestess Arlokk"] = "High Priestess Arlokk",
["High Priestess Jeklik"] = "High Priestess Jeklik",
["High Priestess Mar'li"] = "High Priestess Mar'li",
["High Priestess of Thaurissan"] = "High Priestess of Thaurissan",
["High Priest Thekal"] = "High Priest Thekal",
["High Priest Venoxis"] = "High Priest Venoxis",
["High Warlord Naj'entus"] = "High Warlord Naj'entus",
Hodir = "Hodir",
["Houndmaster Grebmar"] = "Houndmaster Grebmar",
["Houndmaster Loksey"] = "Houndmaster Loksey",
Hukku = "Hukku",
Hungarfen = "Hungarfen",
["Hurley Blackbreath"] = "Hurley Blackbreath",
["Hyakiss the Lurker"] = "Hyakiss the Lurker",
["Hydromancer Thespia"] = "Hydromancer Thespia",
["Hydromancer Velratha"] = "Hydromancer Velratha",
Hydrospawn = "Hydrospawn",
["Hydross the Unstable"] = "Hydross the Unstable",
["Icecrown Gunship Battle"] = "Icecrown Gunship Battle",
Icehowl = "Icehowl",
["Ice Sphere"] = "Ice Sphere",
Ichoron = "Ichoron",
Ick = "Ick",
["Ignis the Furnace Master"] = "Ignis the Furnace Master",
["Illidan Stormrage"] = "Illidan Stormrage",
["Illidari Council"] = "Illidari Council",
["Illyanna Ravenoak"] = "Illyanna Ravenoak",
["Immol'thar"] = "Immol'thar",
["Infinite Corruptor"] = "Infinite Corruptor",
["Infinity Blades"] = "Infinity Blades",
["Ingvar the Plunderer"] = "Ingvar the Plunderer",
["Instructor Malicia"] = "Instructor Malicia",
["Instructor Razuvious"] = "Instructor Razuvious",
["Interrogator Vishas"] = "Interrogator Vishas",
Ionar = "Ionar",
Ironaya = "Ironaya",
Ironspine = "Ironspine",
Isalien = "Isalien",
Jade = "Jade",
["Jammal'an the Prophet"] = "Jammal'an the Prophet",
["Jan'alai"] = "Jan'alai",
["Jandice Barov"] = "Jandice Barov",
["Jedoga Shadowseeker"] = "Jedoga Shadowseeker",
["Jed Runewatcher"] = "Jed Runewatcher",
["Jergosh the Invoker"] = "Jergosh the Invoker",
["Jin'do the Hexxer"] = "Jin'do the Hexxer",
["Jormungar Behemoth"] = "Jormungar Behemoth",
Jormungars = "Jormungars",
Julianne = "Julianne",
["Junk Bot"] = "Junk Bot",
["Kael'thas Sunstrider"] = "Kael'thas Sunstrider",
Kalecgos = "Kalecgos",
["Kam Deepfury"] = "Kam Deepfury",
["Kazkaz the Unholy"] = "Kazkaz the Unholy",
["Kaz'rogal"] = "Kaz'rogal",
["Keli'dan the Breaker"] = "Keli'dan the Breaker",
["Kel'Thuzad"] = "Kel'Thuzad",
Keristrasza = "Keristrasza",
["Kiggler the Crazed"] = "Kiggler the Crazed",
["Kil'jaeden"] = "Kil'jaeden",
["Kil'rek"] = "Kil'rek",
["King Dred"] = "King Dred",
["King Gordok"] = "King Gordok",
["King Llane Piece"] = "King Llane Piece",
["King Ymiron"] = "King Ymiron",
["Kirtonos the Herald"] = "Kirtonos the Herald",
["Knot Thimblejack's Cache"] = "Knot Thimblejack's Cache",
Kolk = "Kolk",
Kologarn = "Kologarn",
["Koralon the Flame Watcher"] = "Koralon the Flame Watcher",
Kormok = "Kormok",
Kresh = "Kresh",
Krick = "Krick",
["Krick and Ick"] = "Krick and Ick",
["Krik'thir the Gatewatcher"] = "Krik'thir the Gatewatcher",
["Krosh Firehand"] = "Krosh Firehand",
Krystallus = "Krystallus",
Kurinnaxx = "Kurinnaxx",
["Lady Anacondra"] = "Lady Anacondra",
["Lady Blaumeux"] = "Lady Blaumeux",
["Lady Deathwhisper"] = "Lady Deathwhisper",
["Lady Illucia Barov"] = "Lady Illucia Barov",
["Lady Malande"] = "Lady Malande",
["Lady Sacrolash"] = "Lady Sacrolash",
["Lady Sarevess"] = "Lady Sarevess",
["Lady Vashj"] = "Lady Vashj",
Laj = "Laj",
Landslide = "Landslide",
Lavanthor = "Lavanthor",
["Left Arm"] = "Left Arm",
["Leotheras the Blind"] = "Leotheras the Blind",
Lethon = "Lethon",
Lethtendris = "Lethtendris",
["Leviathan Mk II"] = "Leviathan Mk II",
["Ley-Guardian Eregos"] = "Ley-Guardian Eregos",
["Lieutenant Drake"] = "Lieutenant Drake",
["Lieutenant General Andorov"] = "Lieutenant General Andorov",
Loatheb = "Loatheb",
Loken = "Loken",
["Lord Alexei Barov"] = "Lord Alexei Barov",
["Lord Cobrahn"] = "Lord Cobrahn",
["Lord Hel'nurath"] = "Lord Hel'nurath",
["Lord Incendius"] = "Lord Incendius",
["Lord Jaraxxus"] = "Lord Jaraxxus",
["Lord Kazzak"] = "Lord Kazzak",
["Lord Kri"] = "Lord Kri",
["Lord Marrowgar"] = "Lord Marrowgar",
["Lord Pythas"] = "Lord Pythas",
["Lord Roccor"] = "Lord Roccor",
["Lord Sanguinar"] = "Lord Sanguinar",
["Lord Serpentis"] = "Lord Serpentis",
["Lord Skwol"] = "Lord Skwol",
["Lord Valthalak"] = "Lord Valthalak",
["Lord Victor Nefarius"] = "Lord Victor Nefarius",
["Lord Vyletongue"] = "Lord Vyletongue",
["Lorekeeper Polkelt"] = "Lorekeeper Polkelt",
Loro = "Loro",
Lucifron = "Lucifron",
["Mad Magglish"] = "Mad Magglish",
Maexxna = "Maexxna",
["Mage-Lord Urom"] = "Mage-Lord Urom",
["Magister Kalendris"] = "Magister Kalendris",
["Magistrate Barthilas"] = "Magistrate Barthilas",
Magmadar = "Magmadar",
Magmus = "Magmus",
Magra = "Magra",
Magtheridon = "Magtheridon",
["Maiden of Grief"] = "Maiden of Grief",
["Maiden of Virtue"] = "Maiden of Virtue",
["Majordomo Executus"] = "Majordomo Executus",
Malacrass = "Malacrass",
["Maleki the Pallid"] = "Maleki the Pallid",
["Mal'Ganis"] = "Mal'Ganis",
Malygos = "Malygos",
Maraudos = "Maraudos",
["Marduk Blackpool"] = "Marduk Blackpool",
["Marisa du'Paige"] = "Marisa du'Paige",
Marwyn = "Marwyn",
["Master Engineer Telonicus"] = "Master Engineer Telonicus",
["Maur Grimtotem"] = "Maur Grimtotem",
Meathook = "Meathook",
["Mechano-Lord Capacitus"] = "Mechano-Lord Capacitus",
Medivh = "Medivh",
["Mekgineer Steamrigger"] = "Mekgineer Steamrigger",
["Mekgineer Thermaplugg"] = "Mekgineer Thermaplugg",
["Mennu the Betrayer"] = "Mennu the Betrayer",
["Meshlok the Harvester"] = "Meshlok the Harvester",
Midnight = "Midnight",
Mijan = "Mijan",
Mimiron = "Mimiron",
["Miner Johnson"] = "Miner Johnson",
["Mistress of Pain"] = "Mistress of Pain",
Moam = "Moam",
Mogor = "Mogor",
["Mokra the Skullcrusher"] = "Mokra the Skullcrusher",
Moorabi = "Moorabi",
Moragg = "Moragg",
["Mordresh Fire Eye"] = "Mordresh Fire Eye",
["Mor Grayhoof"] = "Mor Grayhoof",
Moroes = "Moroes",
["Morogrim Tidewalker"] = "Morogrim Tidewalker",
Morphaz = "Morphaz",
["Mother Shahraz"] = "Mother Shahraz",
["Mother Smolderweb"] = "Mother Smolderweb",
["Mr. Smite"] = "Mr. Smite",
["Muradin Bronzebeard"] = "Muradin Bronzebeard",
["Murkblood Twin"] = "Murkblood Twin",
["Murkblood Twins"] = "Murkblood Twins",
Murmur = "Murmur",
["Murta Grimgut"] = "Murta Grimgut",
["M'uru"] = "M'uru",
Mushgog = "Mushgog",
["Mutanus the Devourer"] = "Mutanus the Devourer",
Nalorakk = "Nalorakk",
Nazan = "Nazan",
Nefarian = "Nefarian",
["Nekrum Gutchewer"] = "Nekrum Gutchewer",
["Nerub'enkan"] = "Nerub'enkan",
["Nethermancer Sepethrea"] = "Nethermancer Sepethrea",
Netherspite = "Netherspite",
["Netherstrand Longbow"] = "Netherstrand Longbow",
["Nexus-Prince Shaffar"] = "Nexus-Prince Shaffar",
Nightbane = "Nightbane",
["Noth the Plaguebringer"] = "Noth the Plaguebringer",
["Novos the Summoner"] = "Novos the Summoner",
Noxxion = "Noxxion",
["Obsidian Sentinel"] = "Obsidian Sentinel",
["Odo the Blindwatcher"] = "Odo the Blindwatcher",
["Ogom the Wretched"] = "Ogom the Wretched",
["Ok'thor the Breaker"] = "Ok'thor the Breaker",
["Old Serra'kis"] = "Old Serra'kis",
["Olm the Summoner"] = "Olm the Summoner",
["Omor the Unscarred"] = "Omor the Unscarred",
Onyxia = "Onyxia",
["Orgrim's Hammer"] = "Orgrim's Hammer",
["Ormorok the Tree-Shaper"] = "Ormorok the Tree-Shaper",
["Oro Eyegouge"] = "Oro Eyegouge",
["Ossirian the Unscarred"] = "Ossirian the Unscarred",
Ouro = "Ouro",
["Overlord Ramtusk"] = "Overlord Ramtusk",
["Overlord Wyrmthalak"] = "Overlord Wyrmthalak",
["Overmaster Pyron"] = "Overmaster Pyron",
["Overseer Tidewrath"] = "Overseer Tidewrath",
Pandemonius = "Pandemonius",
["Panzor the Invincible"] = "Panzor the Invincible",
Patchwerk = "Patchwerk",
["Pathaleon the Calculator"] = "Pathaleon the Calculator",
Phalanx = "Phalanx",
["Phaseshift Bulwark"] = "Phaseshift Bulwark",
Pimgib = "Pimgib",
["Plaguemaw the Rotting"] = "Plaguemaw the Rotting",
["Plugger Spazzring"] = "Plugger Spazzring",
["Postmaster Malown"] = "Postmaster Malown",
["Priestess Delrissa"] = "Priestess Delrissa",
["Prince Keleseth"] = "Prince Keleseth",
["Prince Malchezaar"] = "Prince Malchezaar",
["Prince Skaldrenox"] = "Prince Skaldrenox",
["Princess Huhuran"] = "Princess Huhuran",
["Princess Moira Bronzebeard"] = "Princess Moira Bronzebeard",
["Princess Tempestria"] = "Princess Tempestria",
["Princess Theradras"] = "Princess Theradras",
["Princess Yauj"] = "Princess Yauj",
["Prince Taldaram"] = "Prince Taldaram",
["Prince Tenris Mirkblood"] = "Prince Tenris Mirkblood",
["Prince Tortheldrin"] = "Prince Tortheldrin",
["Prince Valanar"] = "Prince Valanar",
["Professor Putricide"] = "Professor Putricide",
["Pure Spawn of Hydross"] = "Pure Spawn of Hydross",
Pusillin = "Pusillin",
["Pyroguard Emberseer"] = "Pyroguard Emberseer",
["Pyromancer Loregrain"] = "Pyromancer Loregrain",
Quagmirran = "Quagmirran",
["Quartermaster Zigris"] = "Quartermaster Zigris",
["Rage Winterchill"] = "Rage Winterchill",
Ragglesnout = "Ragglesnout",
["Raging Spirit"] = "Raging Spirit",
Ragnaros = "Ragnaros",
["Ramstein the Gorger"] = "Ramstein the Gorger",
["Ras Frostwhisper"] = "Ras Frostwhisper",
Rattlegore = "Rattlegore",
["Razorclaw the Butcher"] = "Razorclaw the Butcher",
["Razorgore the Untamed"] = "Razorgore the Untamed",
Razorlash = "Razorlash",
Razorscale = "Razorscale",
["Reliquary of Souls"] = "Reliquary of Souls",
Renataki = "Renataki",
["Restless Skeleton"] = "Restless Skeleton",
Rethilgore = "Rethilgore",
Revelosh = "Revelosh",
["Rhahk'Zor"] = "Rhahk'Zor",
["Ribbly Screwspigot"] = "Ribbly Screwspigot",
["Right Arm"] = "Right Arm",
Roar = "Roar",
["Rokad the Ravager"] = "Rokad the Ravager",
["Rokdar the Sundered Lord"] = "Rokdar the Sundered Lord",
["Rokmar the Crackler"] = "Rokmar the Crackler",
Romulo = "Romulo",
["Romulo & Julianne"] = "Romulo & Julianne",
Rotface = "Rotface",
Rotgrip = "Rotgrip",
["Runemaster Molgeim"] = "Runemaster Molgeim",
["Runok Wildmane"] = "Runok Wildmane",
Ruuzlu = "Ruuzlu",
["Salramm the Fleshcrafter"] = "Salramm the Fleshcrafter",
["Sanctum Sentry"] = "Sanctum Sentry",
["Sandarr Dunereaver"] = "Sandarr Dunereaver",
["Sandfury Executioner"] = "Sandfury Executioner",
Sapphiron = "Sapphiron",
Sara = "Sara",
["Saronite Animus"] = "Saronite Animus",
Sartharion = "Sartharion",
["Sathrovarr the Corruptor"] = "Sathrovarr the Corruptor",
["Saviana Ragefire"] = "Saviana Ragefire",
["Scarlet Commander Mograine"] = "Scarlet Commander Mograine",
["Scourgelord Tyrannus"] = "Scourgelord Tyrannus",
["Seeth'rel"] = "Seeth'rel",
["Selin Fireheart"] = "Selin Fireheart",
["Sergeant Bly"] = "Sergeant Bly",
["Shade of Akama"] = "Shade of Akama",
["Shade of Aran"] = "Shade of Aran",
["Shade of Eranikus"] = "Shade of Eranikus",
["Shadikith the Glider"] = "Shadikith the Glider",
["Shadow Hunter Vosh'gajin"] = "Shadow Hunter Vosh'gajin",
["Shadow of Leotheras"] = "Shadow of Leotheras",
["Shadowpriest Sezz'ziz"] = "Shadowpriest Sezz'ziz",
Shadron = "Shadron",
Shazzrah = "Shazzrah",
["Shirrak the Dead Watcher"] = "Shirrak the Dead Watcher",
Sindragosa = "Sindragosa",
["Sir Zeliek"] = "Sir Zeliek",
["Sjonnir The Ironshaper"] = "Sjonnir The Ironshaper",
["Skadi the Ruthless"] = "Skadi the Ruthless",
["Skarr the Unbreakable"] = "Skarr the Unbreakable",
["Skarvald the Constructor"] = "Skarvald the Constructor",
["Skra'gath"] = "Skra'gath",
Skul = "Skul",
Skum = "Skum",
["Slad'ran"] = "Slad'ran",
Sneed = "Sneed",
["Sneed's Shredder"] = "Sneed's Shredder",
["Solakar Flamewreath"] = "Solakar Flamewreath",
["Solarium Agent"] = "Solarium Agent",
["Solarium Priest"] = "Solarium Priest",
["Spirestone Battle Lord"] = "Spirestone Battle Lord",
["Spirestone Butcher"] = "Spirestone Butcher",
["Spirestone Lord Magus"] = "Spirestone Lord Magus",
["Staff of Disintegration"] = "Staff of Disintegration",
Stalagg = "Stalagg",
Steelbreaker = "Steelbreaker",
["Stomper Kreeg"] = "Stomper Kreeg",
Stonespine = "Stonespine",
["Stormcaller Brundir"] = "Stormcaller Brundir",
Strawman = "Strawman",
["Sulfuron Harbinger"] = "Sulfuron Harbinger",
Supremus = "Supremus",
["Svala Sorrowgrave"] = "Svala Sorrowgrave",
["Swamplord Musel'ek"] = "Swamplord Musel'ek",
Taerar = "Taerar",
["Tainted Spawn of Hydross"] = "Tainted Spawn of Hydross",
["Talon King Ikiss"] = "Talon King Ikiss",
["Taragaman the Hungerer"] = "Taragaman the Hungerer",
["Targorr the Dread"] = "Targorr the Dread",
Tavarok = "Tavarok",
Techbot = "Techbot",
Temporus = "Temporus",
["Tendris Warpwood"] = "Tendris Warpwood",
Tenebron = "Tenebron",
["Terestian Illhoof"] = "Terestian Illhoof",
["Teron Gorefiend"] = "Teron Gorefiend",
Thaddius = "Thaddius",
["Thaladred the Darkener"] = "Thaladred the Darkener",
["Thane Korth'azz"] = "Thane Korth'azz",
["The Beast"] = "The Beast",
["The Beasts of Northrend"] = "The Beasts of Northrend",
["The Big Bad Wolf"] = "The Big Bad Wolf",
["The Black Knight"] = "The Black Knight",
["The Black Stalker"] = "The Black Stalker",
["The Blue Brothers"] = "The Blue Brothers",
["The Bug Family"] = "The Bug Family",
["The Crone"] = "The Crone",
["The Curator"] = "The Curator",
["The Eredar Twins"] = "The Eredar Twins",
["The Four Horsemen"] = "The Four Horsemen",
["The Illidari Council"] = "The Illidari Council",
["The Iron Council"] = "The Iron Council",
["Theka the Martyr"] = "Theka the Martyr",
["The Lich King"] = "The Lich King",
["The Lurker Below"] = "The Lurker Below",
["The Maker"] = "The Maker",
["The Prophet Skeram"] = "The Prophet Skeram",
["The Prophet Tharon'ja"] = "The Prophet Tharon'ja",
["The Ravenian"] = "The Ravenian",
["The Razza"] = "The Razza",
["The Seven Dwarves"] = "The Seven Dwarves",
["The Skybreaker"] = "The Skybreaker",
["The Tribunal of Ages"] = "The Tribunal of Ages",
["The Twin Emperors"] = "The Twin Emperors",
["The Twin Val'kyr"] = "The Twin Val'kyr",
["The Unforgiven"] = "The Unforgiven",
["The Windreaver"] = "The Windreaver",
Thorim = "Thorim",
["Thorngrin the Tender"] = "Thorngrin the Tender",
["Tidewalker Lurker"] = "Tidewalker Lurker",
["Timmy the Cruel"] = "Timmy the Cruel",
Tinhead = "Tinhead",
["Tinkerer Gizlock"] = "Tinkerer Gizlock",
["Tirion Fordring"] = "Tirion Fordring",
Tito = "Tito",
["Toravon the Ice Watcher"] = "Toravon the Ice Watcher",
["Trigore the Lasher"] = "Trigore the Lasher",
Trollgore = "Trollgore",
["Tsu'zee"] = "Tsu'zee",
["Tuten'kash"] = "Tuten'kash",
["Twilight Lord Kelris"] = "Twilight Lord Kelris",
["Urok Doomhowl"] = "Urok Doomhowl",
["Vaelastrasz the Corrupt"] = "Vaelastrasz the Corrupt",
["Valithria Dreamwalker"] = "Valithria Dreamwalker",
["Val'kyr Shadowguard"] = "Val'kyr Shadowguard",
["Varian Wrynn"] = "Varian Wrynn",
["Varos Cloudstrider"] = "Varos Cloudstrider",
Vazruden = "Vazruden",
["Vazruden the Herald"] = "Vazruden the Herald",
Vectus = "Vectus",
Vem = "Vem",
Veng = "Veng",
["Veras Darkshadow"] = "Veras Darkshadow",
["Verdan the Everliving"] = "Verdan the Everliving",
Verek = "Verek",
Vesperon = "Vesperon",
Vexallus = "Vexallus",
["Veyzhak the Cannibal"] = "Veyzhak the Cannibal",
["Vile'rel"] = "Vile'rel",
Viscidus = "Viscidus",
["Viscous Fallout"] = "Viscous Fallout",
["Void Reaver"] = "Void Reaver",
Volkhan = "Volkhan",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "Warbringer O'mrogg",
["Warchief Blackhand Piece"] = "Warchief Blackhand Piece",
["Warchief Kargath Bladefist"] = "Warchief Kargath Bladefist",
["Warchief Rend Blackhand"] = "Warchief Rend Blackhand",
["Warden Mellichar"] = "Warden Mellichar",
["Warder Stilgiss"] = "Warder Stilgiss",
["Warlord Kalithresh"] = "Warlord Kalithresh",
["War Master Voone"] = "War Master Voone",
["Warmaul Champion"] = "Warmaul Champion",
["Warp Slicer"] = "Warp Slicer",
["Warp Splinter"] = "Warp Splinter",
["Watchkeeper Gargolmar"] = "Watchkeeper Gargolmar",
Weaver = "Weaver",
["Witch Doctor Zum'rah"] = "Witch Doctor Zum'rah",
["Wolf Master Nandos"] = "Wolf Master Nandos",
["Wrath-Scryer Soccothrates"] = "Wrath-Scryer Soccothrates",
Wushoolay = "Wushoolay",
Xevozz = "Xevozz",
["XT-002 Deconstructor"] = "XT-002 Deconstructor",
["Yogg-Saron"] = "Yogg-Saron",
Ysondre = "Ysondre",
Zekkis = "Zekkis",
["Zelemar the Wrathful"] = "Zelemar the Wrathful",
["Zereketh the Unbound"] = "Zereketh the Unbound",
Zerillis = "Zerillis",
["Zevrim Thornhoof"] = "Zevrim Thornhoof",
Zolo = "Zolo",
["Zul'Farrak Dead Hero"] = "Zul'Farrak Dead Hero",
["Zul'jin"] = "Zul'jin",
["Zul'Lor"] = "Zul'Lor",
["Zul'tore"] = "Zul'tore",
["Zuramat the Obliterator"] = "Zuramat the Obliterator",
}
 
 
if GAME_LOCALE == "enUS" then
lib:SetCurrentTranslations(true)
elseif GAME_LOCALE == "deDE" then
lib:SetCurrentTranslations {
Acidmaw = "Ätzschlund",
Aeonus = "Aeonus",
["Aerial Command Unit"] = "Luftkommandoeinheit",
["Agathelos the Raging"] = "Agathelos der Tobende",
Ahune = "Ahune",
["Akil'zon"] = "Akil'zon",
["Aku'mai"] = "Aku'mai",
["Al'ar"] = "Al'ar",
["Algalon the Observer"] = "Algalon der Beobachter",
["Alzzin the Wildshaper"] = "Alzzin der Wildformer",
Amanitar = "Amanitar",
["Ambassador Flamelash"] = "Botschafter Flammenschlag",
["Ambassador Hellmaw"] = "Botschafter Höllenschlund",
["Amnennar the Coldbringer"] = "Amnennar der Kältebringer",
["Ancient Stone Keeper"] = "Uralter Steinbewahrer",
Anetheron = "Anetheron",
["Anger'rel"] = "Anger'rel",
Anomalus = "Anomalus",
["Antu'sul"] = "Antu'sul",
["Anub'arak"] = "Anub'arak",
["Anubisath Defender"] = "Verteidiger des Anubisath",
["Anubisath Guardian"] = "Beschützer des Anubisath",
["Anub'Rekhan"] = "Anub'Rekhan",
["Anub'shiah"] = "Anub'shiah",
Anzu = "Anzu",
["Arcane Watchman"] = "Arkanwachmann",
["Arcanist Doan"] = "Arkanist Doan",
Archaedas = "Archaedas",
["Archavon the Stone Watcher"] = "Archavon der Steinwächter",
Archimonde = "Archimonde",
["Archivist Galford"] = "Archivar Galford",
["Archmage Arugal"] = "Erzmagier Arugal",
["Argent Confessor Paletress"] = "Argentumbeichtpatin Blondlocke",
["Arugal's Voidwalker"] = "Arugals Leerwandler",
["Assault Bot"] = "Angriffsbot",
["Atal'alarion"] = "Atal'alarion",
["Attumen the Huntsman"] = "Attumen der Jäger",
Auriaya = "Auriaya",
Avalanchion = "Avalanchion",
["Avatar of Hakkar"] = "Avatar von Hakkar",
["Ayamiss the Hunter"] = "Ayamiss der Jäger",
Azgalor = "Azgalor",
["Azshir the Sleepless"] = "Azshir der Schlaflose",
Azuregos = "Azuregos",
["Bael'Gar"] = "Bael'Gar",
Baelog = "Baelog",
Balnazzar = "Balnazzar",
["Baltharus the Warborn"] = "Baltharus der Kriegsjünger",
["Bannok Grimaxe"] = "Bannok Grimmaxt",
["Baron Aquanis"] = "Baron Aquanis",
["Baron Charr"] = "Baron Glutarr",
["Baroness Anastari"] = "Baroness Anastari",
["Baron Geddon"] = "Baron Geddon",
["Baron Kazum"] = "Baron Kazum",
["Baron Rivendare"] = "Baron Totenschwur",
["Baron Silverlaine"] = "Baron Silberlein",
["Battleguard Sartura"] = "Schlachtwache Sartura",
["Bazil Thredd"] = "Bazil Thredd",
Bazzalan = "Bazzalan",
["Black Guard Swordsmith"] = "Schwertschmied der schwarzen Wache",
["Blackheart the Inciter"] = "Schwarzherz der Hetzer",
["Blindeye the Seer"] = "Blindauge der Seher",
["Blind Hunter"] = "Blinder Jäger",
["Blood Guard Porung"] = "Blutwache Porung",
["Bloodlord Mandokir"] = "Blutfürst Mandokir",
["Bloodmage Thalnos"] = "Blutmagier Thalnos",
["Blood Prince Council"] = "Rat der Blutprinzen",
["Blood Princes"] = "Rat der Blutprinzen",
["Blood-Queen Lana'thel"] = "Blutkönigin Lana'thel",
["Blood Steward of Kirtonos"] = "Blutdiener von Kirtonos",
Boahn = "Boahn",
["Bomb Bot"] = "Bombenbot",
["Brain of Yogg-Saron"] = "Yogg-Sarons Gehirn",
["Brainwashed Noble"] = "Manipulierter Adliger",
Broggok = "Broggok",
Brokentoe = "Schmetterzehe",
Bronjahm = "Bronjahm",
["Broodlord Lashlayer"] = "Brutwächter Dreschbringer",
["Bruegal Ironknuckle"] = "Bruegal Eisenfaust",
Brutallus = "Brutallus",
["Burning Felguard"] = "Brennende Teufelswache",
["Buru the Gorger"] = "Buru der Verschlinger",
["Cache of the Firelord"] = "Truhe des Feuerlords",
["Cannon Master Willey"] = "Kanonenmeister Willey",
["Captain Greenskin"] = "Kapitän Grünhaut",
["Captain Kromcrush"] = "Hauptmann Krombruch",
["Captain Skarloc"] = "Kapitän Skarloc",
["Celebras the Cursed"] = "Celebras der Verfluchte",
["Charlga Razorflank"] = "Charlga Klingenflanke",
["Chess Event"] = "Chess Event",
["Chest of The Seven"] = "Truhe der Sieben",
["Chief Ukorz Sandscalp"] = "Häuptling Ukorz Sandwüter",
["Cho'Rush the Observer"] = "Cho'Rush der Beobachter",
Chromaggus = "Chromaggus",
["Chrono Lord Deja"] = "Chronolord Deja",
["Chrono-Lord Epoch"] = "Chronolord Epoch",
Claw = "Klaue",
["Coilfang Elite"] = "Elitesoldat des Echsenkessels",
["Coilfang Strider"] = "Schreiter des Echsenkessels",
["Commander Kolurg"] = "Kommandant Kolurg",
["Commander Sarannis"] = "Kommandant Sarannis",
["Commander Springvale"] = "Kommandant Springvale",
["Commander Stoutbeard"] = "Kommandant Starkbart",
["Constructor & Controller"] = "Konstrukteur & Kontrolleur",
Cookie = "Krümel",
["Coren Direbrew"] = "Coren Düsterbräu",
["Cosmic Infuser"] = "Kosmische Macht",
["Crimson Hammersmith"] = "Purpurroter Hammerschmied",
["Crowd Pummeler 9-60"] = "Meuteverprügler 9-60",
["Crystal Fang"] = "Kristallfangzahn",
["C'Thun"] = "C'Thun",
Cyanigosa = "Cyanigosa",
["Dalliah the Doomsayer"] = "Dalliah die Verdammnisverkünderin",
["Dalronn the Controller"] = "Dalronn der Kontrolleur",
["Dark Iron Ambassador"] = "Botschafter der Dunkeleisenzwerge",
["Darkmaster Gandling"] = "Dunkelmeister Gandling",
["Darkweaver Syth"] = "Dunkelwirker Syth",
["Deathbound Ward"] = "Todesgeweihter Wächter",
["Deathbringer Saurfang"] = "Todesbringer Saurfang",
["Death Knight Darkreaver"] = "Todesritter Schattensichel",
["Death Knight Understudy"] = "Reservist der Todesritter",
["Deathspeaker High Priest"] = "Hohepriester der Todessprecher",
["Death Speaker Jargba"] = "Todessprecher Jargba",
["Deathstalker Visceri"] = "Todespirscher Visceri",
["Deathsworn Captain"] = "Todeshöriger Captain",
Devastation = "Verwüstung",
["Deviate Faerie Dragon"] = "Deviatfeendrache",
["Devourer of Souls"] = "Verschlinger der Seelen",
["Dextren Ward"] = "Dextren Ward",
["Digmaster Shovelphlange"] = "Grubenmeister Schaufelphlansch",
["Doctor Theolen Krastinov"] = "Doktor Theolen Krastinov",
["Doom Lord Kazzak"] = "Verdammnislord Kazzak",
["Doom'rel"] = "Un'rel",
Doomwalker = "Verdammniswandler",
["Dope'rel"] = "Trott'rel",
Dorothee = "Dorothee",
["Drakkari Colossus"] = "Koloss der Drakkari",
["Drakos the Interrogator"] = "Drakos der Befrager",
Dreadscale = "Schreckensmaul",
Dreamscythe = "Traumsense",
["Dust Covered Chest"] = "Staub Bedeckter Kasten",
Dustwraith = "Karaburan",
["Eadric the Pure"] = "Eadric der Reine",
["Earthcaller Halmgar"] = "Erdenrufer Halmgar",
Ebonroc = "Schattenschwinge",
["Eck the Ferocious"] = "Der wilde Eck",
["Edwin VanCleef"] = "Edwin van Cleef",
["Elder Brightleaf"] = "Ältester Hellblatt",
["Elder Ironbranch"] = "Ältester Eisenast",
["Elder Nadox"] = "Urahne Nadox",
["Elder Stonebark"] = "Ältester Steinrinde",
["Electrocutioner 6000"] = "Elektrokutor 6000",
["Emalon the Storm Watcher"] = "Emalon der Sturmwächter",
Emeriss = "Smariss",
["Emperor Dagran Thaurissan"] = "Imperator Dagran Thaurissan",
["Emperor Vek'lor"] = "Imperator Vek'lor",
["Emperor Vek'nilash"] = "Imperator Vek'nilash",
Entropius = "Entropius",
["Eonar's Gift"] = "Eonars Geschenk",
["Epoch Hunter"] = "Epochenjäger",
Erekem = "Erekem",
["Eressea Dawnsinger"] = "Eressea Morgensänger",
["Essence of Anger"] = "Essenz des Zorns",
["Essence of Desire"] = "Essenz der Begierde",
["Essence of Suffering"] = "Essenz des Leidens",
Eviscerator = "Ausweider",
["Exarch Maladaar"] = "Exarch Maladaar",
["Expedition Commander"] = "Kommandant der Expedition",
["Eydis Darkbane"] = "Eydis Nachtbann",
["Eye of C'Thun"] = "Auge von C'Thun",
["Faction Champions"] = "Fraktionschampions",
["Fallen Champion"] = "Gestürzter Held",
Falric = "Falric",
["Falric and Marwyn"] = "Falric und Marwyn",
["Fankriss the Unyielding"] = "Fankriss der Unnachgiebige",
["Fathom-Lord Karathress"] = "Tiefenlord Karathress",
Felmyst = "Teufelsruch",
["Fenrus the Devourer"] = "Fenrus der Verschlinger",
["Feral Defender"] = "Wilder Verteidiger",
Festergut = "Fauldarm",
Feugen = "Feugen",
["Fineous Darkvire"] = "Fineous Dunkelader",
Firemaw = "Feuerschwinge",
["Fjola Lightbane"] = "Fjola Lichtbann",
Flamegor = "Flammenmaul",
["Flame Leviathan"] = "Flammenleviathan",
["Foreman Thistlenettle"] = "Großknecht Distelklette",
["Forgemaster Garfrost"] = "Schmiedenmeister Garfrost",
["Four Horsemen Chest"] = "Die Vier Reiter Kiste",
["Fras Siabi"] = "Fras Siabi",
Freya = "Freya",
["Gahz'ranka"] = "Gahz'ranka",
["Gahz'rilla"] = "Gahz'rilla",
["Gal'darah"] = "Gal'darah",
["Galgann Firehammer"] = "Galgann Feuerhammer",
Garr = "Garr",
["Garrosh Hellscream"] = "Garrosh Höllschrei",
Gasher = "Schlitzer",
["Gatewatcher Gyro-Kill"] = "Torwächter Gyrotot",
["Gatewatcher Iron-Hand"] = "Torwächter Eisenhand",
["Gathios the Shatterer"] = "Gathios der Zerschmetterer",
Gehennas = "Gehennas",
Gelihast = "Gelihast",
Gelk = "Gelk",
["General Angerforge"] = "General Zornesschmied",
["General Bjarngrim"] = "General Bjarngrim",
["General Drakkisath"] = "General Drakkisath",
["General Rajaxx"] = "General Rajaxx",
["General Vezax"] = "General Vezax",
["General Zarithrian"] = "General Zarithrian",
["Ghamoo-ra"] = "Ghamoo-ra",
["Ghaz'an"] = "Ghaz'an",
["Ghok Bashguud"] = "Ghok Haudrauf",
Gilnid = "Gilnid",
["Gizrul the Slavener"] = "Gizrul der Geifernde",
["Gloom'rel"] = "Dunk'rel",
Gluth = "Gluth",
Glutton = "Nimmersatt",
["Golemagg the Incinerator"] = "Golemagg der Verbrenner",
["Golem Lord Argelmach"] = "Golemlord Argelmach",
["Goraluk Anvilcrack"] = "Goraluk Hammerbruch",
["Gormok the Impaler"] = "Gormok der Pfähler",
["Gorosh the Dervish"] = "Gorosh der Derwisch",
["Gortok Palehoof"] = "Gortok Bleichhuf",
["Gothik the Harvester"] = "Gothik der Ernter",
["Grand Astromancer Capernian"] = "Großastronom Capernian",
["Grand Champions"] = "Großchampions",
["Grand Magus Telestra"] = "Großmagistrix Telestra",
["Grandmaster Vorpil"] = "Großmeister Vorpil",
Grandmother = "Großmutter",
["Grand Warlock Alythess"] = "Großhexenmeisterin Alythess",
["Grand Warlock Nethekurse"] = "Großhexenmeister Nethekurse",
["Grand Widow Faerlina"] = "Großwitwe Faerlina",
["Grethok the Controller"] = "Grethok der Aufseher",
["Gri'lek"] = "Gri'lek",
Grimlok = "Grimlok",
Grizzle = "Grizzle",
Grobbulus = "Grobbulus",
Grubbis = "Grubbis",
["Gruul the Dragonkiller"] = "Gruul der Drachenschlächter",
["Guard Fengus"] = "Wache Fengus",
["Guardian of Yogg-Saron"] = "Wächter des Yogg-Saron",
["Guard Mol'dar"] = "Wache Mol'dar",
["Guard Slip'kik"] = "Wache Slip'kik",
["Gurtogg Bloodboil"] = "Gurtogg Siedeblut",
Gyth = "Gyth",
Hadronox = "Hadronox",
Hakkar = "Hakkar",
Halazzi = "Halazzi",
Halion = "Halion",
Halycon = "Halycon",
Hamhock = "Hamhock",
["Harbinger Skyriss"] = "Herold Horizontiss",
["Hate'rel"] = "Hass'rel",
["Hazza'rah"] = "Hazza'rah",
Hazzas = "Hazzas",
["Headless Horseman"] = "Der kopflose Reiter",
["Hearthsinger Forresten"] = "Herdsinger Forresten",
["Hedrum the Creeper"] = "Hedrum der Krabbler",
["Heigan the Unclean"] = "Heigan der Unreine",
["Hellfire Channeler"] = "Kanalisierer des Höllenfeuers",
["Henry Stern"] = "Henry Stern",
["Herald Volazj"] = "Verkünder Volazj",
Herod = "Herod",
["Hex Lord Malacrass"] = "Hexlord Malacrass",
["High Astromancer Solarian"] = "Hochastromantin Solarian",
["High Botanist Freywinn"] = "Hochbotaniker Freywinn",
["High Inquisitor Fairbanks"] = "Hochinquisitor Fairbanks",
["High Inquisitor Whitemane"] = "Hochinquisitor Weißsträhne",
["High Interrogator Gerstahn"] = "Verhörmeisterin Gerstahn",
["High King Maulgar"] = "Hochkönig Maulgar",
["Highlord Mograine"] = "Hochlord Mograine",
["Highlord Omokk"] = "Hochlord Omokk",
["High Marshal Whirlaxis"] = "Hochmarschall Whirlaxis",
["High Nethermancer Zerevor"] = "Hochnethermant Zerevor",
["High Overlord Saurfang"] = "Hochfürst Saurfang",
["High Priestess Arlokk"] = "Hohepriesterin Arlokk",
["High Priestess Jeklik"] = "Hohepriesterin Jeklik",
["High Priestess Mar'li"] = "Hohepriesterin Mar'li",
["High Priestess of Thaurissan"] = "\009Hohepriesterin von Thaurissan",
["High Priest Thekal"] = "Hohepriester Thekal",
["High Priest Venoxis"] = "Hohepriester Venoxis",
["High Warlord Naj'entus"] = "Oberster Kriegsfürst Naj'entus",
Hodir = "Hodir",
["Houndmaster Grebmar"] = "Hundemeister Grebmar",
["Houndmaster Loksey"] = "Hundemeister Loksey",
Hukku = "Hukku",
Hungarfen = "Hungarfenn",
["Hurley Blackbreath"] = "Hurley Pestatem",
["Hyakiss the Lurker"] = "Hyakiss der Lauerer",
["Hydromancer Thespia"] = "Wasserbeschwörerin Thespia",
["Hydromancer Velratha"] = "Wasserbeschwörerin Velratha",
Hydrospawn = "Hydrobrut",
["Hydross the Unstable"] = "Hydross der Unstete",
["Icecrown Gunship Battle"] = "Luftschlacht um die Eiskronenzitadelle",
Icehowl = "Eisheuler",
["Ice Sphere"] = "Eissphäre",
Ichoron = "Ichoron",
Ick = "Ick",
["Ignis the Furnace Master"] = "Ignis, Meister des Eisenwerks",
["Illidan Stormrage"] = "Illidan Sturmgrimm",
["Illidari Council"] = "Rat der Illidari",
["Illyanna Ravenoak"] = "Illyanna Rabeneiche",
["Immol'thar"] = "Immol'thar",
["Infinite Corruptor"] = "Ewiger Verderber",
["Infinity Blades"] = "Klinge der Unendlichkeit",
["Ingvar the Plunderer"] = "Ingvar der Brandschatzer",
["Instructor Malicia"] = "Instrukteurin Malicia",
["Instructor Razuvious"] = "Instrukteur Razuvious",
["Interrogator Vishas"] = "Befrager Vishas",
Ionar = "Ionar",
Ironaya = "Ironaya",
Ironspine = "Eisenrücken",
Isalien = "Isalien",
Jade = "Jade",
["Jammal'an the Prophet"] = "Jammal'an der Prophet",
["Jan'alai"] = "Jan'alai",
["Jandice Barov"] = "Jandice Barov",
["Jedoga Shadowseeker"] = "Jedoga Schattensucher",
["Jed Runewatcher"] = "Jed Runenblick",
["Jergosh the Invoker"] = "Jergosh der Herbeirufer",
["Jin'do the Hexxer"] = "Jin'do der Verhexer",
["Jormungar Behemoth"] = "Jormungarungetüm",
Jormungars = "Jormungars",
Julianne = "Julianne",
["Junk Bot"] = "Schrottbot",
["Kael'thas Sunstrider"] = "Kael'thas Sonnenwanderer",
Kalecgos = "Kalecgos",
["Kam Deepfury"] = "Kam Tiefenzorn",
["Kazkaz the Unholy"] = "Kazkaz der Unheilige",
["Kaz'rogal"] = "Kaz'rogal",
["Keli'dan the Breaker"] = "Keli'dan der Zerstörer",
["Kel'Thuzad"] = "Kel'Thuzad",
Keristrasza = "Keristrasza",
["Kiggler the Crazed"] = "Kiggler the Crazed",
["Kil'jaeden"] = "Kil'jaeden",
["Kil'rek"] = "Kil'rek",
["King Dred"] = "König Dred",
["King Gordok"] = "König Gordok",
["King Llane Piece"] = "König Llane",
["King Ymiron"] = "König Ymiron",
["Kirtonos the Herald"] = "Kirtonos der Herold",
["Knot Thimblejack's Cache"] = "Knot Thimblejacks Truhe",
Kolk = "Kolk",
Kologarn = "Kologarn",
["Koralon the Flame Watcher"] = "Koralon der Flammenwächter",
Kormok = "Kormok",
Kresh = "Kresh",
Krick = "Krick",
["Krick and Ick"] = "Krick und Ick",
["Krik'thir the Gatewatcher"] = "Krik'thir der Torwächter",
["Krosh Firehand"] = "Krosh Feuerhand",
Krystallus = "Krystallus",
Kurinnaxx = "Kurinnaxx",
["Lady Anacondra"] = "Lady Anacondra",
["Lady Blaumeux"] = "Lady Blaumeux",
["Lady Deathwhisper"] = "Lady Todeswisper",
["Lady Illucia Barov"] = "Lady Illucia Barov",
["Lady Malande"] = "Lady Malande",
["Lady Sacrolash"] = "Lady Sacrolash",
["Lady Sarevess"] = "Lady Sarevess",
["Lady Vashj"] = "Lady Vashj",
Laj = "Laj",
Landslide = "Erdrutsch",
Lavanthor = "Lavanthor",
["Left Arm"] = "Linker Arm",
["Leotheras the Blind"] = "Leotheras der Blinde",
Lethon = "Lethon",
Lethtendris = "Lethtendris",
["Leviathan Mk II"] = "Leviathan Mk II",
["Ley-Guardian Eregos"] = "Leywächter Eregos",
["Lieutenant Drake"] = "Leutnant Drach",
["Lieutenant General Andorov"] = "Generallieutenant Andorov",
Loatheb = "Loatheb",
Loken = "Loken",
["Lord Alexei Barov"] = "Lord Alexei Barov",
["Lord Cobrahn"] = "Lord Kobrahn",
["Lord Hel'nurath"] = "Lord Hel'nurath",
["Lord Incendius"] = "Lord Incendius",
["Lord Jaraxxus"] = "Lord Jaraxxus",
["Lord Kazzak"] = "Lord Kazzak",
["Lord Kri"] = "Lord Kri",
["Lord Marrowgar"] = "Lord Mark'gar",
["Lord Pythas"] = "Lord Pythas",
["Lord Roccor"] = "Lord Roccor",
["Lord Sanguinar"] = "Fürst Blutdurst",
["Lord Serpentis"] = "Lord Serpentis",
["Lord Skwol"] = "Lord Skwol",
["Lord Valthalak"] = "Lord Valthalak",
["Lord Victor Nefarius"] = "Lord Victor Nefarius",
["Lord Vyletongue"] = "Lord Schlangenzunge",
["Lorekeeper Polkelt"] = "Hüter des Wissens Polkelt",
Loro = "Loro",
Lucifron = "Lucifron",
["Mad Magglish"] = "Zausel der Verrückte",
Maexxna = "Maexxna",
["Mage-Lord Urom"] = "Magierlord Urom",
["Magister Kalendris"] = "Magister Kalendris",
["Magistrate Barthilas"] = "Magistrat Barthilas",
Magmadar = "Magmadar",
Magmus = "Magmus",
Magra = "Magra",
Magtheridon = "Magtheridon",
["Maiden of Grief"] = "Maid der Trauer",
["Maiden of Virtue"] = "Tugendhafte Maid",
["Majordomo Executus"] = "Majordomus Exekutus",
Malacrass = "Malacrass",
["Maleki the Pallid"] = "Maleki der Leichenblasse",
["Mal'Ganis"] = "Mal'Ganis",
Malygos = "Malygos",
Maraudos = "Maraudos",
["Marduk Blackpool"] = "Marduk Blackpool",
["Marisa du'Paige"] = "Marisa du'Paige",
Marwyn = "Marwyn",
["Master Engineer Telonicus"] = "Meisteringenieur Telonicus",
["Maur Grimtotem"] = "Maur Grimmtotem",
Meathook = "Fleischhaken",
["Mechano-Lord Capacitus"] = "Mechanolord Kapazitus",
Medivh = "Medivh",
["Mekgineer Steamrigger"] = "Robogenieur Dampfhammer",
["Mekgineer Thermaplugg"] = "Robogenieur Thermadraht",
["Mennu the Betrayer"] = "Mennu der Verräter",
["Meshlok the Harvester"] = "Meshlok der Ernter",
Midnight = "Mittnacht",
Mijan = "Mijan",
Mimiron = "Mimiron",
["Miner Johnson"] = "Minenarbeiter Johnson",
["Mistress of Pain"] = "Herrin der Schmerzen",
Moam = "Moam",
Mogor = "Mogor",
["Mokra the Skullcrusher"] = "Mokra der Schädelberster",
Moorabi = "Moorabi",
Moragg = "Moragg",
["Mordresh Fire Eye"] = "Mordresh Feuerauge",
["Mor Grayhoof"] = "Mor Grauhuf",
Moroes = "Moroes",
["Morogrim Tidewalker"] = "Morogrim Gezeitenwandler",
Morphaz = "Morphaz",
["Mother Shahraz"] = "Mutter Shahraz",
["Mother Smolderweb"] = "Mutter Glimmernetz",
["Mr. Smite"] = "Handlanger Pein",
["Muradin Bronzebeard"] = "Muradin Bronzebart",
["Murkblood Twin"] = "Zwilling der Finsterblut",
["Murkblood Twins"] = "Zwillinge der Finsterblut",
Murmur = "Murmur",
["Murta Grimgut"] = "Murta Bauchgrimm",
["M'uru"] = "M'uru",
Mushgog = "Mushgog",
["Mutanus the Devourer"] = "Mutanus der Verschlinger",
Nalorakk = "Nalorakk",
Nazan = "Nazan",
Nefarian = "Nefarian",
["Nekrum Gutchewer"] = "Nekrum der Ausweider",
["Nerub'enkan"] = "Nerub'enkan",
["Nethermancer Sepethrea"] = "Nethermant Sepethrea",
Netherspite = "Nethergroll",
["Netherstrand Longbow"] = "Netherbespannter Langbogen",
["Nexus-Prince Shaffar"] = "Nexusprinz Shaffar",
Nightbane = "Schrecken der Nacht",
["Noth the Plaguebringer"] = "Noth der Seuchenfürst",
["Novos the Summoner"] = "Novos der Beschwörer",
Noxxion = "Noxxion",
["Obsidian Sentinel"] = "Obsidianschildwache",
["Odo the Blindwatcher"] = "Odo der Blindseher",
["Ogom the Wretched"] = "Ogom der Elende",
["Ok'thor the Breaker"] = "Ok'thor der Zerstörer",
["Old Serra'kis"] = "Old Serra'kis",
["Olm the Summoner"] = "Olm der Beschwörer",
["Omor the Unscarred"] = "Omor der Narbenlose",
Onyxia = "Onyxia",
["Orgrim's Hammer"] = "Orgrims Hammer",
["Ormorok the Tree-Shaper"] = "Ormorok der Baumformer",
["Oro Eyegouge"] = "Oro Hohlauge",
["Ossirian the Unscarred"] = "Ossirian der Narbenlose",
Ouro = "Ouro",
["Overlord Ramtusk"] = "Oberanführer Rammhauer",
["Overlord Wyrmthalak"] = "Oberanführer Wyrmthalak",
["Overmaster Pyron"] = "Übermeister Pyron",
["Overseer Tidewrath"] = "Overseer Tidewrath",
Pandemonius = "Pandemonius",
["Panzor the Invincible"] = "Panzor der Unbesiegbare",
Patchwerk = "Flickwerk",
["Pathaleon the Calculator"] = "Pathaleon der Kalkulator",
Phalanx = "Phalanx",
["Phaseshift Bulwark"] = "Phasenverschobenes Bollwerk",
Pimgib = "Pimgib",
["Plaguemaw the Rotting"] = "Seuchenschlund der Faulende",
["Plugger Spazzring"] = "Stöpsel Zapfring",
["Postmaster Malown"] = "Postmeister Malown",
["Priestess Delrissa"] = "Priesterin Delrissa",
["Prince Keleseth"] = "Prinz Keleseth",
["Prince Malchezaar"] = "Prinz Malchezaar",
["Prince Skaldrenox"] = "Prince Skaldrenox",
["Princess Huhuran"] = "Prinzessin Huhuran",
["Princess Moira Bronzebeard"] = "Prinzessin Moira Bronzebeard",
["Princess Tempestria"] = "Prinzessin Tempestria",
["Princess Theradras"] = "Prinzessin Theradras",
["Princess Yauj"] = "Prinzessin Yauj",
["Prince Taldaram"] = "Prinz Taldaram",
["Prince Tenris Mirkblood"] = "Prinz Tenris Mirkblut",
["Prince Tortheldrin"] = "Prinz Tortheldrin",
["Prince Valanar"] = "Prinz Valanar",
["Professor Putricide"] = "Professor Seuchenmord",
["Pure Spawn of Hydross"] = "Gereinigter Nachkomme Hydross'",
Pusillin = "Pusillin",
["Pyroguard Emberseer"] = "Feuerwache Glutseher",
["Pyromancer Loregrain"] = "Pyromant Weisenkorn",
Quagmirran = "Quagmirran",
["Quartermaster Zigris"] = "Rüstmeister Zigris",
["Rage Winterchill"] = "Furor Winterfrost",
Ragglesnout = "Struppmähne",
["Raging Spirit"] = "Tobender Geist",
Ragnaros = "Ragnaros",
["Ramstein the Gorger"] = "Ramstein der Verschlinger",
["Ras Frostwhisper"] = "Ras Frostraunen",
Rattlegore = "Blutrippe",
["Razorclaw the Butcher"] = "Klingenklaue der Metzger",
["Razorgore the Untamed"] = "Razorgore der Ungezähmte",
Razorlash = "Schlingwurzler",
Razorscale = "Klingenschuppe",
["Reliquary of Souls"] = "Reliquium der Seelen",
Renataki = "Renataki",
["Restless Skeleton"] = "Ruheloses Skelett",
Rethilgore = "Rotkralle",
Revelosh = "Revelosh",
["Rhahk'Zor"] = "Rhahk'Zor",
["Ribbly Screwspigot"] = "Ribbly Schraubstutz",
["Right Arm"] = "Rechter Arm",
Roar = "Brüller",
["Rokad the Ravager"] = "Rokad der Verheerer",
["Rokdar the Sundered Lord"] = "Rokdar der Zerklüftete",
["Rokmar the Crackler"] = "Rokmar der Zerquetscher",
Romulo = "Romulo",
["Romulo & Julianne"] = "Romulo & Julianne",
Rotface = "Modermiene",
Rotgrip = "Faulschnapper",
["Runemaster Molgeim"] = "Runenmeister Molgeim",
["Runok Wildmane"] = "Runok Wildmähne",
Ruuzlu = "Ruuzlu",
["Salramm the Fleshcrafter"] = "Salramm der Fleischformer",
["Sanctum Sentry"] = "Späher des Sanktums",
["Sandarr Dunereaver"] = "Sandarr der Wüstenräuber",
["Sandfury Executioner"] = "Henker der Sandwüter",
Sapphiron = "Saphiron",
Sara = "Sara",
["Saronite Animus"] = "Saronitanimus",
Sartharion = "Sartharion",
["Sathrovarr the Corruptor"] = "Sathrovarr der Verderber",
["Saviana Ragefire"] = "Saviana Flammenschlund",
["Scarlet Commander Mograine"] = "Scharlachroter Kommandant Mograine",
["Scourgelord Tyrannus"] = "Geißelfürst Tyrannus",
["Seeth'rel"] = "Wut'rel",
["Selin Fireheart"] = "Selin Feuerherz",
["Sergeant Bly"] = "Unteroffizier Bly",
["Shade of Akama"] = "Akamas Schemen",
["Shade of Aran"] = "Arans Schemen",
["Shade of Eranikus"] = "Eranikus' Schemen",
["Shadikith the Glider"] = "Shadikith der Segler",
["Shadow Hunter Vosh'gajin"] = "Schattenjägerin Vosh'gajin",
["Shadow of Leotheras"] = "Schatten von Leotheras",
["Shadowpriest Sezz'ziz"] = "Schattenpriester Sezz'ziz",
Shadron = "Shadron",
Shazzrah = "Shazzrah",
["Shirrak the Dead Watcher"] = "Shirrak der Totenwächter",
Sindragosa = "Sindragosa",
["Sir Zeliek"] = "Sir Zeliek",
["Sjonnir The Ironshaper"] = "Sjonnir der Eisenformer",
["Skadi the Ruthless"] = "Skadi der Skrupellose",
["Skarr the Unbreakable"] = "Skarr der Unbezwingbare",
["Skarvald the Constructor"] = "Skarvald der Konstrukteur",
["Skra'gath"] = "Skra'gath",
Skul = "Skul",
Skum = "Skum",
["Slad'ran"] = "Slad'ran",
Sneed = "Sneed",
["Sneed's Shredder"] = "Sneeds Schredder",
["Solakar Flamewreath"] = "Solakar Feuerkrone",
["Solarium Agent"] = "Solarian Agent",
["Solarium Priest"] = "Solarian Priester",
["Spirestone Battle Lord"] = "Kampflord der Felsspitzoger",
["Spirestone Butcher"] = "Metzger der Felsspitzoger",
["Spirestone Lord Magus"] = "Maguslord der Felsspitzoger",
["Staff of Disintegration"] = "Stab der Auflösung",
Stalagg = "Stalagg",
Steelbreaker = "Stahlbrecher",
["Stomper Kreeg"] = "Stampfer Kreeg",
Stonespine = "Steinbuckel",
["Stormcaller Brundir"] = "Sturmrufer Brundir",
Strawman = "Strohmann",
["Sulfuron Harbinger"] = "Sulfuronherold",
Supremus = "Supremus",
["Svala Sorrowgrave"] = "Svala Grabesleid",
["Swamplord Musel'ek"] = "Sumpffürst Musel'ek",
Taerar = "Taerar",
["Tainted Spawn of Hydross"] = "Besudelter Nachkomme Hydross'",
["Talon King Ikiss"] = "Klauenkönig Ikiss",
["Taragaman the Hungerer"] = "Taragaman der Hungerleider",
["Targorr the Dread"] = "Targorr der Schreckliche",
Tavarok = "Tavarok",
Techbot = "Techbot",
Temporus = "Temporus",
["Tendris Warpwood"] = "Tendris Wucherborke",
Tenebron = "Tenebron",
["Terestian Illhoof"] = "Terestian Siechhuf",
["Teron Gorefiend"] = "Teron Blutschatten",
Thaddius = "Thaddius",
["Thaladred the Darkener"] = "Thaladred der Verfinsterer",
["Thane Korth'azz"] = "Than Korth'azz",
["The Beast"] = "Die Bestie",
["The Beasts of Northrend"] = "Bestien von Nordend",
["The Big Bad Wolf"] = "Der große böse Wolf",
["The Black Knight"] = "Der Schwarze Ritter",
["The Black Stalker"] = "Die Schattenmutter",
["The Blue Brothers"] = "Die Blaumänner",
["The Bug Family"] = "Die Käferfamilie",
["The Crone"] = "Die böse Hexe",
["The Curator"] = "Der Kurator",
["The Eredar Twins"] = "Die Eredar Zwillinge",
["The Four Horsemen"] = "Die Vier Reiter",
["The Illidari Council"] = "Rat der Illidari",
["The Iron Council"] = "Rat der Eisernen",
["Theka the Martyr"] = "Theka der Märtyrer",
["The Lich King"] = "Der Lichkönig",
["The Lurker Below"] = "Das Grauen aus der Tiefe",
["The Maker"] = "Der Schöpfer",
["The Prophet Skeram"] = "Der Prophet Skeram",
["The Prophet Tharon'ja"] = "Der Prophet Tharon'ja",
["The Ravenian"] = "Der Ravenier",
["The Razza"] = "Der Razza",
["The Seven Dwarves"] = "Die Sieben Zwerge",
["The Skybreaker"] = "Die Himmelsbrecher",
["The Tribunal of Ages"] = "Das Tribunal der Zeitalter",
["The Twin Emperors"] = "Die Zwillings-Imperatoren",
["The Twin Val'kyr"] = "Zwillingsval'kyr",
["The Unforgiven"] = "Der Unverziehene",
["The Windreaver"] = "Der Windhäscher",
Thorim = "Thorim",
["Thorngrin the Tender"] = "Dorngrin der Hüter",
["Tidewalker Lurker"] = "Lauerer der Gezeitenwandler",
["Timmy the Cruel"] = "Timmy der Grausame",
Tinhead = "Blechkopf",
["Tinkerer Gizlock"] = "Tüftler Gizlock",
["Tirion Fordring"] = "Tirion Fordring",
Tito = "Tito",
["Toravon the Ice Watcher"] = "Toravon der Eiswächter",
["Trigore the Lasher"] = "Trigore der Peitscher",
Trollgore = "Trollgrind",
["Tsu'zee"] = "Tsu'zee",
["Tuten'kash"] = "Tuten'kash",
["Twilight Lord Kelris"] = "Lord des Schattenhammers Kelris",
["Urok Doomhowl"] = "Urok Schreckensbote",
["Vaelastrasz the Corrupt"] = "Vaelastrasz der Verdorbene",
["Valithria Dreamwalker"] = "Valithria Traumwandler",
["Val'kyr Shadowguard"] = "Schattenwächterin der Val'kyr",
["Varian Wrynn"] = "Varian Wrynn",
["Varos Cloudstrider"] = "Varos Wolkenschreiter",
Vazruden = "Vazruden",
["Vazruden the Herald"] = "Vazruden der Herold",
Vectus = "Vectus",
Vem = "Vem",
Veng = "Veng",
["Veras Darkshadow"] = "Veras Schwarzschatten",
["Verdan the Everliving"] = "Verdan der Ewiglebende",
Verek = "Verek",
Vesperon = "Vesperon",
Vexallus = "Vexallus",
["Veyzhak the Cannibal"] = "Veyzhack der Kannibale",
["Vile'rel"] = "Bös'rel",
Viscidus = "Viscidus",
["Viscous Fallout"] = "Verflüssigte Ablagerung",
["Void Reaver"] = "Leerhäscher",
Volkhan = "Volkhan",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "Kriegshetzer O'mrogg",
["Warchief Blackhand Piece"] = "Kriegshäuptling Schwarzfaust",
["Warchief Kargath Bladefist"] = "Kriegshäuptling Kargath Messerfaust",
["Warchief Rend Blackhand"] = "Kriegshäuptling Rend Schwarzfaust",
["Warden Mellichar"] = "Aufseher Mellichar",
["Warder Stilgiss"] = "Wärter Stilgiss",
["Warlord Kalithresh"] = "Kriegsherr Kalithresh",
["War Master Voone"] = "Kriegsmeister Voone",
["Warmaul Champion"] = "Champion der Totschläger",
["Warp Slicer"] = "Warpschnitter",
["Warp Splinter"] = "Warpzweig",
["Watchkeeper Gargolmar"] = "Wachhabender Gargolmar",
Weaver = "Wirker",
["Witch Doctor Zum'rah"] = "Hexendoktor Zum'rah",
["Wolf Master Nandos"] = "Wolfmeister Nados",
["Wrath-Scryer Soccothrates"] = "Zornseher Soccothrates",
Wushoolay = "Wushoolay",
Xevozz = "Xevozz",
["XT-002 Deconstructor"] = "XT-002 Dekonstruktor",
["Yogg-Saron"] = "Yogg-Saron",
Ysondre = "Ysondre",
Zekkis = "Zekkis",
["Zelemar the Wrathful"] = "Zelemar der Hasserfüllte",
["Zereketh the Unbound"] = "Zereketh der Unabhängige",
Zerillis = "Zerillis",
["Zevrim Thornhoof"] = "Zevrim Dornhuf",
Zolo = "Zolo",
["Zul'Farrak Dead Hero"] = "Untoter Held aus Zul'Farrak",
["Zul'jin"] = "Zul'jin",
["Zul'Lor"] = "Zul'Lor",
["Zul'tore"] = "Zul'tore",
["Zuramat the Obliterator"] = "Zuramat der Auslöscher",
}
elseif GAME_LOCALE == "frFR" then
lib:SetCurrentTranslations {
Acidmaw = "Gueule-d'acide",
Aeonus = "Aeonus",
["Aerial Command Unit"] = "Unité de commandement aérien",
["Agathelos the Raging"] = "Agathelos le Déchaîné",
Ahune = "Ahune",
["Akil'zon"] = "Akil'zon",
["Aku'mai"] = "Aku'mai",
["Al'ar"] = "Al'ar",
["Algalon the Observer"] = "Algalon l'Observateur",
["Alzzin the Wildshaper"] = "Alzzin le Modeleur",
Amanitar = "Amanitar",
["Ambassador Flamelash"] = "Ambassadeur Cinglefouet",
["Ambassador Hellmaw"] = "Ambassadeur Gueule-d'enfer",
["Amnennar the Coldbringer"] = "Amnennar le Porte-froid",
["Ancient Stone Keeper"] = "Ancien Gardien des pierres",
Anetheron = "Anetheron",
["Anger'rel"] = "Colé'rel",
Anomalus = "Anomalus",
["Antu'sul"] = "Antu'sul",
["Anub'arak"] = "Anub'arak",
["Anubisath Defender"] = "Défenseur Anubisath",
["Anubisath Guardian"] = "Gardien Anubisath",
["Anub'Rekhan"] = "Anub'Rekhan",
["Anub'shiah"] = "Anub'shiah",
Anzu = "Anzu",
["Arcane Watchman"] = "Veilleur arcanique",
["Arcanist Doan"] = "Arcaniste Doan",
Archaedas = "Archaedas",
["Archavon the Stone Watcher"] = "Archavon le Gardien des pierres",
Archimonde = "Archimonde",
["Archivist Galford"] = "Archiviste Galford",
["Archmage Arugal"] = "Archimage Arugal",
["Argent Confessor Paletress"] = "Confesseur d'argent Paletress",
["Arugal's Voidwalker"] = "Marcheur du Vide d'Arugal",
["Assault Bot"] = "Robot d'assaut",
["Atal'alarion"] = "Atal'alarion",
["Attumen the Huntsman"] = "Attumen le Veneur",
Auriaya = "Auriaya",
Avalanchion = "Avalanchion",
["Avatar of Hakkar"] = "Avatar d'Hakkar",
["Ayamiss the Hunter"] = "Ayamiss le Chasseur",
Azgalor = "Azgalor",
["Azshir the Sleepless"] = "Azshir le Sans-sommeil",
Azuregos = "Azuregos",
["Bael'Gar"] = "Bael'Gar",
Baelog = "Baelog",
Balnazzar = "Balnazzar",
["Baltharus the Warborn"] = "Baltharus l'Enfant de la guerre",
["Bannok Grimaxe"] = "Bannok Hache-sinistre",
["Baron Aquanis"] = "Baron Aquanis",
["Baron Charr"] = "Baron Charr",
["Baroness Anastari"] = "Baronne Anastari",
["Baron Geddon"] = "Baron Geddon",
["Baron Kazum"] = "Baron Kazum",
["Baron Rivendare"] = "Baron Vaillefendre",
["Baron Silverlaine"] = "Baron d'Argelaine",
["Battleguard Sartura"] = "Garde de guerre Sartura",
["Bazil Thredd"] = "Bazil Thredd",
Bazzalan = "Bazzalan",
["Black Guard Swordsmith"] = "Fabricant d'épées de la Garde noire",
["Blackheart the Inciter"] = "Coeur-noir le Séditieux",
["Blindeye the Seer"] = "Oeillaveugle le Voyant",
["Blind Hunter"] = "Chasseur aveugle",
["Blood Guard Porung"] = "Garde de sang Porung",
["Bloodlord Mandokir"] = "Seigneur sanglant Mandokir",
["Bloodmage Thalnos"] = "Mage de sang Thalnos",
["Blood Prince Council"] = "Conseil des princes de sang",
["Blood Princes"] = "Princes de sang",
["Blood-Queen Lana'thel"] = "Reine de sang Lana'thel",
["Blood Steward of Kirtonos"] = "Régisseuse sanglante de Kirtonos",
Boahn = "Boahn",
["Bomb Bot"] = "Robo-bombe",
["Brain of Yogg-Saron"] = "Cerveau de Yogg-Saron",
["Brainwashed Noble"] = "Noble manipulé",
Broggok = "Broggok",
Brokentoe = "Brisorteil",
Bronjahm = "Bronjahm",
["Broodlord Lashlayer"] = "Seigneur des couvées Lanistaire",
["Bruegal Ironknuckle"] = "Bruegal Poing-de-fer",
Brutallus = "Brutallus",
["Burning Felguard"] = "Gangregarde ardent",
["Buru the Gorger"] = "Buru Grandgosier",
["Cache of the Firelord"] = "Cachette du Seigneur du feu",
["Cannon Master Willey"] = "Maître canonnier Willey",
["Captain Greenskin"] = "Capitaine Vertepeau",
["Captain Kromcrush"] = "Capitaine Kromcrush",
["Captain Skarloc"] = "Capitaine Skarloc",
["Celebras the Cursed"] = "Celebras le Maudit",
["Charlga Razorflank"] = "Charlga Trancheflanc",
["Chess Event"] = "Partie d'échec",
["Chest of The Seven"] = "Coffre des sept",
["Chief Ukorz Sandscalp"] = "Chef Ukorz Scalpessable",
["Cho'Rush the Observer"] = "Cho'Rush l'Observateur",
Chromaggus = "Chromaggus",
["Chrono Lord Deja"] = "Chronoseigneur Déjà",
["Chrono-Lord Epoch"] = "Chronoseigneur Epoch",
Claw = "Griffe",
["Coilfang Elite"] = "Elite de Glissecroc",
["Coilfang Strider"] = "Trotteur de Glissecroc",
["Commander Kolurg"] = "Commandant Kolurg",
["Commander Sarannis"] = "Commandant Sarannis",
["Commander Springvale"] = "Commandant Springvale",
["Commander Stoutbeard"] = "Commandant Rudebarbe",
["Constructor & Controller"] = "Constructeur & Contrôleur",
Cookie = "Macaron",
["Coren Direbrew"] = "Coren Navrebière",
["Cosmic Infuser"] = "Masse d'infusion cosmique",
["Crimson Hammersmith"] = "Forgeur de marteaux cramoisi",
["Crowd Pummeler 9-60"] = "Faucheur de foule 9-60",
["Crystal Fang"] = "Croc cristallin",
["C'Thun"] = "C'Thun",
Cyanigosa = "Cyanigosa",
["Dalliah the Doomsayer"] = "Dalliah l'Auspice-funeste",
["Dalronn the Controller"] = "Dalronn le Contrôleur",
["Dark Iron Ambassador"] = "Ambassadeur Sombrefer",
["Darkmaster Gandling"] = "Sombre Maître Gandling",
["Darkweaver Syth"] = "Tisseur d'ombre Syth",
["Deathbound Ward"] = "Gardien lié par la mort",
["Deathbringer Saurfang"] = "Porte-mort Saurcroc",
["Death Knight Darkreaver"] = "Chevalier de la mort Ravassombre",
["Death Knight Understudy"] = "Doublure de chevalier de la mort",
["Deathspeaker High Priest"] = "Grand prêtre nécrorateur",
["Death Speaker Jargba"] = "Nécrorateur Jargba",
["Deathstalker Visceri"] = "Nécrotraqueur Viscéri",
["Deathsworn Captain"] = "Capitaine Ligemort",
Devastation = "Dévastation",
["Deviate Faerie Dragon"] = "Dragon féérique déviant",
["Devourer of Souls"] = "Dévoreur d’âmes",
["Dextren Ward"] = "Dextren Ward",
["Digmaster Shovelphlange"] = "Maître des fouilles Pellaphlange",
["Doctor Theolen Krastinov"] = "Docteur Theolen Krastinov",
["Doom Lord Kazzak"] = "Seigneur funeste Kazzak",
["Doom'rel"] = "Tragi'rel",
Doomwalker = "Marche-funeste",
["Dope'rel"] = "Demeu'rel",
Dorothee = "Dorothée",
["Drakkari Colossus"] = "Colosse drakkari",
["Drakos the Interrogator"] = "Drakos l'Interrogateur",
Dreadscale = "Écaille-d'effroi",
Dreamscythe = "Fauche-rêve",
["Dust Covered Chest"] = "Coffre couvert de poussière",
Dustwraith = "Ame en peine poudreuse",
["Eadric the Pure"] = "Eadric le Pur",
["Earthcaller Halmgar"] = "Implorateur de la terre Halmgar",
Ebonroc = "Rochébène",
["Eck the Ferocious"] = "Eck le Féroce",
["Edwin VanCleef"] = "Edwin VanCleef",
["Elder Brightleaf"] = "Ancien Brillefeuille",
["Elder Ironbranch"] = "Ancien Branchefer",
["Elder Nadox"] = "Ancien Nadox",
["Elder Stonebark"] = "Ancien Ecorcepierre",
["Electrocutioner 6000"] = "Electrocuteur 6000",
["Emalon the Storm Watcher"] = "Emalon le Guetteur d'orage",
Emeriss = "Emeriss",
["Emperor Dagran Thaurissan"] = "Empereur Dagran Thaurissan",
["Emperor Vek'lor"] = "Empereur Vek'lor",
["Emperor Vek'nilash"] = "Empereur Vek'nilash",
Entropius = "Entropius",
["Eonar's Gift"] = "Cadeau d'Eonar",
["Epoch Hunter"] = "Chasseur d'époques",
Erekem = "Erekem",
["Eressea Dawnsinger"] = "Eressa Chantelaube",
["Essence of Anger"] = "Essence de la colère",
["Essence of Desire"] = "Essence du désir",
["Essence of Suffering"] = "Essence de la souffrance",
Eviscerator = "Eviscérateur",
["Exarch Maladaar"] = "Exarque Maladaar",
["Expedition Commander"] = "Commandant de l'expédition",
["Eydis Darkbane"] = "Eydis Plaie-sombre",
["Eye of C'Thun"] = "Œil de C'Thun",
["Faction Champions"] = "Champions de faction",
["Fallen Champion"] = "Champion mort",
Falric = "Falric",
["Falric and Marwyn"] = "Falric et Marwyn",
["Fankriss the Unyielding"] = "Fankriss l'Inflexible",
["Fathom-Lord Karathress"] = "Seigneur des fonds Karathress",
Felmyst = "Gangrebrume",
["Fenrus the Devourer"] = "Fenrus le Dévoreur",
["Feral Defender"] = "Défenseur farouche",
Festergut = "Pulentraille",
Feugen = "Feugen",
["Fineous Darkvire"] = "Fineous Sombrevire",
Firemaw = "Gueule-de-feu",
["Fjola Lightbane"] = "Fjola Plaie-lumineuse",
Flamegor = "Flamegor",
["Flame Leviathan"] = "Léviathan des flammes",
["Foreman Thistlenettle"] = "Contremaître Crispechardon",
["Forgemaster Garfrost"] = "Maître-forge Gargivre",
["Four Horsemen Chest"] = "Coffre des quatre cavaliers",
["Fras Siabi"] = "Fras Siabi",
Freya = "Freya",
["Gahz'ranka"] = "Gahz'ranka",
["Gahz'rilla"] = "Gahz'rilla",
["Gal'darah"] = "Gal'darah",
["Galgann Firehammer"] = "Galgann Martel-de-feu",
Garr = "Garr",
["Garrosh Hellscream"] = "Garrosh Hurlenfer",
Gasher = "Gasher",
["Gatewatcher Gyro-Kill"] = "Gardien de porte Gyro-Meurtre",
["Gatewatcher Iron-Hand"] = "Gardien de porte Main-en-fer",
["Gathios the Shatterer"] = "Gathios le Briseur",
Gehennas = "Gehennas",
Gelihast = "Gelihast",
Gelk = "Gelk",
["General Angerforge"] = "Général Forgehargne",
["General Bjarngrim"] = "Général Bjarngrim",
["General Drakkisath"] = "Général Drakkisath",
["General Rajaxx"] = "Général Rajaxx",
["General Vezax"] = "Général Vezax",
["General Zarithrian"] = "Général Zarithrian",
["Ghamoo-ra"] = "Ghamoo-ra",
["Ghaz'an"] = "Ghaz'an",
["Ghok Bashguud"] = "Ghok Bounnebaffe",
Gilnid = "Gilnid",
["Gizrul the Slavener"] = "Gizrul l'esclavagiste",
["Gloom'rel"] = "Funéb'rel",
Gluth = "Gluth",
Glutton = "Glouton",
["Golemagg the Incinerator"] = "Golemagg l'Incinérateur",
["Golem Lord Argelmach"] = "Seigneur golem Argelmach",
["Goraluk Anvilcrack"] = "Goraluk Brisenclume",
["Gormok the Impaler"] = "Gormok l'Empaleur",
["Gorosh the Dervish"] = "Gorosh le Derviche",
["Gortok Palehoof"] = "Gortok Pâle-sabot",
["Gothik the Harvester"] = "Gothik le Moissonneur",
["Grand Astromancer Capernian"] = "Grande astromancienne Capernian",
["Grand Champions"] = "Grand champions",
["Grand Magus Telestra"] = "Grand magus Telestra",
["Grandmaster Vorpil"] = "Grand Maître Vorpil",
Grandmother = "Mère-grand",
["Grand Warlock Alythess"] = "Grande démoniste Alythess",
["Grand Warlock Nethekurse"] = "Grand démoniste Néanathème",
["Grand Widow Faerlina"] = "Grande veuve Faerlina",
["Grethok the Controller"] = "Grethok le Contrôleur",
["Gri'lek"] = "Gri'lek",
Grimlok = "Grimlok",
Grizzle = "Grison",
Grobbulus = "Grobbulus",
Grubbis = "Grubbis",
["Gruul the Dragonkiller"] = "Gruul le Tue-dragon",
["Guard Fengus"] = "Garde Fengus",
["Guardian of Yogg-Saron"] = "Gardien de Yogg-Saron",
["Guard Mol'dar"] = "Garde Mol'dar",
["Guard Slip'kik"] = "Garde Slip'kik",
["Gurtogg Bloodboil"] = "Gurtogg Fièvresang",
Gyth = "Gyth",
Hadronox = "Hadronox",
Hakkar = "Hakkar",
Halazzi = "Halazzi",
Halion = "Halion",
Halycon = "Halycon",
Hamhock = "Hamhock",
["Harbinger Skyriss"] = "Messager Cieuriss",
["Hate'rel"] = "Haine'rel",
["Hazza'rah"] = "Hazza'rah",
Hazzas = "Hazzas",
["Headless Horseman"] = "Cavalier sans tête",
["Hearthsinger Forresten"] = "Chanteloge Forrestin",
["Hedrum the Creeper"] = "Hedrum le Rampant",
["Heigan the Unclean"] = "Heigan l'Impur",
["Hellfire Channeler"] = "Canaliste des Flammes infernales",
["Henry Stern"] = "Henry Stern",
["Herald Volazj"] = "Héraut Volazj",
Herod = "Hérode",
["Hex Lord Malacrass"] = "Seigneur des maléfices Malacrass",
["High Astromancer Solarian"] = "Grande astromancienne Solarian",
["High Botanist Freywinn"] = "Grand botaniste Freywinn",
["High Inquisitor Fairbanks"] = "Grand Inquisiteur Fairbanks",
["High Inquisitor Whitemane"] = "Grand Inquisiteur Blanchetête",
["High Interrogator Gerstahn"] = "Grand Interrogateur Gerstahn",
["High King Maulgar"] = "Haut Roi Maulgar",
["Highlord Mograine"] = "Généralissime Mograine",
["Highlord Omokk"] = "Généralissime Omokk",
["High Marshal Whirlaxis"] = "Haut maréchal Trombe",
["High Nethermancer Zerevor"] = "Grand néantomancien Zerevor",
["High Overlord Saurfang"] = "Haut seigneur Saurcroc",
["High Priestess Arlokk"] = "Grande prêtresse Arlokk",
["High Priestess Jeklik"] = "Grande prêtresse Jeklik",
["High Priestess Mar'li"] = "Grande prêtresse Mar'li",
["High Priestess of Thaurissan"] = "Grande prêtresse de Thaurissan",
["High Priest Thekal"] = "Grand prêtre Thekal",
["High Priest Venoxis"] = "Grand prêtre Venoxis",
["High Warlord Naj'entus"] = "Grand seigneur de guerre Naj'entus",
Hodir = "Hodir",
["Houndmaster Grebmar"] = "Maître-chien Grebmar",
["Houndmaster Loksey"] = "Maître-chien Loksey",
Hukku = "Hukku",
Hungarfen = "Hungarfen",
["Hurley Blackbreath"] = "Hurley Soufflenoir",
["Hyakiss the Lurker"] = "Hyakiss le rôdeur",
["Hydromancer Thespia"] = "Hydromancienne Thespia",
["Hydromancer Velratha"] = "Hydromancienne Velratha",
Hydrospawn = "Hydrogénos",
["Hydross the Unstable"] = "Hydross l'Instable",
["Icecrown Gunship Battle"] = "Bataille des canonnières",
Icehowl = "Glace-hurlante",
["Ice Sphere"] = "Sphère de glace",
Ichoron = "Ichoron",
Ick = "Ick",
["Ignis the Furnace Master"] = "Ignis le maître de la Fournaise",
["Illidan Stormrage"] = "Illidan Hurlorage",
["Illidari Council"] = "Conseil illidari",
["Illyanna Ravenoak"] = "Illyanna Corvichêne",
["Immol'thar"] = "Immol'thar",
["Infinite Corruptor"] = "Corrupteur infini",
["Infinity Blades"] = "Lames d'infinité",
["Ingvar the Plunderer"] = "Ingvar le Pilleur",
["Instructor Malicia"] = "Instructeur Malicia",
["Instructor Razuvious"] = "Instructeur Razuvious",
["Interrogator Vishas"] = "Interrogateur Vishas",
Ionar = "Ionar",
Ironaya = "Ironaya",
Ironspine = "Echine-de-fer",
Isalien = "Isalien",
Jade = "Jade",
["Jammal'an the Prophet"] = "Jammal'an le prophète",
["Jan'alai"] = "Jan'alai",
["Jandice Barov"] = "Jandice Barov",
["Jedoga Shadowseeker"] = "Jedoga Cherchelombre",
["Jed Runewatcher"] = "Jed Guette-runes",
["Jergosh the Invoker"] = "Jergosh l'Invocateur",
["Jin'do the Hexxer"] = "Jin'do le Maléficieur",
["Jormungar Behemoth"] = "Béhémoth jormungar",
Jormungars = "Jormungars",
Julianne = "Julianne",
["Junk Bot"] = "Robot camelote",
["Kael'thas Sunstrider"] = "Kael'thas Haut-soleil",
Kalecgos = "Kalecgos",
["Kam Deepfury"] = "Kam Furie-du-fond",
["Kazkaz the Unholy"] = "Kazkaz l'Impie",
["Kaz'rogal"] = "Kaz'rogal",
["Keli'dan the Breaker"] = "Keli'dan le Briseur",
["Kel'Thuzad"] = "Kel'Thuzad",
Keristrasza = "Keristrasza",
["Kiggler the Crazed"] = "Kiggler le Cinglé",
["Kil'jaeden"] = "Kil'jaeden",
["Kil'rek"] = "Kil'rek",
["King Dred"] = "Roi Dred",
["King Gordok"] = "Roi Gordok",
["King Llane Piece"] = "Pion du Roi Llane",
["King Ymiron"] = "Roi Ymiron",
["Kirtonos the Herald"] = "Kirtonos le Héraut",
["Knot Thimblejack's Cache"] = "Réserve de Noué Dédodevie",
Kolk = "Kolk",
Kologarn = "Kologarn",
["Koralon the Flame Watcher"] = "Koralon le Veilleur des flammes",
Kormok = "Kormok",
Kresh = "Kresh",
Krick = "Krick",
["Krick and Ick"] = "Krick et Ick",
["Krik'thir the Gatewatcher"] = "Krik'thir le Gardien de porte",
["Krosh Firehand"] = "Krosh Brasemain",
Krystallus = "Krystallus",
Kurinnaxx = "Kurinnaxx",
["Lady Anacondra"] = "Dame Anacondra",
["Lady Blaumeux"] = "Dame Blaumeux",
["Lady Deathwhisper"] = "Dame Murmemort",
["Lady Illucia Barov"] = "Dame Illucia Barov",
["Lady Malande"] = "Dame Malande",
["Lady Sacrolash"] = "Dame Sacrocingle",
["Lady Sarevess"] = "Dame Sarevess",
["Lady Vashj"] = "Dame Vashj",
Laj = "Laj",
Landslide = "Glissement de terrain",
Lavanthor = "Lavanthor",
["Left Arm"] = "Bras gauche",
["Leotheras the Blind"] = "Leotheras l'Aveugle",
Lethon = "Léthon",
Lethtendris = "Lethtendris",
["Leviathan Mk II"] = "Léviathan Mod. II",
["Ley-Guardian Eregos"] = "Gardien-tellurique Eregos",
["Lieutenant Drake"] = "Lieutenant Drake",
["Lieutenant General Andorov"] = "Général de division Andorov",
Loatheb = "Horreb",
Loken = "Loken",
["Lord Alexei Barov"] = "Seigneur Alexei Barov",
["Lord Cobrahn"] = "Seigneur Cobrahn",
["Lord Hel'nurath"] = "Seigneur Hel'nurath",
["Lord Incendius"] = "Seigneur Incendius",
["Lord Jaraxxus"] = "Seigneur Jaraxxus",
["Lord Kazzak"] = "Seigneur Kazzak",
["Lord Kri"] = "Seigneur Kri",
["Lord Marrowgar"] = "Seigneur Gargamoelle",
["Lord Pythas"] = "Seigneur Pythas",
["Lord Roccor"] = "Seigneur Roccor",
["Lord Sanguinar"] = "Seigneur Sanguinar",
["Lord Serpentis"] = "Seigneur Serpentis",
["Lord Skwol"] = "Seigneur Skwol",
["Lord Valthalak"] = "Seigneur Valthalak",
["Lord Victor Nefarius"] = "Seigneur Victor Nefarius",
["Lord Vyletongue"] = "Seigneur Vylelangue",
["Lorekeeper Polkelt"] = "Gardien du savoir Polkelt",
Loro = "Loro",
Lucifron = "Lucifron",
["Mad Magglish"] = "Magglish le Dingue",
Maexxna = "Maexxna",
["Mage-Lord Urom"] = "Seigneur-mage Urom",
["Magister Kalendris"] = "Magistère Kalendris",
["Magistrate Barthilas"] = "Magistrat Barthilas",
Magmadar = "Magmadar",
Magmus = "Magmus",
Magra = "Magra",
Magtheridon = "Magtheridon",
["Maiden of Grief"] = "Damoiselle de peine",
["Maiden of Virtue"] = "Damoiselle de vertu",
["Majordomo Executus"] = "Chambellan Executus",
Malacrass = "Malacrass",
["Maleki the Pallid"] = "Maleki le Blafard",
["Mal'Ganis"] = "Mal'Ganis",
Malygos = "Malygos",
Maraudos = "Maraudos",
["Marduk Blackpool"] = "Marduk Noirétang",
["Marisa du'Paige"] = "Marisa du'Paige",
Marwyn = "Marwyn",
["Master Engineer Telonicus"] = "Maître ingénieur Telonicus",
["Maur Grimtotem"] = "Maur Totem-sinistre",
Meathook = "Grancrochet",
["Mechano-Lord Capacitus"] = "Mécano-seigneur Capacitus",
Medivh = "Medivh",
["Mekgineer Steamrigger"] = "Mékgénieur Montevapeur",
["Mekgineer Thermaplugg"] = "Mekgénieur Thermojoncteur",
["Mennu the Betrayer"] = "Mennu le Traître",
["Meshlok the Harvester"] = "Meshlok le Moissonneur",
Midnight = "Minuit",
Mijan = "Mijan",
Mimiron = "Mimiron",
["Miner Johnson"] = "Mineur Johnson",
["Mistress of Pain"] = "Maîtresse de Douleur",
Moam = "Moam",
Mogor = "Mogor",
["Mokra the Skullcrusher"] = "Mokra le Brise-tête",
Moorabi = "Moorabi",
Moragg = "Moragg",
["Mordresh Fire Eye"] = "Mordresh Oeil-de-feu",
["Mor Grayhoof"] = "Mor Sabot-gris",
Moroes = "Moroes",
["Morogrim Tidewalker"] = "Morogrim Marcheur-des-flots",
Morphaz = "Morphaz",
["Mother Shahraz"] = "Mère Shahraz",
["Mother Smolderweb"] = "Matriarche Couveuse",
["Mr. Smite"] = "M. Châtiment",
["Muradin Bronzebeard"] = "Muradin Barbe-de-bronze",
["Murkblood Twin"] = "Jumeau bourbesang",
["Murkblood Twins"] = "Jumeaux bourbesang",
Murmur = "Marmon",
["Murta Grimgut"] = "Murta Mornentraille",
["M'uru"] = "M'uru",
Mushgog = "Mushgog",
["Mutanus the Devourer"] = "Mutanus le Dévoreur",
Nalorakk = "Nalorakk",
Nazan = "Nazan",
Nefarian = "Nefarian",
["Nekrum Gutchewer"] = "Nekrum Mâchetripes",
["Nerub'enkan"] = "Nerub'enkan",
["Nethermancer Sepethrea"] = "Néantomancien Sepethrea",
Netherspite = "Dédain-du-Néant",
["Netherstrand Longbow"] = "Arc long brins-de-Néant",
["Nexus-Prince Shaffar"] = "Prince-nexus Shaffar",
Nightbane = "Plaie-de-nuit",
["Noth the Plaguebringer"] = "Noth le Porte-peste",
["Novos the Summoner"] = "Novos l'Invocateur",
Noxxion = "Noxcion",
["Obsidian Sentinel"] = "Sentinelle d'obsidienne",
["Odo the Blindwatcher"] = "Odo l'Aveugle",
["Ogom the Wretched"] = "Ogom le Misérable",
["Ok'thor the Breaker"] = "Ok'thor le Briseur",
["Old Serra'kis"] = "Vieux Serra'kis",
["Olm the Summoner"] = "Olm l'Invocateur",
["Omor the Unscarred"] = "Omor l'Intouché",
Onyxia = "Onyxia",
["Orgrim's Hammer"] = "Marteau d'Orgrim",
["Ormorok the Tree-Shaper"] = "Ormorok le Sculpte-arbre",
["Oro Eyegouge"] = "Oro Crève-oeil ",
["Ossirian the Unscarred"] = "Ossirian l'Intouché",
Ouro = "Ouro",
["Overlord Ramtusk"] = "Seigneur Brusquebroche",
["Overlord Wyrmthalak"] = "Seigneur Wyrmthalak",
["Overmaster Pyron"] = "Grand seigneur Pyron",
["Overseer Tidewrath"] = "Surveillant Tidewrath",
Pandemonius = "Pandemonius",
["Panzor the Invincible"] = "Panzor l'Invincible",
Patchwerk = "Le Recousu",
["Pathaleon the Calculator"] = "Pathaleon le Calculateur",
Phalanx = "Phalange",
["Phaseshift Bulwark"] = "Rempart de déphasage",
Pimgib = "Pimgib",
["Plaguemaw the Rotting"] = "Pestegueule le Pourrissant",
["Plugger Spazzring"] = "Lanfiche Brouillecircuit",
["Postmaster Malown"] = "Postier Malown",
["Priestess Delrissa"] = "Prêtresse Delrissa",
["Prince Keleseth"] = "Prince Keleseth",
["Prince Malchezaar"] = "Prince Malchezaar",
["Prince Skaldrenox"] = "Prince Skaldrenox ",
["Princess Huhuran"] = "Princesse Huhuran",
["Princess Moira Bronzebeard"] = "Princesse Moira Barbe-de-bronze",
["Princess Tempestria"] = "Princesse Tempestria",
["Princess Theradras"] = "Princesse Theradras",
["Princess Yauj"] = "Princesse Yauj",
["Prince Taldaram"] = "Prince Taldaram",
["Prince Tenris Mirkblood"] = "Prince Tenris Bourbassang",
["Prince Tortheldrin"] = "Prince Tortheldrin",
["Prince Valanar"] = "Prince Valanar",
["Professor Putricide"] = "Professeur Putricide",
["Pure Spawn of Hydross"] = "Pur rejeton d'Hydross",
Pusillin = "Pusillin",
["Pyroguard Emberseer"] = "Pyrogarde Prophète ardent",
["Pyromancer Loregrain"] = "Pyromancien Blé-du-savoir",
Quagmirran = "Bourbierreux",
["Quartermaster Zigris"] = "Intendant Zigris",
["Rage Winterchill"] = "Rage Froidhiver",
Ragglesnout = "Groinfendu",
["Raging Spirit"] = "Esprit déchaîné",
Ragnaros = "Ragnaros",
["Ramstein the Gorger"] = "Ramstein Grandgosier",
["Ras Frostwhisper"] = "Ras Murmegivre",
Rattlegore = "Cliquettripes",
["Razorclaw the Butcher"] = "Tranchegriffe le Boucher",
["Razorgore the Untamed"] = "Tranchetripe l'Indompté",
Razorlash = "Tranchefouet",
Razorscale = "Tranchécaille",
["Reliquary of Souls"] = "Le reliquaire des âmes",
Renataki = "Renataki",
["Restless Skeleton"] = "Squelette sans repos",
Rethilgore = "Rethiltripe",
Revelosh = "Revelosh",
["Rhahk'Zor"] = "Rhahk'Zor",
["Ribbly Screwspigot"] = "Ribbly Fermevanne",
["Right Arm"] = "Bras droit",
Roar = "Graou",
["Rokad the Ravager"] = "Rodak le ravageur",
["Rokdar the Sundered Lord"] = "Rokdar le Seigneur scindé",
["Rokmar the Crackler"] = "Rokmar le Crépitant",
Romulo = "Romulo",
["Romulo & Julianne"] = "Romulo & Julianne",
Rotface = "Trognepus",
Rotgrip = "Grippe-charogne",
["Runemaster Molgeim"] = "Maître des runes Molgeim",
["Runok Wildmane"] = "Runok Crin-sauvage",
Ruuzlu = "Ruuzlu",
["Salramm the Fleshcrafter"] = "Salramm le Façonneur de chair",
["Sanctum Sentry"] = "Factionnaire du sanctum",
["Sandarr Dunereaver"] = "Sandarr Ravadune",
["Sandfury Executioner"] = "Bourreau Furie-des-sables",
Sapphiron = "Saphiron",
Sara = "Sara",
["Saronite Animus"] = "Animus de saronite",
Sartharion = "Sartharion",
["Sathrovarr the Corruptor"] = "Sathrovarr le Corrupteur",
["Saviana Ragefire"] = "Saviana Ragefeu",
["Scarlet Commander Mograine"] = "Commandant écarlate Mograine",
["Scourgelord Tyrannus"] = "Seigneur du Fléau Tyrannus",
["Seeth'rel"] = "Fulmi'rel",
["Selin Fireheart"] = "Selin Coeur-de-feu",
["Sergeant Bly"] = "Sergent Bly",
["Shade of Akama"] = "Ombre d'Akama",
["Shade of Aran"] = "Ombre d'Aran",
["Shade of Eranikus"] = "Ombre d'Eranikus",
["Shadikith the Glider"] = "Shadikith le glisseur",
["Shadow Hunter Vosh'gajin"] = "Chasseresse des ombres Vosh'gajin",
["Shadow of Leotheras"] = "Ombre de Leotheras",
["Shadowpriest Sezz'ziz"] = "Prêtre des ombres Sezz'ziz",
Shadron = "Obscuron",
Shazzrah = "Shazzrah",
["Shirrak the Dead Watcher"] = "Shirrak le Veillemort",
Sindragosa = "Sindragosa",
["Sir Zeliek"] = "Sire Zeliek",
["Sjonnir The Ironshaper"] = "Sjonnir le Sculptefer",
["Skadi the Ruthless"] = "Skadi le Brutal",
["Skarr the Unbreakable"] = "Bâlhafr l'Invaincu",
["Skarvald the Constructor"] = "Skarvald le Constructeur",
["Skra'gath"] = "Skra'gath",
Skul = "Krân",
Skum = "Skum",
["Slad'ran"] = "Slad'ran",
Sneed = "Sneed",
["Sneed's Shredder"] = "Déchiqueteur de Sneed",
["Solakar Flamewreath"] = "Solakar Voluteflamme",
["Solarium Agent"] = "Agent du Solarium",
["Solarium Priest"] = "Prêtre du Solarium",
["Spirestone Battle Lord"] = "Seigneur de bataille Pierre-du-pic",
["Spirestone Butcher"] = "Boucher Pierre-du-pic",
["Spirestone Lord Magus"] = "Seigneur magus Pierre-du-pic",
["Staff of Disintegration"] = "Bâton de désintégration",
Stalagg = "Stalagg",
Steelbreaker = "Brise-acier",
["Stomper Kreeg"] = "Kreeg le Marteleur",
Stonespine = "Echine-de-pierre",
["Stormcaller Brundir"] = "Mande-foudre Brundir",
Strawman = "Homme de paille",
["Sulfuron Harbinger"] = "Messager de Sulfuron",
Supremus = "Supremus",
["Svala Sorrowgrave"] = "Svala Tristetombe",
["Swamplord Musel'ek"] = "Seigneur des marais Musel'ek",
Taerar = "Taerar",
["Tainted Spawn of Hydross"] = "Rejeton d'Hydross souillé",
["Talon King Ikiss"] = "Roi-serre Ikiss",
["Taragaman the Hungerer"] = "Taragaman l'Affameur",
["Targorr the Dread"] = "Targorr le Terrifiant",
Tavarok = "Tavarok",
Techbot = "Techbot",
Temporus = "Temporus",
["Tendris Warpwood"] = "Tendris Crochebois",
Tenebron = "Ténébron",
["Terestian Illhoof"] = "Terestian Malsabot",
["Teron Gorefiend"] = "Teron Fielsang",
Thaddius = "Thaddius",
["Thaladred the Darkener"] = "Thaladred l'Assombrisseur",
["Thane Korth'azz"] = "Thane Korth'azz",
["The Beast"] = "La Bête",
["The Beasts of Northrend"] = "Les bêtes du Norfendre",
["The Big Bad Wolf"] = "Le Grand Méchant Loup",
["The Black Knight"] = "Le Chevalier noir",
["The Black Stalker"] = "La Traqueuse noire",
["The Blue Brothers"] = "Les Grands Bleus",
["The Bug Family"] = "La famille insecte",
["The Crone"] = "La Mégère",
["The Curator"] = "Le conservateur",
["The Eredar Twins"] = "Les jumelles érédars",
["The Four Horsemen"] = "Les quatre cavaliers",
["The Illidari Council"] = "Le conseil illidari",
["The Iron Council"] = "Assemblée du fer",
["Theka the Martyr"] = "Theka le Martyr",
["The Lich King"] = "Le roi-liche",
["The Lurker Below"] = "Le Rôdeur d'En bas",
["The Maker"] = "Le Faiseur",
["The Prophet Skeram"] = "Le Prophète Skeram",
["The Prophet Tharon'ja"] = "Le prophète Tharon'ja",
["The Ravenian"] = "Le Voracien",
["The Razza"] = "La Razza",
["The Seven Dwarves"] = "Les sept nains",
["The Skybreaker"] = "Le Brise-ciel",
["The Tribunal of Ages"] = "Le tribunal des Âges",
["The Twin Emperors"] = "Les Empereurs jumeaux",
["The Twin Val'kyr"] = "Les jumelles val'kyr",
["The Unforgiven"] = "Le Condamné",
["The Windreaver"] = "Ouraganien",
Thorim = "Thorim",
["Thorngrin the Tender"] = "Rirépine le Tendre",
["Tidewalker Lurker"] = "Rôdeur marcheur-des-flots",
["Timmy the Cruel"] = "Timmy le Cruel",
Tinhead = "Tête de fer-blanc",
["Tinkerer Gizlock"] = "Bricoleur Kadenaz",
["Tirion Fordring"] = "Tirion Fordring",
Tito = "Tito",
["Toravon the Ice Watcher"] = "Toravon la Sentinelle de glace",
["Trigore the Lasher"] = "Trigore le Flagelleur",
Trollgore = "Trollétripe",
["Tsu'zee"] = "Tsu'zee",
["Tuten'kash"] = "Tuten'kash",
["Twilight Lord Kelris"] = "Seigneur du crépuscule Kelris",
["Urok Doomhowl"] = "Urok Hurleruine",
["Vaelastrasz the Corrupt"] = "Vaelastrasz le Corrompu",
["Valithria Dreamwalker"] = "Valithria Marcherêve",
["Val'kyr Shadowguard"] = "Garde de l'ombre val'kyr",
["Varian Wrynn"] = "Varian Wrynn",
["Varos Cloudstrider"] = "Varos Arpentenuée",
Vazruden = "Vazruden",
["Vazruden the Herald"] = "Vazruden le Héraut",
Vectus = "Vectus",
Vem = "Vem",
Veng = "Veng",
["Veras Darkshadow"] = "Veras Ombrenoir",
["Verdan the Everliving"] = "Verdan l'Immortel",
Verek = "Verek",
Vesperon = "Vespéron",
Vexallus = "Vexallus",
["Veyzhak the Cannibal"] = "Veyzhak le Cannibale",
["Vile'rel"] = "Ignobl'rel",
Viscidus = "Viscidus",
["Viscous Fallout"] = "Retombée visqueuse",
["Void Reaver"] = "Saccageur du Vide",
Volkhan = "Volkhan",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "Porteguerre O'mrogg",
["Warchief Blackhand Piece"] = "Pion du Chef de guerre Main-noire",
["Warchief Kargath Bladefist"] = "Chef de guerre Kargath Lamepoing",
["Warchief Rend Blackhand"] = "Chef de guerre Rend Main-noire",
["Warden Mellichar"] = "Gardien Mellichar",
["Warder Stilgiss"] = "Gardien Stilgiss",
["Warlord Kalithresh"] = "Seigneur de guerre Kalithresh",
["War Master Voone"] = "Maître de guerre Voone",
["Warmaul Champion"] = "Champion Cogneguerre",
["Warp Slicer"] = "Tranchoir dimensionnel",
["Warp Splinter"] = "Brise-dimension",
["Watchkeeper Gargolmar"] = "Gardien des guetteurs Gargolmar",
Weaver = "Tisserand",
["Witch Doctor Zum'rah"] = "Sorcier-docteur Zum'rah",
["Wolf Master Nandos"] = "Maître-loup Nandos",
["Wrath-Scryer Soccothrates"] = "Scrute-courroux Soccothrates",
Wushoolay = "Wushoolay",
Xevozz = "Xevozz",
["XT-002 Deconstructor"] = "Déconstructeur XT-002",
["Yogg-Saron"] = "Yogg-Saron",
Ysondre = "Ysondre",
Zekkis = "Zekkis",
["Zelemar the Wrathful"] = "Zelemar le Courroucé",
["Zereketh the Unbound"] = "Zereketh le Délié",
Zerillis = "Zerillis",
["Zevrim Thornhoof"] = "Zevrim Sabot-de-ronce",
Zolo = "Zolo",
["Zul'Farrak Dead Hero"] = "Héros mort de Zul'Farrak",
["Zul'jin"] = "Zul'jin",
["Zul'Lor"] = "Zul'Lor",
["Zul'tore"] = "Zul'tore",
["Zuramat the Obliterator"] = "Zuramat l'Oblitérateur",
}
elseif GAME_LOCALE == "koKR" then
lib:SetCurrentTranslations {
Acidmaw = "공포비늘",
Aeonus = "아에누스",
["Aerial Command Unit"] = "공중 지휘기",
["Agathelos the Raging"] = "흉포한 아가테로스",
Ahune = "아훈",
["Akil'zon"] = "아킬존",
["Aku'mai"] = "아쿠마이",
["Al'ar"] = "알라르",
["Algalon the Observer"] = "관찰자 알갈론",
["Alzzin the Wildshaper"] = "칼날바람 알진",
Amanitar = "아마니타르",
["Ambassador Flamelash"] = "사자 화염채찍",
["Ambassador Hellmaw"] = "사자 지옥아귀",
["Amnennar the Coldbringer"] = "혹한의 암네나르",
["Ancient Stone Keeper"] = "고대 바위 문지기",
Anetheron = "아네테론",
["Anger'rel"] = "격노의 문지기",
Anomalus = "아노말루스",
["Antu'sul"] = "안투술",
["Anub'arak"] = "아눕아락",
["Anubisath Defender"] = "아누비사스 문지기",
["Anubisath Guardian"] = "아누비사스 감시자",
["Anub'Rekhan"] = "아눕레칸",
["Anub'shiah"] = "아눕쉬아",
Anzu = "안주",
["Arcane Watchman"] = "비전 보초",
["Arcanist Doan"] = "신비술사 도안",
Archaedas = "아카에다스",
["Archavon the Stone Watcher"] = "바위 감시자 아카본",
Archimonde = "아키몬드",
["Archivist Galford"] = "기록관 갈포드",
["Archmage Arugal"] = "대마법사 아루갈",
["Argent Confessor Paletress"] = "은빛 고해사제 페일트리스",
["Arugal's Voidwalker"] = "아루갈의 보이드워커",
["Assault Bot"] = "돌격로봇",
["Atal'alarion"] = "아탈알라리온",
["Attumen the Huntsman"] = "사냥꾼 어튜멘",
Auriaya = "아우리아야",
Avalanchion = "아발란치온",
["Avatar of Hakkar"] = "학카르의 화신",
["Ayamiss the Hunter"] = "사냥꾼 아야미스",
Azgalor = "아즈갈로",
["Azshir the Sleepless"] = "잠들지 않는 아즈시르",
Azuregos = "아주어고스",
["Bael'Gar"] = "벨가르",
Baelog = "밸로그",
Balnazzar = "발나자르",
-- ["Baltharus the Warborn"] = "",
["Bannok Grimaxe"] = "반노크 그림액스",
["Baron Aquanis"] = "남작 아쿠아니스",
["Baron Charr"] = "남작 차르",
["Baroness Anastari"] = "남작부인 아나스타리",
["Baron Geddon"] = "남작 게돈",
["Baron Kazum"] = "남작 카줌",
["Baron Rivendare"] = "남작 리븐데어",
["Baron Silverlaine"] = "남작 실버레인",
["Battleguard Sartura"] = "전투감시병 살투라",
["Bazil Thredd"] = "바질 스레드",
Bazzalan = "바잘란",
["Black Guard Swordsmith"] = "검은호위대 검제작자",
["Blackheart the Inciter"] = "선동자 검은심장",
["Blindeye the Seer"] = "현자 블라인드아이",
["Blind Hunter"] = "장님 사냥꾼",
["Blood Guard Porung"] = "혈투사 포룽",
["Bloodlord Mandokir"] = "혈군주 만도키르",
["Bloodmage Thalnos"] = "혈법사 탈노스",
["Blood Prince Council"] = "피의 공작 의회",
["Blood Princes"] = "피의 공작",
["Blood-Queen Lana'thel"] = "피의 여왕 라나텔",
["Blood Steward of Kirtonos"] = "키르토노스의 혈지기",
Boahn = "보안",
["Bomb Bot"] = "폭탄로봇",
["Brain of Yogg-Saron"] = "요그사론의 뇌",
["Brainwashed Noble"] = "세뇌당한 귀족",
Broggok = "브로고크",
Brokentoe = "망치발굽",
Bronjahm = "브론잠",
["Broodlord Lashlayer"] = "용기대장 래쉬레이어",
["Bruegal Ironknuckle"] = "무쇠주먹 브루갈",
Brutallus = "브루탈루스",
["Burning Felguard"] = "불타는 지옥수호병",
["Buru the Gorger"] = "먹보 부루",
["Cache of the Firelord"] = "Cache of the Firelord",
["Cannon Master Willey"] = "포병대장 윌리",
["Captain Greenskin"] = "선장 그린스킨",
["Captain Kromcrush"] = "대장 크롬크러쉬",
["Captain Skarloc"] = "경비대장 스칼록",
["Celebras the Cursed"] = "저주받은 셀레브라스",
["Charlga Razorflank"] = "서슬깃 차를가",
["Chess Event"] = "Chess Event",
["Chest of The Seven"] = "Chest of The Seven",
["Chief Ukorz Sandscalp"] = "족장 우코르즈 샌드스칼프",
["Cho'Rush the Observer"] = "정찰병 초루쉬",
Chromaggus = "크로마구스",
["Chrono Lord Deja"] = "시간의 군주 데자",
["Chrono-Lord Epoch"] = "시간의 군주 에포크",
Claw = "클로",
["Coilfang Elite"] = "갈퀴송곳니 정예병",
["Coilfang Strider"] = "갈퀴송곳니 포자손",
["Commander Kolurg"] = "사령관 콜루르그",
["Commander Sarannis"] = "지휘관 새래니스",
["Commander Springvale"] = "사령관 스프링베일",
["Commander Stoutbeard"] = "사령관 스타우트비어드",
["Constructor & Controller"] = "건축가와 감시자",
Cookie = "쿠키",
["Coren Direbrew"] = "코렌 다이어브루",
["Cosmic Infuser"] = "붕괴의 지팡이",
["Crimson Hammersmith"] = "진홍십자군 대장장이",
["Crowd Pummeler 9-60"] = "고철 압축기 9-60",
["Crystal Fang"] = "수정 맹독 거미",
["C'Thun"] = "쑨",
Cyanigosa = "시아니고사",
["Dalliah the Doomsayer"] = "파멸의 예언자 달리아",
["Dalronn the Controller"] = "감시자 달론",
["Dark Iron Ambassador"] = "검은무쇠단 사절",
["Darkmaster Gandling"] = "암흑스승 간틀링",
["Darkweaver Syth"] = "흑마술사 시스",
["Deathbound Ward"] = "죽음에 속박된 감시자",
["Deathbringer Saurfang"] = "죽음의 인도자 사울팽",
["Death Knight Darkreaver"] = "죽음의 기사 다크리버",
["Death Knight Understudy"] = "죽음의 기사 수습생",
["Deathspeaker High Priest"] = "죽음예언자 대사제",
["Death Speaker Jargba"] = "죽음의 예언자 잘그바",
["Deathstalker Visceri"] = "죽음의추적자 비세리",
["Deathsworn Captain"] = "죽음의 경비대장",
Devastation = "황폐의 도끼",
["Deviate Faerie Dragon"] = "돌연변이 요정용",
["Devourer of Souls"] = "영혼의 포식자",
["Dextren Ward"] = "덱스트렌 워드",
["Digmaster Shovelphlange"] = "발굴단장 쇼벨플랜지",
["Doctor Theolen Krastinov"] = "학자 테올린 크라스티노브",
["Doom Lord Kazzak"] = "파멸의 군주 카자크",
["Doom'rel"] = "운명의 문지기",
Doomwalker = "파멸의 절단기",
["Dope'rel"] = "최면의 문지기",
Dorothee = "도로시",
["Drakkari Colossus"] = "드라카리 거대골렘",
["Drakos the Interrogator"] = "심문관 드라코스",
Dreadscale = "공포비늘",
Dreamscythe = "드림사이드",
["Dust Covered Chest"] = "Dust Covered Chest",
Dustwraith = "더스트레이스",
["Eadric the Pure"] = "성기사 에드릭",
["Earthcaller Halmgar"] = "대지술사 함가르",
Ebonroc = "에본로크",
["Eck the Ferocious"] = "사나운 엑크",
["Edwin VanCleef"] = "에드윈 밴클리프",
["Elder Brightleaf"] = "장로 밝은잎",
["Elder Ironbranch"] = "장로 무쇠돌기",
["Elder Nadox"] = "장로 나독스",
["Elder Stonebark"] = "장로 돌나무껍질",
["Electrocutioner 6000"] = "기계화 문지기 6000",
["Emalon the Storm Watcher"] = "폭풍 감시자 에말론",
Emeriss = "에메리스",
["Emperor Dagran Thaurissan"] = "제왕 다그란 타우릿산",
["Emperor Vek'lor"] = "제왕 베클로어",
["Emperor Vek'nilash"] = "제왕 베크닐라쉬",
Entropius = "엔트로피우스",
["Eonar's Gift"] = "이오나의 선물",
["Epoch Hunter"] = "시대의 사냥꾼",
Erekem = "에레켐",
["Eressea Dawnsinger"] = "에레시아 돈싱어",
["Essence of Anger"] = "격노의 정수",
["Essence of Desire"] = "욕망의 정수",
["Essence of Suffering"] = "고뇌의 정수",
Eviscerator = "적출자",
["Exarch Maladaar"] = "총독 말라다르",
["Expedition Commander"] = "원정대 대장",
["Eydis Darkbane"] = "아이디스 다크베인",
["Eye of C'Thun"] = "쑨의 눈",
["Faction Champions"] = "진영 대표 용사",
["Fallen Champion"] = "타락한 용사",
Falric = "팔릭",
["Falric and Marwyn"] = "팔릭과 마윈",
["Fankriss the Unyielding"] = "불굴의 판크리스",
["Fathom-Lord Karathress"] = "심연의 군주 카라드레스",
Felmyst = "지옥안개",
["Fenrus the Devourer"] = "파멸의 펜루스",
["Feral Defender"] = "수호 야수",
Festergut = "구린속",
Feugen = "퓨진",
["Fineous Darkvire"] = "파이너스 다크바이어",
Firemaw = "화염아귀",
["Fjola Lightbane"] = "피욜라 라이트베인",
Flamegor = "플레임고르",
["Flame Leviathan"] = "거대 화염전차",
["Foreman Thistlenettle"] = "현장감독 시슬네틀",
["Forgemaster Garfrost"] = "괴철로감독관 가프로스트",
["Four Horsemen Chest"] = "Four Horsemen Chest",
["Fras Siabi"] = "프라스 샤비",
Freya = "프레이야",
["Gahz'ranka"] = "가즈란카",
["Gahz'rilla"] = "가즈릴라",
["Gal'darah"] = "갈다라",
["Galgann Firehammer"] = "갈간 파이어해머",
Garr = "가르",
["Garrosh Hellscream"] = "가로쉬 헬스크림",
Gasher = "게이셔",
["Gatewatcher Gyro-Kill"] = "문지기 회전톱날",
["Gatewatcher Iron-Hand"] = "문지기 무쇠주먹",
["Gathios the Shatterer"] = "파괴자 가디오스",
Gehennas = "게헨나스",
Gelihast = "겔리하스트",
Gelk = "겔크",
["General Angerforge"] = "사령관 앵거포지",
["General Bjarngrim"] = "장군 비야른그림",
["General Drakkisath"] = "사령관 드라키사스",
["General Rajaxx"] = "장군 라작스",
["General Vezax"] = "장군 베작스",
["General Zarithrian"] = "장군 자리스리안",
["Ghamoo-ra"] = "가무라 ",
["Ghaz'an"] = "가즈안",
["Ghok Bashguud"] = "고크 배시구드",
Gilnid = "길니드",
["Gizrul the Slavener"] = "흉포한 기즈룰",
["Gloom'rel"] = "그늘의 문지기",
Gluth = "글루스",
Glutton = "게걸먹보",
["Golemagg the Incinerator"] = "초열의 골레마그",
["Golem Lord Argelmach"] = "골렘군주 아젤마크",
["Goraluk Anvilcrack"] = "고랄루크 앤빌크랙",
["Gormok the Impaler"] = "꿰뚫는 자 고르목",
["Gorosh the Dervish"] = "광신자 고로쉬",
["Gortok Palehoof"] = "고르톡 페일후프",
["Gothik the Harvester"] = "영혼 착취자 고딕",
["Grand Astromancer Capernian"] = "대점성술사 카퍼니안",
["Grand Champions"] = "도시 최고 용사",
["Grand Magus Telestra"] = "대학자 텔레스트라",
["Grandmaster Vorpil"] = "단장 보르필",
Grandmother = "할머니",
["Grand Warlock Alythess"] = "대흑마법사 알리테스",
["Grand Warlock Nethekurse"] = "대흑마법사 네더쿠르스",
["Grand Widow Faerlina"] = "귀부인 팰리나",
["Grethok the Controller"] = "감시자 그레토크",
["Gri'lek"] = "그리렉",
Grimlok = "그림로크",
Grizzle = "그리즐",
Grobbulus = "그라불루스",
Grubbis = "그루비스 ",
["Gruul the Dragonkiller"] = "용 학살자 그룰",
["Guard Fengus"] = "경비병 펜구스",
["Guardian of Yogg-Saron"] = "요그사론의 수호자",
["Guard Mol'dar"] = "경비병 몰다르",
["Guard Slip'kik"] = "경기병 슬립킥",
["Gurtogg Bloodboil"] = "구르토그 블러드보일",
Gyth = "기스",
Hadronox = "하드로녹스",
Hakkar = "학카르",
Halazzi = "할라지",
Halion = "할리온",
Halycon = "할리콘",
Hamhock = "햄혹",
["Harbinger Skyriss"] = "선구자 스키리스",
["Hate'rel"] = "증오의 문지기",
["Hazza'rah"] = "하자라",
Hazzas = "하자스",
["Headless Horseman"] = "저주받은 기사",
["Hearthsinger Forresten"] = "하스싱어 포레스턴",
["Hedrum the Creeper"] = "왕거미 헤드룸",
["Heigan the Unclean"] = "부정의 헤이건",
["Hellfire Channeler"] = "지옥불 역술사",
["Henry Stern"] = "헨리 스턴",
["Herald Volazj"] = "사자 볼라즈",
Herod = "헤로드",
["Hex Lord Malacrass"] = "주술 군주 말라크라스",
["High Astromancer Solarian"] = "고위 점성술사 솔라리안",
["High Botanist Freywinn"] = "고위 식물학자 프레이윈",
["High Inquisitor Fairbanks"] = "종교재판관 페어뱅크스",
["High Inquisitor Whitemane"] = "종교재판관 화이트메인",
["High Interrogator Gerstahn"] = "대심문관 게르스탄",
["High King Maulgar"] = "왕중왕 마울가르",
["Highlord Mograine"] = "대영주 모그레인",
["Highlord Omokk"] = "대군주 오모크",
["High Marshal Whirlaxis"] = "대장군 휠락시스",
["High Nethermancer Zerevor"] = "고위 황천술사 제레보르",
["High Overlord Saurfang"] = "대군주 사울팽",
["High Priestess Arlokk"] = "대여사제 알로크",
["High Priestess Jeklik"] = "대여사제 제클릭",
["High Priestess Mar'li"] = "대여사제 말리",
["High Priestess of Thaurissan"] = "타우릿산의 대여사제",
["High Priest Thekal"] = "대사제 데칼",
["High Priest Venoxis"] = "대사제 베녹시스",
["High Warlord Naj'entus"] = "대장군 나젠투스",
Hodir = "호디르",
["Houndmaster Grebmar"] = "사냥개조련사 그렙마르",
["Houndmaster Loksey"] = "사냥개 조련사 록시",
Hukku = "후쿠",
Hungarfen = "헝가르펜",
["Hurley Blackbreath"] = "헐레이 블랙브레스",
["Hyakiss the Lurker"] = "잠복꾼 히아키스",
["Hydromancer Thespia"] = "풍수사 세스피아",
["Hydromancer Velratha"] = "유체술사 벨라타",
Hydrospawn = "히드로스폰",
["Hydross the Unstable"] = "불안정한 히드로스",
["Icecrown Gunship Battle"] = "얼음왕관 비행포격선 전투",
Icehowl = "얼음울음",
["Ice Sphere"] = "얼음 구슬",
Ichoron = "이코론",
Ick = "이크",
["Ignis the Furnace Master"] = "용광로 군주 이그니스",
["Illidan Stormrage"] = "일리단 스톰레이지",
["Illidari Council"] = "일리다리 의회",
["Illyanna Ravenoak"] = "일샨나 레이븐호크",
["Immol'thar"] = "이몰타르",
["Infinite Corruptor"] = "무한의 타락자",
["Infinity Blades"] = "무한의 비수",
["Ingvar the Plunderer"] = "약탈자 잉그바르",
["Instructor Malicia"] = "조교 말리시아",
["Instructor Razuvious"] = "훈련교관 라주비어스",
["Interrogator Vishas"] = "심문관 비샤스",
Ionar = "아이오나",
Ironaya = "아이로나야",
Ironspine = "무쇠해골",
Isalien = "이살리엔",
Jade = "제이드",
["Jammal'an the Prophet"] = "예언자 잠말란",
["Jan'alai"] = "잔알라이",
["Jandice Barov"] = "잔다이스 바로브",
["Jedoga Shadowseeker"] = "어둠추적자 제도가",
["Jed Runewatcher"] = "제드 룬와처",
["Jergosh the Invoker"] = "기원사 제로쉬",
["Jin'do the Hexxer"] = "주술사 진도",
["Jormungar Behemoth"] = "요르문가르 거수",
Jormungars = "요르문가르",
Julianne = "줄리엔",
["Junk Bot"] = "고철로봇",
["Kael'thas Sunstrider"] = "캘타스 선스트라이더",
Kalecgos = "칼렉고스",
["Kam Deepfury"] = "캄 딥퓨리",
["Kazkaz the Unholy"] = "타락한 카즈카즈",
["Kaz'rogal"] = "카즈로갈",
["Keli'dan the Breaker"] = "파괴자 켈리단",
["Kel'Thuzad"] = "켈투자드",
Keristrasza = "케리스트라자",
["Kiggler the Crazed"] = "광기의 키글러",
["Kil'jaeden"] = "킬제덴",
["Kil'rek"] = "킬렉",
["King Dred"] = "랩터왕 서슬발톱",
["King Gordok"] = "왕 고르독",
["King Llane Piece"] = "국왕 레인",
["King Ymiron"] = "왕 이미론",
["Kirtonos the Herald"] = "사자 키르토노스",
["Knot Thimblejack's Cache"] = "노트 팀블젝의 은닉품",
Kolk = "콜크",
Kologarn = "콜로간",
["Koralon the Flame Watcher"] = "화염 감시자 코랄론",
Kormok = "코르모크",
Kresh = "크레쉬",
Krick = "크리크",
["Krick and Ick"] = "크리크와 이크",
["Krik'thir the Gatewatcher"] = "문지기 크릭시르",
["Krosh Firehand"] = "크로쉬 파이어핸드",
Krystallus = "크리스탈루스",
Kurinnaxx = "쿠린낙스",
["Lady Anacondra"] = "여군주 아나콘드라",
["Lady Blaumeux"] = "여군주 블라미우스",
["Lady Deathwhisper"] = "여교주 데스위스퍼",
["Lady Illucia Barov"] = "여군주 일루시아 바로브",
["Lady Malande"] = "여군주 말란데",
["Lady Sacrolash"] = "여군주 사크로래쉬",
["Lady Sarevess"] = "여왕 사레베스",
["Lady Vashj"] = "여군주 바쉬",
Laj = "라즈",
Landslide = "산사태",
Lavanthor = "라반토르",
["Left Arm"] = "왼팔",
["Leotheras the Blind"] = "눈먼 레오테라스",
Lethon = "레손",
Lethtendris = "레스텐드리스",
["Leviathan Mk II"] = "거대 전차 Mk II",
["Ley-Guardian Eregos"] = "지맥 수호자 에레고스",
["Lieutenant Drake"] = "부관 드레이크",
["Lieutenant General Andorov"] = "사령관 안도로브",
Loatheb = "로데브",
Loken = "로켄",
["Lord Alexei Barov"] = "군주 알렉세이 바로브",
["Lord Cobrahn"] = "군주 코브란",
["Lord Hel'nurath"] = "군주 헬누라스",
["Lord Incendius"] = "군주 인센디우스",
["Lord Jaraxxus"] = "군주 자락서스",
["Lord Kazzak"] = "군주 카자크",
["Lord Kri"] = "군주 크리",
["Lord Marrowgar"] = "군주 매로우가르",
["Lord Pythas"] = "군주 피타스",
["Lord Roccor"] = "불의군주 록코르",
["Lord Sanguinar"] = "군주 생귀나르",
["Lord Serpentis"] = "군주 서펜디스",
["Lord Skwol"] = "군주 스퀄",
["Lord Valthalak"] = "군주 발타라크",
["Lord Victor Nefarius"] = "군주 빅터 네파리우스",
["Lord Vyletongue"] = "군주 바일텅",
["Lorekeeper Polkelt"] = "현자 폴켈트",
Loro = "로로",
Lucifron = "루시프론",
["Mad Magglish"] = "광기의 매글리시",
Maexxna = "맥스나",
["Mage-Lord Urom"] = "마법사 군주 우롬",
["Magister Kalendris"] = "마법사 칼렌드리스",
["Magistrate Barthilas"] = "집정관 바실라스",
Magmadar = "마그마다르",
Magmus = "마그무스",
Magra = "마그라",
Magtheridon = "마그테리돈",
["Maiden of Grief"] = "고뇌의 마녀",
["Maiden of Virtue"] = "고결의 여신",
["Majordomo Executus"] = "청지기 이그젝큐투스",
Malacrass = "말라크라스",
["Maleki the Pallid"] = "냉혈한 말레키",
["Mal'Ganis"] = "말가니스",
Malygos = "말리고스",
Maraudos = "마라우도스",
["Marduk Blackpool"] = "마르두크 블랙풀",
["Marisa du'Paige"] = "마리사 두페이지",
Marwyn = "마윈",
["Master Engineer Telonicus"] = "수석기술자 텔로니쿠스",
["Maur Grimtotem"] = "마우르 그림토템",
Meathook = "살덩이갈고리",
["Mechano-Lord Capacitus"] = "기계군주 캐퍼시투스",
Medivh = "메디브",
["Mekgineer Steamrigger"] = "기계공학자 스팀리거",
["Mekgineer Thermaplugg"] = "멕기니어 텔마플러그",
["Mennu the Betrayer"] = "배반자 멘누",
["Meshlok the Harvester"] = "정원사 메슬로크",
Midnight = "천둥이",
Mijan = "마이잔",
Mimiron = "미미론",
["Miner Johnson"] = "광부 존슨",
["Mistress of Pain"] = "고통의 여군주",
Moam = "모암",
Mogor = "모고르",
["Mokra the Skullcrusher"] = "해골분쇄자 모크라",
Moorabi = "무라비",
Moragg = "모라그",
["Mordresh Fire Eye"] = "불꽃눈 모드레쉬",
["Mor Grayhoof"] = "모르 그레이후프",
Moroes = "모로스",
["Morogrim Tidewalker"] = "겅둥파도 모로그림",
Morphaz = "몰파즈",
["Mother Shahraz"] = "대모 샤라즈",
["Mother Smolderweb"] = "여왕 불그물거미",
["Mr. Smite"] = "미스터 스마이트",
["Muradin Bronzebeard"] = "무라딘 브론즈비어드",
["Murkblood Twin"] = "수렁피일족 쌍둥이",
["Murkblood Twins"] = "수렁피일족 쌍둥이",
Murmur = "울림",
["Murta Grimgut"] = "무르타 그림구트",
["M'uru"] = "므우루",
Mushgog = "머쉬고그",
["Mutanus the Devourer"] = "걸신들린 무타누스",
Nalorakk = "날로라크",
Nazan = "나잔",
Nefarian = "네파리안",
["Nekrum Gutchewer"] = "네크룸 거트츄어",
["Nerub'enkan"] = "네룹엔칸",
["Nethermancer Sepethrea"] = "황천술사 세페스레아",
Netherspite = "황천의 원령",
["Netherstrand Longbow"] = "황천매듭 장궁",
["Nexus-Prince Shaffar"] = "연합왕자 샤파르",
Nightbane = "파멸의 어둠",
["Noth the Plaguebringer"] = "역병술사 노스",
["Novos the Summoner"] = "소환사 노보스",
Noxxion = "녹시온",
["Obsidian Sentinel"] = "흑요석 파수꾼",
["Odo the Blindwatcher"] = "눈먼감시자 오도",
["Ogom the Wretched"] = "비운의 오그옴",
["Ok'thor the Breaker"] = "파괴자 오크토르",
["Old Serra'kis"] = "늙은 세라키스",
["Olm the Summoner"] = "소환사 올름",
["Omor the Unscarred"] = "무적의 오모르",
Onyxia = "오닉시아",
["Orgrim's Hammer"] = "오그림의 망치호",
["Ormorok the Tree-Shaper"] = "정원사 오르모로크",
["Oro Eyegouge"] = "오로 아이가우지",
["Ossirian the Unscarred"] = "무적의 오시리안",
Ouro = "아우로",
["Overlord Ramtusk"] = "대군주 램터스크",
["Overlord Wyrmthalak"] = "대군주 윔타라크",
["Overmaster Pyron"] = "멸망의 파이론",
["Overseer Tidewrath"] = "우두머리 성난파도",
Pandemonius = "팬더모니우스",
["Panzor the Invincible"] = "무적의 판저",
Patchwerk = "패치워크",
["Pathaleon the Calculator"] = "철두철미한 파탈리온",
Phalanx = "팔란스",
["Phaseshift Bulwark"] = "위상 변화의 보루방패",
Pimgib = "핌기브",
["Plaguemaw the Rotting"] = "썩어가는 역병아귀",
["Plugger Spazzring"] = "플러거스파즈링",
["Postmaster Malown"] = "우체국장 말로운",
["Priestess Delrissa"] = "여사제 델리사",
["Prince Keleseth"] = "공작 켈레세스",
["Prince Malchezaar"] = "공작 말체자르",
["Prince Skaldrenox"] = "왕자 스칼레녹스",
["Princess Huhuran"] = "공주 후후란",
["Princess Moira Bronzebeard"] = "공주 모이라 브론즈비어드",
["Princess Tempestria"] = "공주 템페스트리아",
["Princess Theradras"] = "공주 테라드라스",
["Princess Yauj"] = "공주 야우즈",
["Prince Taldaram"] = "공작 탈다람",
["Prince Tenris Mirkblood"] = "공작 텐리스 머크블러드",
["Prince Tortheldrin"] = "왕자 토르텔드린",
["Prince Valanar"] = "공작 발라나르",
["Professor Putricide"] = "교수 퓨트리사이드",
["Pure Spawn of Hydross"] = "순수한 히드로스의 피조물",
Pusillin = "푸실린",
["Pyroguard Emberseer"] = "불의 수호자 엠버시어",
["Pyromancer Loregrain"] = "화염술사 로어그레인",
Quagmirran = "쿠아그미란",
["Quartermaster Zigris"] = "병참장교 지그리스",
["Rage Winterchill"] = "격노한 윈터칠",
Ragglesnout = "너덜주둥이",
["Raging Spirit"] = "분노한 영혼",
Ragnaros = "라그나로스",
["Ramstein the Gorger"] = "먹보 람스타인",
["Ras Frostwhisper"] = "라스 프로스트위스퍼",
Rattlegore = "들창어금니",
["Razorclaw the Butcher"] = "도살자 칼날발톱",
["Razorgore the Untamed"] = "폭군 서슬송곳니",
Razorlash = "칼날채찍",
Razorscale = "칼날비늘",
["Reliquary of Souls"] = "영혼의 성물함",
Renataki = "레나타키",
["Restless Skeleton"] = "잠 못 드는 해골",
Rethilgore = "레실고어",
Revelosh = "레벨로쉬",
["Rhahk'Zor"] = "라크조르",
["Ribbly Screwspigot"] = "리블리 스크류스피곳",
["Right Arm"] = "오른팔",
Roar = "어흥이",
["Rokad the Ravager"] = "파괴자 로카드",
["Rokdar the Sundered Lord"] = "파괴의 군주 로크다르",
["Rokmar the Crackler"] = "딱딱이 로크마르",
Romulo = "로밀로",
["Romulo & Julianne"] = "로밀로 & 줄리엔",
Rotface = "썩은얼굴",
Rotgrip = "썩은 아귀",
["Runemaster Molgeim"] = "룬술사 몰가임",
["Runok Wildmane"] = "루노크 와일드메인",
Ruuzlu = "루즐루",
["Salramm the Fleshcrafter"] = "살덩이창조자 살람",
["Sanctum Sentry"] = "성소의 파수꾼",
["Sandarr Dunereaver"] = "산다르 듄리버",
["Sandfury Executioner"] = "성난모래부족 사형집행인",
Sapphiron = "사피론",
Sara = "사라",
["Saronite Animus"] = "사로나이트 원혼",
Sartharion = "살타리온",
["Sathrovarr the Corruptor"] = "타락의 사스로바르",
["Saviana Ragefire"] = "사비아나 레이지파이어",
["Scarlet Commander Mograine"] = "붉은십자군 사령관 모그레인",
["Scourgelord Tyrannus"] = "스컬지군주 티라누스",
["Seeth'rel"] = "불안의 문지기",
["Selin Fireheart"] = "셀린 파이어하트",
["Sergeant Bly"] = "하사관 블라이",
["Shade of Akama"] = "아카마의 망령",
["Shade of Aran"] = "아란의 망령",
["Shade of Eranikus"] = "에라니쿠스의 사령",
["Shadikith the Glider"] = "활강의 샤디키스",
["Shadow Hunter Vosh'gajin"] = "어둠사냥꾼 보쉬가진",
["Shadow of Leotheras"] = "레오테라스의 그림자",
["Shadowpriest Sezz'ziz"] = "어둠의사제 세즈지즈",
Shadron = "샤드론",
Shazzrah = "샤즈라",
["Shirrak the Dead Watcher"] = "죽음의 감시인 쉴라크",
Sindragosa = "신드라고사",
["Sir Zeliek"] = "젤리에크 경",
["Sjonnir The Ironshaper"] = "무쇠구체자 쇼니르",
["Skadi the Ruthless"] = "학살자 스카디",
["Skarr the Unbreakable"] = "무적의 스카르",
["Skarvald the Constructor"] = "건축가 스카발드",
["Skra'gath"] = "스크라가스",
Skul = "스컬",
Skum = "스컴",
["Slad'ran"] = "슬라드란",
Sneed = "스니드",
["Sneed's Shredder"] = "스니드의 벌목기",
["Solakar Flamewreath"] = "화염고리 솔라카르",
["Solarium Agent"] = "태양의 전당 요원",
["Solarium Priest"] = "태양의 전당 사제",
["Spirestone Battle Lord"] = "뾰족바위일족 전투대장",
["Spirestone Butcher"] = "뾰족바위일족 학살자",
["Spirestone Lord Magus"] = "뾰족바위일족 마법사장",
["Staff of Disintegration"] = "우주 에너지 주입기",
Stalagg = "스탈라그",
Steelbreaker = "강철파괴자",
["Stomper Kreeg"] = "천둥발 크리그",
Stonespine = "뾰족바위",
["Stormcaller Brundir"] = "폭풍소환사 브룬디르",
Strawman = "허수아비",
["Sulfuron Harbinger"] = "설퍼론 사자",
Supremus = "궁극의 심연",
["Svala Sorrowgrave"] = "스발라 소로우그레이브",
["Swamplord Musel'ek"] = "늪군주 뮤즐레크",
Taerar = "타에라",
["Tainted Spawn of Hydross"] = "오염된 히드로스의 피조물",
["Talon King Ikiss"] = "갈퀴대왕 이키스",
["Taragaman the Hungerer"] = "욕망의 타라가만",
["Targorr the Dread"] = "흉악범 타고르",
Tavarok = "타바로크",
Techbot = "첨단로봇",
Temporus = "템퍼루스",
["Tendris Warpwood"] = "굽이나무 텐드리스",
Tenebron = "테네브론",
["Terestian Illhoof"] = "테레스티안 일후프",
["Teron Gorefiend"] = "테론 고어핀드",
Thaddius = "타디우스",
["Thaladred the Darkener"] = "암흑의 인도자 탈라드레드",
["Thane Korth'azz"] = "영주 코스아즈",
["The Beast"] = "괴수",
["The Beasts of Northrend"] = "노스렌드의 야수",
["The Big Bad Wolf"] = "커다란 나쁜 늑대",
["The Black Knight"] = "흑기사",
["The Black Stalker"] = "검은 추적자",
["The Blue Brothers"] = "푸른 형제들",
["The Bug Family"] = "벌레 무리",
["The Crone"] = "마녀",
["The Curator"] = "전시 관리인",
["The Eredar Twins"] = "에레다르 쌍둥이",
["The Four Horsemen"] = "4인의 기병대",
["The Illidari Council"] = "일리다리 의회",
["The Iron Council"] = "무쇠 평의회",
["Theka the Martyr"] = "순교자 데카",
["The Lich King"] = "리치 왕",
["The Lurker Below"] = "심연의 잠복꾼",
["The Maker"] = "재앙의 창조자",
["The Prophet Skeram"] = "예언자 스케람",
["The Prophet Tharon'ja"] = "예언자 타론자",
["The Ravenian"] = "라베니안",
["The Razza"] = "라자",
["The Seven Dwarves"] = "The Seven Dwarves", -- Needs review
["The Skybreaker"] = "하늘파괴자호",
["The Tribunal of Ages"] = "시대의 심판장",
["The Twin Emperors"] = "쌍둥이 제왕",
["The Twin Val'kyr"] = "발키르 쌍둥이",
["The Unforgiven"] = "용서받지 못한 자",
["The Windreaver"] = "칼날바람",
Thorim = "토림",
["Thorngrin the Tender"] = "감시인 쏜그린",
["Tidewalker Lurker"] = "겅둥파도 잠복꾼",
["Timmy the Cruel"] = "잔혹한 티미",
Tinhead = "양철나무꾼",
["Tinkerer Gizlock"] = "땜장이 기즐록",
["Tirion Fordring"] = "티리온 폴드링",
Tito = "티토",
["Toravon the Ice Watcher"] = "얼음 감시자 토라본",
["Trigore the Lasher"] = "채찍꼬리 트리고어",
Trollgore = "송곳아귀",
["Tsu'zee"] = "츄지",
["Tuten'kash"] = "투텐카쉬",
["Twilight Lord Kelris"] = "황혼의 군주 켈리스",
["Urok Doomhowl"] = "우르크 둠하울",
["Vaelastrasz the Corrupt"] = "타락한 밸라스트라즈",
["Valithria Dreamwalker"] = "발리스리아 드림워커",
["Val'kyr Shadowguard"] = "발키르 어둠수호병",
["Varian Wrynn"] = "바리안 린",
["Varos Cloudstrider"] = "바로스 클라우드스트라이더",
Vazruden = "바즈루덴",
["Vazruden the Herald"] = "사자 바즈루덴",
Vectus = "벡투스",
Vem = "ë²°",
Veng = "ë²µ",
["Veras Darkshadow"] = "베라스 다크섀도",
["Verdan the Everliving"] = "영생의 베르단",
Verek = "베레크",
Vesperon = "베스페론",
Vexallus = "벡살루스",
["Veyzhak the Cannibal"] = "식인트롤 베이쟉",
["Vile'rel"] = "타락의 문지기",
Viscidus = "비시디우스",
["Viscous Fallout"] = "방사성 폐기물",
["Void Reaver"] = "공허의 절단기",
Volkhan = "볼칸",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "돌격대장 오므로그",
["Warchief Blackhand Piece"] = "대족장 블랙핸드",
["Warchief Kargath Bladefist"] = "대족장 카르가스 블레이드피스트",
["Warchief Rend Blackhand"] = "대족장 렌드 블랙핸드",
["Warden Mellichar"] = "교도관 멜리챠르",
["Warder Stilgiss"] = "문지기 스틸기스",
["Warlord Kalithresh"] = "장군 칼리스레쉬",
["War Master Voone"] = "대장군 부네",
["Warmaul Champion"] = "전쟁망치일족 용사",
["Warp Slicer"] = "차원의 절단기",
["Warp Splinter"] = "차원의 분리자",
["Watchkeeper Gargolmar"] = "감시자 가르골마르",
Weaver = "위버",
["Witch Doctor Zum'rah"] = "의술사 줌라",
["Wolf Master Nandos"] = "늑대왕 난도스",
["Wrath-Scryer Soccothrates"] = "격노의 점술사 소코드라테스",
Wushoolay = "우슬레이",
Xevozz = "제보즈",
["XT-002 Deconstructor"] = "XT-002 해체자",
["Yogg-Saron"] = "요그사론",
Ysondre = "이손드레",
Zekkis = "젝키스",
["Zelemar the Wrathful"] = "진노의 젤레마르",
["Zereketh the Unbound"] = "속박이 풀린 제레케스",
Zerillis = "제릴리스",
["Zevrim Thornhoof"] = "제브림 쏜후프",
Zolo = "졸로",
["Zul'Farrak Dead Hero"] = "줄파락 죽음의 영웅",
["Zul'jin"] = "줄진",
["Zul'Lor"] = "줄로",
["Zul'tore"] = "줄토어",
["Zuramat the Obliterator"] = "파멸자 주라마트",
}
elseif GAME_LOCALE == "esES" then
lib:SetCurrentTranslations {
Acidmaw = "Fauceácida",
Aeonus = "Aeonus",
["Aerial Command Unit"] = "Unidad de mando aérea",
["Agathelos the Raging"] = "Agathelos el Furioso",
Ahune = "Ahune",
["Akil'zon"] = "Akil'zon",
["Aku'mai"] = "Aku'mai",
["Al'ar"] = "Al'ar",
["Algalon the Observer"] = "Algalon el Observador",
["Alzzin the Wildshaper"] = "Alzzin el Formaferal",
Amanitar = "Amanitar",
["Ambassador Flamelash"] = "Embajador Latifuego",
["Ambassador Hellmaw"] = "Embajador Faucinferno",
["Amnennar the Coldbringer"] = "Amnennar el Gélido",
["Ancient Stone Keeper"] = "Vigilante pétreo anciano",
Anetheron = "Anetheron",
["Anger'rel"] = "Anger'rel",
Anomalus = "Anomalus",
["Antu'sul"] = "Antu'sul",
["Anub'arak"] = "Anub'arak",
["Anubisath Defender"] = "Defensor Anubisath",
["Anubisath Guardian"] = "Guardián Anubisath",
["Anub'Rekhan"] = "Anub'Rekhan",
["Anub'shiah"] = "Anub'shiah",
Anzu = "Anzu",
["Arcane Watchman"] = "Vigilante Arcano",
["Arcanist Doan"] = "Arcanista Doan",
Archaedas = "Archaedas",
["Archavon the Stone Watcher"] = "Archavon el Vigía de piedra",
Archimonde = "Archimonde",
["Archivist Galford"] = "Archivista Galford",
["Archmage Arugal"] = "Archimago Arugal",
["Argent Confessor Paletress"] = "Confesora Argenta Cabelloclaro",
["Arugal's Voidwalker"] = "Abisario de Arugal",
["Assault Bot"] = "Robot de asalto",
["Atal'alarion"] = "Atal'alarion",
["Attumen the Huntsman"] = "Attumen el Montero",
Auriaya = "Auriaya",
Avalanchion = "Avalanchion",
["Avatar of Hakkar"] = "Avatar de Hakkar",
["Ayamiss the Hunter"] = "Ayamiss el Cazador",
Azgalor = "Azgalor",
["Azshir the Sleepless"] = "Azshir el Insomne",
Azuregos = "Azuregos",
["Bael'Gar"] = "Bael'Gar",
Baelog = "Baelog",
Balnazzar = "Balnazzar",
-- ["Baltharus the Warborn"] = "",
["Bannok Grimaxe"] = "Bannok Hachamacabra",
["Baron Aquanis"] = "Barón Aquanis",
["Baron Charr"] = "Barón Charr",
["Baroness Anastari"] = "Baronesa Anastari",
["Baron Geddon"] = "Barón Geddon",
["Baron Kazum"] = "Barón Kazum",
["Baron Rivendare"] = "Barón Rivendare",
["Baron Silverlaine"] = "Barón Filargenta",
["Battleguard Sartura"] = "Guardia de batalla Sartura",
["Bazil Thredd"] = "Bazil Thredd",
Bazzalan = "Bazzalan",
["Black Guard Swordsmith"] = "Armero Guardia Negra",
["Blackheart the Inciter"] = "Negrozón el Incitador",
["Blindeye the Seer"] = "Ciego el Vidente",
["Blind Hunter"] = "Cazador ciego",
["Blood Guard Porung"] = "Guardia de sangre Porung",
["Bloodlord Mandokir"] = "Señor sangriento Mandokir",
["Bloodmage Thalnos"] = "Mago sangriento Thalnos",
["Blood Prince Council"] = "Blood Prince Council", -- Needs review
["Blood Princes"] = "Príncipes de sangre", -- Needs review
["Blood-Queen Lana'thel"] = "Reina de sangre Lana’thel",
["Blood Steward of Kirtonos"] = "Administrador de sangre de Kirtonos",
Boahn = "Boahn",
["Bomb Bot"] = "Robot bum",
["Brain of Yogg-Saron"] = "Cerebro de Yogg-Saron",
["Brainwashed Noble"] = "Noble aducido",
Broggok = "Broggok",
Brokentoe = "Dedorroto",
Bronjahm = "Bronjahm",
["Broodlord Lashlayer"] = "Señor de prole Capazote",
["Bruegal Ironknuckle"] = "Bruegal Nudoferro",
Brutallus = "Brutallus",
["Burning Felguard"] = "Guarda vil ardiente",
["Buru the Gorger"] = "Buru el Manducador",
["Cache of the Firelord"] = "Botín del Señor del Fuego",
["Cannon Master Willey"] = "Cañonero Jefe Willey",
["Captain Greenskin"] = "Capitán Verdepel",
["Captain Kromcrush"] = "Capitán Kromcrush",
["Captain Skarloc"] = "Capitán Skarloc",
["Celebras the Cursed"] = "Celebras el Maldito",
["Charlga Razorflank"] = "Charlga Filonavaja",
["Chess Event"] = "Evento de ajedrez",
["Chest of The Seven"] = "Tesoro de los Siete",
["Chief Ukorz Sandscalp"] = "Jefe Ukorz Cabellarena",
["Cho'Rush the Observer"] = "Cho'Rush el Observador",
Chromaggus = "Chromaggus",
["Chrono Lord Deja"] = "Cronolord Deja",
["Chrono-Lord Epoch"] = "Chrono-Lord Epoch",
Claw = "Zarpa",
["Coilfang Elite"] = "Elite Colimillo Torcido",
["Coilfang Strider"] = "Zancudo Colmillo Torcido",
["Commander Kolurg"] = "Comandante Kolurg",
["Commander Sarannis"] = "Comandante Sarannis",
["Commander Springvale"] = "Comandante Vallefont",
["Commander Stoutbeard"] = "Comandante Barbarrecia",
["Constructor & Controller"] = "Constructor y Controlador",
Cookie = "El Chef",
["Coren Direbrew"] = "Coren Cerveza Temible",
["Cosmic Infuser"] = "Infusor cósmico",
["Crimson Hammersmith"] = "Forjamartillos Carmesí",
["Crowd Pummeler 9-60"] = "Gopleamasa 9-60",
["Crystal Fang"] = "Colmillor de cristal",
["C'Thun"] = "C'Thun",
Cyanigosa = "Cyanigosa",
["Dalliah the Doomsayer"] = "Dalliah la Decidora del Destino",
["Dalronn the Controller"] = "Dalronn el Controlador",
["Dark Iron Ambassador"] = "Embajador Hierro Negro",
["Darkmaster Gandling"] = "Maestro oscuro Gandling",
["Darkweaver Syth"] = "Tejeoscuro Syth",
-- ["Deathbound Ward"] = "",
["Deathbringer Saurfang"] = "Lamorte Saurfang",
["Death Knight Darkreaver"] = "Caballero de la Muerte Atracoscuro",
["Death Knight Understudy"] = "Suplente Caballero de la Muerte",
-- ["Deathspeaker High Priest"] = "",
["Death Speaker Jargba"] = "Médium Jargba",
["Deathstalker Visceri"] = "Mortacechador Visceri",
["Deathsworn Captain"] = "Capitán Juramorte",
Devastation = "Devastación",
["Deviate Faerie Dragon"] = "Dragón férico descarriado",
["Devourer of Souls"] = "Devoradora de almas",
["Dextren Ward"] = "Dextren Tutor",
["Digmaster Shovelphlange"] = "Maestro de excavación Palatiro",
["Doctor Theolen Krastinov"] = "Doctor Theolen Krastinov",
["Doom Lord Kazzak"] = "Señor Apocalíptico Kazzak",
["Doom'rel"] = "Doom'rel",
Doomwalker = "Caminante del Destino",
["Dope'rel"] = "Dope'rel",
Dorothee = "Dorothea",
["Drakkari Colossus"] = "Coloso Drakkari",
["Drakos the Interrogator"] = "Drakos el interrogador",
Dreadscale = "Aterraescama",
Dreamscythe = "Guadañasueños",
["Dust Covered Chest"] = "Cofre cubierto de polvo",
Dustwraith = "Ánima de polvo",
["Eadric the Pure"] = "Eadric el Puro",
["Earthcaller Halmgar"] = "Clamor de Tierra Halmgar",
Ebonroc = "Ebonroc",
["Eck the Ferocious"] = "Eck the Ferocious",
["Edwin VanCleef"] = "Edwin VanCleef",
["Elder Brightleaf"] = "Ancestro Hojabrillante",
["Elder Ironbranch"] = "Ancestro Hierrorrama",
["Elder Nadox"] = "Ancestro Nadox",
["Elder Stonebark"] = "Ancestro Cortezapiedra",
["Electrocutioner 6000"] = "Electrocutor 6000",
["Emalon the Storm Watcher"] = "Emalon el Vigía de la Tormenta",
Emeriss = "Emeriss",
["Emperor Dagran Thaurissan"] = "Emperador Dagran Thaurissan",
["Emperor Vek'lor"] = "Emperador Vek'lor",
["Emperor Vek'nilash"] = "Emperador Vek'nilash",
Entropius = "Entropius",
["Eonar's Gift"] = "Don de Eonar",
["Epoch Hunter"] = "Cazador de eras",
Erekem = "Erekem",
["Eressea Dawnsinger"] = "Eressea Cantoalba",
["Essence of Anger"] = "Esencia de Cólera",
["Essence of Desire"] = "Esencia de Deseo",
["Essence of Suffering"] = "Esencia de Sufrimiento",
Eviscerator = "Eviscerador",
["Exarch Maladaar"] = "Exarca Maladaar",
["Expedition Commander"] = "Comandante de expedición",
["Eydis Darkbane"] = "Eydis Penaumbra",
["Eye of C'Thun"] = "Ojo de C'Thun",
["Faction Champions"] = "Campeones de la facción",
["Fallen Champion"] = "Campeón caído",
Falric = "Falric",
["Falric and Marwyn"] = "Falric and Marwyn", -- Needs review
["Fankriss the Unyielding"] = "Fankriss el Implacable",
["Fathom-Lord Karathress"] = "Señor de la profundidades Karathress",
Felmyst = "Brumavil",
["Fenrus the Devourer"] = "Fenrus el Devorador",
["Feral Defender"] = "Defensor feral",
Festergut = "Panzachancro",
Feugen = "Feugen",
["Fineous Darkvire"] = "Finoso Virunegro",
Firemaw = "Faucefogo",
["Fjola Lightbane"] = "Fjola Penívea",
Flamegor = "Flamagor",
["Flame Leviathan"] = "Leviatán de llamas",
["Foreman Thistlenettle"] = "Supervisor Cardortiga",
["Forgemaster Garfrost"] = "Maestro de forja Gargelus",
["Four Horsemen Chest"] = "Cofre de los Cuatro Jinetes",
["Fras Siabi"] = "Fras Siabi",
Freya = "Freya",
["Gahz'ranka"] = "Gahz'ranka",
["Gahz'rilla"] = "Gahz'rilla",
["Gal'darah"] = "Gal'darah",
["Galgann Firehammer"] = "Galgann Flamartillo",
Garr = "Garr",
["Garrosh Hellscream"] = "Garrosh Grito Infernal",
Gasher = "Gasher",
["Gatewatcher Gyro-Kill"] = "Vígia de las puertas Giromata",
["Gatewatcher Iron-Hand"] = "Vigía de las puertas Manoyerro",
["Gathios the Shatterer"] = "Gathios the Shatterer",
Gehennas = "Gehennas",
Gelihast = "Gelihast",
Gelk = "Gelk",
["General Angerforge"] = "General Forjira",
["General Bjarngrim"] = "General Bjarngrim",
["General Drakkisath"] = "General Drakkisath",
["General Rajaxx"] = "General Rajaxx",
["General Vezax"] = "General Vezax",
-- ["General Zarithrian"] = "",
["Ghamoo-ra"] = "Ghamoo-ra",
["Ghaz'an"] = "Ghaz'an",
["Ghok Bashguud"] = "Ghok Bashguud",
Gilnid = "Gilnid",
["Gizrul the Slavener"] = "Gizrul el Esclavista",
["Gloom'rel"] = "Gloom'rel",
Gluth = "Gluth",
Glutton = "Glotón",
["Golemagg the Incinerator"] = "Golemagg el Incinerador",
["Golem Lord Argelmach"] = "Señor Golem Argelmach",
["Goraluk Anvilcrack"] = "Goraluk Yunquegrieta",
["Gormok the Impaler"] = "Gormok el Empalador",
["Gorosh the Dervish"] = "Gorosh el Endemoniado",
["Gortok Palehoof"] = "Gortok Pezuña Pálida",
["Gothik the Harvester"] = "Gothik el Cosechador",
["Grand Astromancer Capernian"] = "Gran astromántica Capernian",
["Grand Champions"] = "Grandes campeones",
["Grand Magus Telestra"] = "Gran maga Telestra",
["Grandmaster Vorpil"] = "Maestro mayor Vorpil",
Grandmother = "Abuela",
["Grand Warlock Alythess"] = "Bruja suprema Alythess",
["Grand Warlock Nethekurse"] = "Brujo supremo Malbisal",
["Grand Widow Faerlina"] = "Gran Viuda Faerlina",
["Grethok the Controller"] = "Grethok el Controlador",
["Gri'lek"] = "Gri'lek",
Grimlok = "Grimlok",
Grizzle = "\009Grisez",
Grobbulus = "Grobbulus",
Grubbis = "Grubbis",
["Gruul the Dragonkiller"] = "Gruul el Asesino de Dragones",
["Guard Fengus"] = "Guardia Fengus",
["Guardian of Yogg-Saron"] = "Guardián de Yogg-Saron",
["Guard Mol'dar"] = "Guardia Mol'dar",
["Guard Slip'kik"] = "Guardia Slip'kik",
["Gurtogg Bloodboil"] = "Gurtogg Sangre Hirviente",
Gyth = "Gyth",
Hadronox = "Hadronox",
Hakkar = "Hakkar",
Halazzi = "Halazzi",
-- Halion = "",
Halycon = "Halycon",
Hamhock = "Hamhock",
["Harbinger Skyriss"] = "Presagista Cieloriss",
["Hate'rel"] = "Odio'rel",
["Hazza'rah"] = "Hazza'rah",
Hazzas = "Hazzas",
["Headless Horseman"] = "Cofre de los Cuatro Jinetes",
["Hearthsinger Forresten"] = "Escupezones Foreste",
["Hedrum the Creeper"] = "Hedrum el Trepador",
["Heigan the Unclean"] = "Heigan el Impuro",
["Hellfire Channeler"] = "Canalizador Fuego Infernal",
["Henry Stern"] = "Henry Stern",
["Herald Volazj"] = "Heraldo Volazj",
Herod = "Herod",
["Hex Lord Malacrass"] = "Señor aojador Malacrass",
["High Astromancer Solarian"] = "Gran astromántica Solarian",
["High Botanist Freywinn"] = "Gran botánico Freywinn",
["High Inquisitor Fairbanks"] = "Alto Inquisidor Ribalimpia",
["High Inquisitor Whitemane"] = "Alta Inquisidora Melenablanca",
["High Interrogator Gerstahn"] = "Alto Interrogador Gerstahn",
["High King Maulgar"] = "Su majestad Maulgar",
["Highlord Mograine"] = "Alto Señor Mograine",
["Highlord Omokk"] = "Alto Señor Omokk",
["High Marshal Whirlaxis"] = "High Marshal Whirlaxis",
["High Nethermancer Zerevor"] = "High Nethermancer Zerevor",
["High Overlord Saurfang"] = "Alto señor supremo Colmillosauro",
["High Priestess Arlokk"] = "Suma Sacerdotisa Arlokk",
["High Priestess Jeklik"] = "Suma Sacerdotisa Jeklik",
["High Priestess Mar'li"] = "Suma Sacerdotisa Mar'li",
["High Priestess of Thaurissan"] = "Alta Sacerdotisa de Thaurissan",
["High Priest Thekal"] = "Sumo Sacerdote Thekal",
["High Priest Venoxis"] = "Sumo Sacerdote Venoxis",
["High Warlord Naj'entus"] = "Gran Señor de la Guerra Naj'entus",
Hodir = "Hodir",
["Houndmaster Grebmar"] = "Maestro de canes Grebmar",
["Houndmaster Loksey"] = "Maestro de canes Loksey",
Hukku = "Hukku",
Hungarfen = "Panthambre",
["Hurley Blackbreath"] = "Hurley Negrálito",
["Hyakiss the Lurker"] = "Hyakiss el Rondador",
["Hydromancer Thespia"] = "Hidromántico Thespia",
["Hydromancer Velratha"] = "Hidromántica Velratha",
Hydrospawn = "Hidromilecio",
["Hydross the Unstable"] = "Hydross el Inestable",
["Icecrown Gunship Battle"] = "Batalla aerea", -- Needs review
Icehowl = "Aullahielo",
["Ice Sphere"] = "Ice Sphere", -- Needs review
Ichoron = "Icoron",
Ick = "Ick", -- Needs review
["Ignis the Furnace Master"] = "Ignis el Maestro de la Caldera",
["Illidan Stormrage"] = "Illidan Tempestira",
["Illidari Council"] = "Concilio Illidari",
["Illyanna Ravenoak"] = "Illyanna Roblecuervo",
["Immol'thar"] = "Immol'thar",
["Infinite Corruptor"] = "Corruptor Infinito",
["Infinity Blades"] = "Hojas de infinidad",
["Ingvar the Plunderer"] = "Ingvar the Plunderer",
["Instructor Malicia"] = "Instructor Malicia",
["Instructor Razuvious"] = "Instructor Razuvious",
["Interrogator Vishas"] = "Interrogador Vishas",
Ionar = "Ionar",
Ironaya = "Hierraya",
Ironspine = "Dorsacerado",
Isalien = "Isalien",
Jade = "Jade",
["Jammal'an the Prophet"] = "Jammal'an el Profeta",
["Jan'alai"] = "Jan'alai",
["Jandice Barov"] = "Jandice Barov",
["Jedoga Shadowseeker"] = "Jedoga Buscasombras",
["Jed Runewatcher"] = "Jed vigía de las runas",
["Jergosh the Invoker"] = "Jergosh el Convocador",
["Jin'do the Hexxer"] = "Jin'do el Aojador",
["Jormungar Behemoth"] = "Behemoth Jormungar",
Jormungars = "jormungar",
Julianne = "Julianne",
["Junk Bot"] = "Chatarrobot",
["Kael'thas Sunstrider"] = "Kael'thas Caminante del Sol",
Kalecgos = "Kalecgos",
["Kam Deepfury"] = "Kam Furiahonda",
["Kazkaz the Unholy"] = "Kazkaz el Blasfemo",
["Kaz'rogal"] = "Kaz'rogal",
["Keli'dan the Breaker"] = "Keli'dan el Ultrajador",
["Kel'Thuzad"] = "Kel'Thuzad",
Keristrasza = "Keristrasza",
["Kiggler the Crazed"] = "Kiggler el Enloquecido",
["Kil'jaeden"] = "Kil'jaeden",
["Kil'rek"] = "Kil'rek",
["King Dred"] = "Rey Dred",
["King Gordok"] = "Rey Gordok",
["King Llane Piece"] = "Rey Llane",
["King Ymiron"] = "Rey Ymiron",
["Kirtonos the Herald"] = "Kirtonos el Heraldo",
["Knot Thimblejack's Cache"] = "Carretilla de Knot Llavededo",
Kolk = "Kolk",
Kologarn = "Kologarn",
["Koralon the Flame Watcher"] = "Koralon el Vigía de las llamas",
Kormok = "Kormok",
Kresh = "Kresh",
Krick = "Krick", -- Needs review
["Krick and Ick"] = "Krick and Ick", -- Needs review
["Krik'thir the Gatewatcher"] = "Krik’thir el vígia de las puertas",
["Krosh Firehand"] = "Krosh Manofuego",
Krystallus = "Krystallus",
Kurinnaxx = "Kurinnaxx",
["Lady Anacondra"] = "Lady Anacondra",
["Lady Blaumeux"] = "Lady Blaumeux",
["Lady Deathwhisper"] = "Lady Susurramuerte",
["Lady Illucia Barov"] = "Lady Illucia Barov",
["Lady Malande"] = "Lady Malande",
["Lady Sacrolash"] = "Lady Sacrolash",
["Lady Sarevess"] = "Lady Sarevess",
["Lady Vashj"] = "Lady Vashj",
Laj = "Laj",
Landslide = "Derrumblo",
Lavanthor = "Lavanthor",
["Left Arm"] = "Brazo izquierdo",
["Leotheras the Blind"] = "Leotheras el Ciego",
Lethon = "Lethon",
Lethtendris = "Lethtendris",
["Leviathan Mk II"] = "Mk II de leviatán",
["Ley-Guardian Eregos"] = "Guardian-Ley Eregos",
["Lieutenant Drake"] = "Teniente Draco",
["Lieutenant General Andorov"] = "Teniente General Andorov",
Loatheb = "Loatheb",
Loken = "Loken",
["Lord Alexei Barov"] = "Lord Alexei Barov",
["Lord Cobrahn"] = "Lord Cobrahn",
["Lord Hel'nurath"] = "Lord Hel'nurath",
["Lord Incendius"] = "Lord Incendius",
["Lord Jaraxxus"] = "Lord Jaraxxus",
["Lord Kazzak"] = "Lord Kazzak",
["Lord Kri"] = "Lord Kri",
["Lord Marrowgar"] = "Lord Tuétano",
["Lord Pythas"] = "Lord Pythas",
["Lord Roccor"] = "Lord Roccor",
["Lord Sanguinar"] = "Lord Sanguinar",
["Lord Serpentis"] = "Lord Serpentis",
["Lord Skwol"] = "Lord Skwol",
["Lord Valthalak"] = "Lord Valthalak",
["Lord Victor Nefarius"] = "Lord Víctor Nefarius",
["Lord Vyletongue"] = "Lord Lenguavil",
["Lorekeeper Polkelt"] = "Tradicionalista Polkelt",
Loro = "Loro",
Lucifron = "Lucifron",
["Mad Magglish"] = "Magglish el Loco",
Maexxna = "Maexxna",
["Mage-Lord Urom"] = "Señor de la Magia Urom",
["Magister Kalendris"] = "Magister Kalendris",
["Magistrate Barthilas"] = "Magistrado Barthilas",
Magmadar = "Magmadar",
Magmus = "Magmus",
Magra = "Magra",
Magtheridon = "Magtheridon",
["Maiden of Grief"] = "Doncella de Pena",
["Maiden of Virtue"] = "Doncella de Virtud",
["Majordomo Executus"] = "Mayordomo Executus",
Malacrass = "Malacrass",
["Maleki the Pallid"] = "Maleki el Pálido",
["Mal'Ganis"] = "Mal'Ganis",
Malygos = "Malygos",
Maraudos = "Maraudos",
["Marduk Blackpool"] = "Marduz Pozonegro",
["Marisa du'Paige"] = "Marisa du'Paige",
Marwyn = "Marwyn",
["Master Engineer Telonicus"] = "Maestro Ingeriero Telonicus",
["Maur Grimtotem"] = "Maur Tótem Siniestro",
Meathook = "Meathook",
["Mechano-Lord Capacitus"] = "Lord-mecano Capacitus",
Medivh = "Medivh",
["Mekgineer Steamrigger"] = "Mekigeniero Vaporino",
["Mekgineer Thermaplugg"] = "Mekigeniero Termochufe",
["Mennu the Betrayer"] = "Mennu el Traidor",
["Meshlok the Harvester"] = "Meshlok el Cosechador",
Midnight = "Medianoche",
Mijan = "Mijar",
Mimiron = "Mimiron",
["Miner Johnson"] = "Minero Johnson",
["Mistress of Pain"] = "Maestra de dolor",
Moam = "Moam",
Mogor = "Mogor",
["Mokra the Skullcrusher"] = "Mokra el Trituracráneos",
Moorabi = "Moorabi",
Moragg = "Moragg",
["Mordresh Fire Eye"] = "Mordresh Ojo de Fuego",
["Mor Grayhoof"] = "Mor Grayhoof",
Moroes = "Moroes",
["Morogrim Tidewalker"] = "Morogrim Levantamareas",
Morphaz = "Morphaz",
["Mother Shahraz"] = "Madre Shahraz",
["Mother Smolderweb"] = "Madre Telabrasada",
["Mr. Smite"] = "Sr. Golpin",
["Muradin Bronzebeard"] = "Muradin Barbabronce",
["Murkblood Twin"] = "Gemelo Sangreoscura",
["Murkblood Twins"] = "Gemelos Sangreoscura",
Murmur = "Murmur",
["Murta Grimgut"] = "Murta Tripuriosa",
["M'uru"] = "M'uru",
Mushgog = "Mushgog",
["Mutanus the Devourer"] = "Mutanus el Devorador",
Nalorakk = "Nalorakk",
Nazan = "Nazan",
Nefarian = "Nefarian",
["Nekrum Gutchewer"] = "Nekrum Cometripas",
["Nerub'enkan"] = "Nerub'enkan",
["Nethermancer Sepethrea"] = "Abisálico Sepethrea",
Netherspite = "Rencor abisal",
["Netherstrand Longbow"] = "Arco largo de fibra abisal",
["Nexus-Prince Shaffar"] = "Príncipe-nexo Shaffar",
Nightbane = "Nocturno",
["Noth the Plaguebringer"] = "Noth el Pesteador",
["Novos the Summoner"] = "Novos el Invocador",
Noxxion = "Noxxion",
["Obsidian Sentinel"] = "Centinela Obsidiano",
["Odo the Blindwatcher"] = "Odo el vigía ciego",
["Ogom the Wretched"] = "Ogom el Desdichado",
["Ok'thor the Breaker"] = "Ok'thor el Rompedor",
["Old Serra'kis"] = "Viejo Serra'kis",
["Olm the Summoner"] = "Olm el Invocador",
["Omor the Unscarred"] = "Omor el Sinmarcas",
Onyxia = "Onyxia",
["Orgrim's Hammer"] = "Martillo de Orgrim",
["Ormorok the Tree-Shaper"] = "Ormorok el cortador de árboles",
["Oro Eyegouge"] = "Oro Bocojo ",
["Ossirian the Unscarred"] = "Osirio el Sinmarcas",
Ouro = "Ouro",
["Overlord Ramtusk"] = "Señor Supremo Colmicarnero",
["Overlord Wyrmthalak"] = "Señor Supremo Vermiothalak",
["Overmaster Pyron"] = "Gran maestro Pyron",
["Overseer Tidewrath"] = "Avizor Aleta de Cólera",
Pandemonius = "Pandemonius",
["Panzor the Invincible"] = "Panzor el Invencible",
Patchwerk = "Remendejo",
["Pathaleon the Calculator"] = "Panthaleon el Calculador",
Phalanx = "Falange",
["Phaseshift Bulwark"] = "Baluarte de cambio de fase",
Pimgib = "Pimgib",
["Plaguemaw the Rotting"] = "Fauzpeste el Putrefacto",
["Plugger Spazzring"] = "Plugger Aropatoso",
["Postmaster Malown"] = "Jefe de correos Malown",
["Priestess Delrissa"] = "Sacerdotisa Delrissa",
["Prince Keleseth"] = "Príncipe Keleseth",
["Prince Malchezaar"] = "Príncipe Malchezaar",
["Prince Skaldrenox"] = "Príncipe Skaldrenox",
["Princess Huhuran"] = "Princesa Huhuran",
["Princess Moira Bronzebeard"] = "Princesa Moira Barbabronce",
["Princess Tempestria"] = "Princesa Tempestria",
["Princess Theradras"] = "Princesa Theradras",
["Princess Yauj"] = "Princesa Yauj",
["Prince Taldaram"] = "Príncipe Taldaram",
["Prince Tenris Mirkblood"] = "Príncipe Tenris Sangre Penumbra",
["Prince Tortheldrin"] = "Príncipe Tortheldrin",
["Prince Valanar"] = "Príncipe Valanar",
["Professor Putricide"] = "Profesor Putricidio",
["Pure Spawn of Hydross"] = "Engendro puro de Hydross",
Pusillin = "Pusillín",
["Pyroguard Emberseer"] = "Piroguardián Brasadivino",
["Pyromancer Loregrain"] = "Piromántico Cultugrano",
Quagmirran = "Quagmirran",
["Quartermaster Zigris"] = "Intendente Zigris",
["Rage Winterchill"] = "Ira Fríoinvierno",
Ragglesnout = "Morrandrajos",
["Raging Spirit"] = "Raging Spirit", -- Needs review
Ragnaros = "Ragnaros",
["Ramstein the Gorger"] = "Ramstein el Empachador",
["Ras Frostwhisper"] = "Ras Levescarcha",
Rattlegore = "Traquesangre",
["Razorclaw the Butcher"] = "Zarpador el Carnicero",
["Razorgore the Untamed"] = "Sangrevaja el Indomable",
Razorlash = "Lativaja",
Razorscale = "Tajoescama",
["Reliquary of Souls"] = "Relicario de Almas",
Renataki = "Renataki",
["Restless Skeleton"] = "Esqueleto inquieto",
Rethilgore = "Rethilgore", -- Needs review
Revelosh = "Revelosh",
["Rhahk'Zor"] = "Rhahk'Zor",
["Ribbly Screwspigot"] = "Ribbly Llavenrosca",
["Right Arm"] = "Brazo derecho",
Roar = "Rugido",
["Rokad the Ravager"] = "Rokad el Devastador",
["Rokdar the Sundered Lord"] = "Rokdar el Señor Hendido",
["Rokmar the Crackler"] = "Rokmar el Crujidor",
Romulo = "Romulo",
["Romulo & Julianne"] = "Romeo y Julieta",
Rotface = "Carapútrea",
Rotgrip = "Escamapodrida",
["Runemaster Molgeim"] = "Maestro de runas Molgeim",
["Runok Wildmane"] = "Runok Ferocrín",
Ruuzlu = "Ruuzlu",
["Salramm the Fleshcrafter"] = "Salramm el Modelador de carne",
["Sanctum Sentry"] = "Centinela del sagrario",
["Sandarr Dunereaver"] = "Sandarr Asaltadunas",
["Sandfury Executioner"] = "Ejecutor Furiarena",
Sapphiron = "Sapphiron",
Sara = "Sara",
["Saronite Animus"] = "Animus de saronita",
Sartharion = "Sartharion",
["Sathrovarr the Corruptor"] = "Sathrovarr el Corruptor",
-- ["Saviana Ragefire"] = "",
["Scarlet Commander Mograine"] = "Comandante Escarlata Mograine",
["Scourgelord Tyrannus"] = "Señor de la Plaga Tyrannus",
["Seeth'rel"] = "Seeth'rel",
["Selin Fireheart"] = "Selin Corazón de Fuego",
["Sergeant Bly"] = "Sargento Bly",
["Shade of Akama"] = "Sombra de Akama",
["Shade of Aran"] = "Sombra de Aran",
["Shade of Eranikus"] = "Sombra de Eranikus",
["Shadikith the Glider"] = "Shadikith the Glider",
["Shadow Hunter Vosh'gajin"] = "Cazador de las Sombras Vosh'gajin",
["Shadow of Leotheras"] = "Sombra de Leotheras",
["Shadowpriest Sezz'ziz"] = "Sacerdote oscuro Sezz'ziz",
Shadron = "Shadron",
Shazzrah = "Shazzrah",
["Shirrak the Dead Watcher"] = "Shirrak el Vigía de los Muertos",
Sindragosa = "Sindragosa",
["Sir Zeliek"] = "Sir Zeliek",
["Sjonnir The Ironshaper"] = "Sjonnir el afilador",
["Skadi the Ruthless"] = "Skadi el Despiadado",
["Skarr the Unbreakable"] = "Skarr el Inquebrantable",
["Skarvald the Constructor"] = "Skarvald el Constructor",
["Skra'gath"] = "Skra'gath",
Skul = "Skul",
Skum = "Skum",
["Slad'ran"] = "Slad'ran",
Sneed = "Sneed",
["Sneed's Shredder"] = "Machacador de Sneed",
["Solakar Flamewreath"] = "Solakar Corona de Fuego",
["Solarium Agent"] = "Agente Solarium",
["Solarium Priest"] = "Sacerdote Solarium",
["Spirestone Battle Lord"] = "Señor de batalla Cumbrerroca",
["Spirestone Butcher"] = "Carnicero Cumbrerroca",
["Spirestone Lord Magus"] = "Señor Magus Cumbrerroca",
["Staff of Disintegration"] = "Bastón de desintegración",
Stalagg = "Stalagg",
Steelbreaker = "Rompeacero",
["Stomper Kreeg"] = "Vapuleador Kreeg",
Stonespine = "Pidrespina",
["Stormcaller Brundir"] = "Clamatormentas Brundir",
Strawman = "Espantapájaros",
["Sulfuron Harbinger"] = "Sulfuron Presagista",
Supremus = "Supremus",
["Svala Sorrowgrave"] = "Svala Tumbapena",
["Swamplord Musel'ek"] = "Señor del pantano Musel'ek",
Taerar = "Taerar",
["Tainted Spawn of Hydross"] = "Engendro de Hydross corrupto",
["Talon King Ikiss"] = "Rey Garra Ikiss",
["Taragaman the Hungerer"] = "Taragaman el Hambriento",
["Targorr the Dread"] = "Targor el Pavoroso",
Tavarok = "Tavarok",
Techbot = "Tecnobot",
Temporus = "Temporus",
["Tendris Warpwood"] = "Tendris Madeguerra",
Tenebron = "Tenebron",
["Terestian Illhoof"] = "Terestian Pezuña Enferma",
["Teron Gorefiend"] = "Teron Sanguino",
Thaddius = "Thaddius",
["Thaladred the Darkener"] = "Thaladred el Oscurecedor",
["Thane Korth'azz"] = "Thane Korth'azz",
["The Beast"] = "La Bestia",
["The Beasts of Northrend"] = "Las bestias de Rasganorte",
["The Big Bad Wolf"] = "El Gran Lobo Malvado",
["The Black Knight"] = "El Caballero Negro",
["The Black Stalker"] = "La acechadora negra",
["The Blue Brothers"] = "Los Hermanos Azules",
["The Bug Family"] = "La Familia Insecto",
["The Crone"] = "La Vieja Bruja",
["The Curator"] = "Curator",
["The Eredar Twins"] = "Los Gemelos Eredar",
["The Four Horsemen"] = "Los Cuatro Jinetes",
["The Illidari Council"] = "El concilio Illidari",
["The Iron Council"] = "La Asamblea de Hierro",
["Theka the Martyr"] = "Theka la Mártir",
["The Lich King"] = "El Rey Exánime",
["The Lurker Below"] = "El Rondador de abajo",
["The Maker"] = "El Hacedor",
["The Prophet Skeram"] = "El profeta Skeram",
["The Prophet Tharon'ja"] = "El Profeta Tharon'ja",
["The Ravenian"] = "El Devorador",
["The Razza"] = "El Razza",
["The Seven Dwarves"] = "Los Siete Enanitos",
["The Skybreaker"] = "El Rompecielos",
["The Tribunal of Ages"] = "Cofre del Tribunal",
["The Twin Emperors"] = "Los Emperadores Gemelos",
["The Twin Val'kyr"] = "Gemelas Val'kyr",
["The Unforgiven"] = "El Imperdonable",
["The Windreaver"] = "El Atracavientos",
Thorim = "Thorim",
["Thorngrin the Tender"] = "Thorngrin el Tierno",
["Tidewalker Lurker"] = "Rondador Levantamareas",
["Timmy the Cruel"] = "Timmy el Cruel",
Tinhead = "Cabezalata",
["Tinkerer Gizlock"] = "Manitas Gizlock",
["Tirion Fordring"] = "Tirion Vadín",
Tito = "Tito",
["Toravon the Ice Watcher"] = "Toravon the Ice Watcher", -- Needs review
["Trigore the Lasher"] = "Trigore el Azotador",
Trollgore = "Cuernotroll",
["Tsu'zee"] = "Tsu'zee",
["Tuten'kash"] = "Tuten'kash",
["Twilight Lord Kelris"] = "Señor Crepuscular Kelris",
["Urok Doomhowl"] = "Urok Aullapocalipsis",
["Vaelastrasz the Corrupt"] = "Vaelastrasz el Corrupto",
["Valithria Dreamwalker"] = "Valithria Caminasueños",
["Val'kyr Shadowguard"] = "Val'kyr Shadowguard", -- Needs review
["Varian Wrynn"] = "Varian Wrynn",
["Varos Cloudstrider"] = "Varos Cloudstrider",
Vazruden = "Vazruden",
["Vazruden the Herald"] = "Vazruden el Heraldo",
Vectus = "Vectus",
Vem = "Vem",
Veng = "Veng",
["Veras Darkshadow"] = "Veras Darkshadow",
["Verdan the Everliving"] = "Verdan el Eterno",
Verek = "Verek",
Vesperon = "Vesperon",
Vexallus = "Vexallus",
["Veyzhak the Cannibal"] = "Veyzhak el Caníbal",
["Vile'rel"] = "Vil'rel",
Viscidus = "Viscidus",
["Viscous Fallout"] = "Radiactivo viscoso",
["Void Reaver"] = "Atracador del vacío",
Volkhan = "Volkhan",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "Belisario O'mrogg",
["Warchief Blackhand Piece"] = "Jefe de Guerra Mano Negra",
["Warchief Kargath Bladefist"] = "Jefe de Guerra Kargath Garrafilada",
["Warchief Rend Blackhand"] = "Jefe de Guerra Desgarro Puño Negro",
["Warden Mellichar"] = "Celador Mellichar",
["Warder Stilgiss"] = "Guarda Stilgiss",
["Warlord Kalithresh"] = "Señor de la Guerra Kalithresh",
["War Master Voone"] = "Maestro de guerra Voone",
["Warmaul Champion"] = "Campeón Mazo de Guerra",
["Warp Slicer"] = "Cercenadora de distorsión",
["Warp Splinter"] = "Disidente de distorsión",
["Watchkeeper Gargolmar"] = "Guardián vigía Gargolmar",
Weaver = "Sastrón",
["Witch Doctor Zum'rah"] = "Médico brujo Zum'rah",
["Wolf Master Nandos"] = "Maestro de lobos Nandos",
["Wrath-Scryer Soccothrates"] = "Arúspice de cólera Soccothrates",
Wushoolay = "Wushoolay",
Xevozz = "Xevozz",
["XT-002 Deconstructor"] = "Desarmador XA-002",
["Yogg-Saron"] = "Yogg-Saron",
Ysondre = "Ysondre",
Zekkis = "Zekkis",
["Zelemar the Wrathful"] = "Zelemar el Colérico",
["Zereketh the Unbound"] = "Zereketh el Desatado",
Zerillis = "Zerillis",
["Zevrim Thornhoof"] = "Zevrim Pezuñahendida",
Zolo = "Zolo",
["Zul'Farrak Dead Hero"] = "Héroe muerto Zul'Farrak",
["Zul'jin"] = "Zul'jin",
["Zul'Lor"] = "Zul'Lor",
["Zul'tore"] = "Zul'tore",
["Zuramat the Obliterator"] = "Zuramat el Obliterador",
}
elseif GAME_LOCALE == "esMX" then
lib:SetCurrentTranslations {
Acidmaw = "Fauceácida",
Aeonus = "Aeonus",
["Aerial Command Unit"] = "Unidad de mando aérea",
["Agathelos the Raging"] = "Agathelos el Furioso",
Ahune = "Ahune",
["Akil'zon"] = "Akil'zon",
["Aku'mai"] = "Aku'mai",
["Al'ar"] = "Al'ar",
["Algalon the Observer"] = "Algalon el Observador",
["Alzzin the Wildshaper"] = "Alzzin el Formaferal",
Amanitar = "Amanitar",
["Ambassador Flamelash"] = "Embajador Latifuego",
["Ambassador Hellmaw"] = "Embajador Faucinferno",
["Amnennar the Coldbringer"] = "Amnennar el Gélido",
["Ancient Stone Keeper"] = "Vigilante pétreo anciano",
Anetheron = "Anetheron",
["Anger'rel"] = "Anger'rel",
Anomalus = "Anomalus",
["Antu'sul"] = "Antu'sul",
["Anub'arak"] = "Anub'arak",
["Anubisath Defender"] = "Defensor Anubisath",
["Anubisath Guardian"] = "Guardián Anubisath",
["Anub'Rekhan"] = "Anub'Rekhan",
["Anub'shiah"] = "Anub'shiah",
Anzu = "Anzu",
["Arcane Watchman"] = "Vigilante Arcano",
["Arcanist Doan"] = "Arcanista Doan",
Archaedas = "Archaedas",
["Archavon the Stone Watcher"] = "Archavon el vigía de piedra",
Archimonde = "Archimonde",
["Archivist Galford"] = "Archivista Galford",
["Archmage Arugal"] = "Archimago Arugal",
["Argent Confessor Paletress"] = "confesora Argenta Cabelloclaro",
["Arugal's Voidwalker"] = "Abisario de Arugal",
["Assault Bot"] = "Robot de asalto",
["Atal'alarion"] = "Atal'alarion",
["Attumen the Huntsman"] = "Attumen el Montero",
Auriaya = "Auriaya",
Avalanchion = "Avalanchion",
["Avatar of Hakkar"] = "Avatar de Hakkar",
["Ayamiss the Hunter"] = "Ayamiss el Cazador",
Azgalor = "Azgalor",
["Azshir the Sleepless"] = "Azshir el Insomne",
Azuregos = "Azuregos",
["Bael'Gar"] = "Bael'Gar",
Baelog = "Baelog",
Balnazzar = "Balnazzar",
-- ["Baltharus the Warborn"] = "",
["Bannok Grimaxe"] = "Bannok Hachamacabra",
["Baron Aquanis"] = "Barón Aquanis",
["Baron Charr"] = "Barón Charr",
["Baroness Anastari"] = "Baronesa Anastari",
["Baron Geddon"] = "Barón Geddon",
["Baron Kazum"] = "Barón Kazum",
["Baron Rivendare"] = "Barón Osahendido",
["Baron Silverlaine"] = "Barón Filargenta",
["Battleguard Sartura"] = "Guardia de batalla Sartura",
["Bazil Thredd"] = "Bazil Thredd",
Bazzalan = "Bazzalan",
["Black Guard Swordsmith"] = "Armero Guardia Negra",
["Blackheart the Inciter"] = "Negrozón el Incitador",
["Blindeye the Seer"] = "Ciego el Vidente",
["Blind Hunter"] = "Cazador ciego",
["Blood Guard Porung"] = "Guardia de sangre Porung",
["Bloodlord Mandokir"] = "Señor sangriento Mandokir",
["Bloodmage Thalnos"] = "Mago sangriento Thalnos",
["Blood Prince Council"] = "Consejo de Príncipes de Sangre",
["Blood Princes"] = "Príncipes de Sangre",
["Blood-Queen Lana'thel"] = "Reina de Sangre Lana'thel",
["Blood Steward of Kirtonos"] = "Administrador de sangre de Kirtonos",
Boahn = "Boahn",
["Bomb Bot"] = "Robot bum",
["Brain of Yogg-Saron"] = "Cerebro de Yogg-Saron",
["Brainwashed Noble"] = "Noble aducido",
Broggok = "Broggok",
Brokentoe = "Dedorroto",
Bronjahm = "Bronjahm",
["Broodlord Lashlayer"] = "Señor de prole Capazote",
["Bruegal Ironknuckle"] = "Bruegal Nudoferro",
Brutallus = "Brutallus",
["Burning Felguard"] = "Guarda vil ardiente",
["Buru the Gorger"] = "Buru el Manducador",
["Cache of the Firelord"] = "Botín del Señor del Fuego",
["Cannon Master Willey"] = "Cañonero Jefe Willey",
["Captain Greenskin"] = "Capitán Verdepel",
["Captain Kromcrush"] = "Capitán Kromcrush",
["Captain Skarloc"] = "Capitán Skarloc",
["Celebras the Cursed"] = "Celebras el Maldito",
["Charlga Razorflank"] = "Charlga Filonavaja",
["Chess Event"] = "Evento de ajedrez",
["Chest of The Seven"] = "Tesoro de los Siete",
["Chief Ukorz Sandscalp"] = "Jefe Ukorz Cabellarena",
["Cho'Rush the Observer"] = "Cho'Rush el Observador",
Chromaggus = "Chromaggus",
["Chrono Lord Deja"] = "Cronolord Deja",
["Chrono-Lord Epoch"] = "Cronolord Época",
Claw = "Zarpa",
["Coilfang Elite"] = "Elite Colimillo Torcido",
["Coilfang Strider"] = "Zancudo Colmillo Torcido",
["Commander Kolurg"] = "Comandante Kolurg",
["Commander Sarannis"] = "Comandante Sarannis",
["Commander Springvale"] = "Comandante Vallefont",
["Commander Stoutbeard"] = "Comandante Barbarrecia",
["Constructor & Controller"] = "Constructor & Controlador",
Cookie = "El Chef",
["Coren Direbrew"] = "Coren Cerveza Temible",
["Cosmic Infuser"] = "Infusor cósmico",
["Crimson Hammersmith"] = "Forjamartillos Carmesí",
["Crowd Pummeler 9-60"] = "Gopleamasa 9-60",
["Crystal Fang"] = "Colmillor de cristal",
["C'Thun"] = "C'Thun",
Cyanigosa = "Cyanigosa",
["Dalliah the Doomsayer"] = "Dalliah la Decidora del Destino",
["Dalronn the Controller"] = "Dalronn el Controlador",
["Dark Iron Ambassador"] = "Embajador Hierro Negro",
["Darkmaster Gandling"] = "Maestro oscuro Gandling",
["Darkweaver Syth"] = "Tejeoscuro Syth",
["Deathbound Ward"] = "Depositario vinculado a la muerte",
["Deathbringer Saurfang"] = "Libramorte Colmillosauro",
["Death Knight Darkreaver"] = "Caballero de la Muerte Atracoscuro",
["Death Knight Understudy"] = "Suplente Caballero de la Muerte",
["Deathspeaker High Priest"] = "Sumo sacerdote portavoz de la muerte",
["Death Speaker Jargba"] = "Médium Jargba",
["Deathstalker Visceri"] = "Mortacechador Visceri",
["Deathsworn Captain"] = "Capitán Juramorte",
Devastation = "Devastación",
["Deviate Faerie Dragon"] = "Dragón férico descarriado",
["Devourer of Souls"] = "Devorador de Almas",
["Dextren Ward"] = "Dextren Tutor",
["Digmaster Shovelphlange"] = "Maestro de excavación Palatiro",
["Doctor Theolen Krastinov"] = "Doctor Theolen Krastinov",
["Doom Lord Kazzak"] = "Señor Apocalíptico Kazzak",
["Doom'rel"] = "Doom'rel",
Doomwalker = "Caminante del Destino",
["Dope'rel"] = "Dope'rel",
Dorothee = "Dorothea",
["Drakkari Colossus"] = "Coloso Drakkari",
["Drakos the Interrogator"] = "Drakos el Interrogador",
Dreadscale = "Aterraescama",
Dreamscythe = "Guadañasueños",
["Dust Covered Chest"] = "Cofre cubierto de polvo",
Dustwraith = "Ánima de polvo",
["Eadric the Pure"] = "Eadric el Puro",
["Earthcaller Halmgar"] = "Clamor de Tierra Halmgar",
Ebonroc = "Ebonroc",
["Eck the Ferocious"] = "Eck el Feroz",
["Edwin VanCleef"] = "Edwin VanCleef",
["Elder Brightleaf"] = "Ancestro Hojabrillante",
["Elder Ironbranch"] = "Ancestro Hierrorrama",
["Elder Nadox"] = "Ancestro Nadox",
["Elder Stonebark"] = "Ancestro Cortezapiedra",
["Electrocutioner 6000"] = "Electrocutor 6000",
["Emalon the Storm Watcher"] = "Emalon e Viagía de la Tormenta",
Emeriss = "Emeriss",
["Emperor Dagran Thaurissan"] = "Emperador Dagran Thaurissan",
["Emperor Vek'lor"] = "Emperador Vek'lor",
["Emperor Vek'nilash"] = "Emperador Vek'nilash",
Entropius = "Entropius",
["Eonar's Gift"] = "Don de Eonar",
["Epoch Hunter"] = "Cazador de eras",
Erekem = "Erekem",
["Eressea Dawnsinger"] = "Eressea Cantoalba",
["Essence of Anger"] = "Esencia de Cólera",
["Essence of Desire"] = "Esencia de Deseo",
["Essence of Suffering"] = "Esencia de Sufrimiento",
Eviscerator = "Eviscerador",
["Exarch Maladaar"] = "Exarca Maladaar",
["Expedition Commander"] = "Comandante de expedición",
["Eydis Darkbane"] = "Eydis Penaumbra",
["Eye of C'Thun"] = "Ojo de C'Thun",
["Faction Champions"] = "Campeones de Facción",
["Fallen Champion"] = "Campeón caído",
Falric = "Falric",
["Falric and Marwyn"] = "Falric y Marwyn",
["Fankriss the Unyielding"] = "Fankriss el Implacable",
["Fathom-Lord Karathress"] = "Señor de la profundidades Karathress",
Felmyst = "Brumavil",
["Fenrus the Devourer"] = "Fenrus el Devorador",
["Feral Defender"] = "Defensor Feral",
Festergut = "Panzachancro",
Feugen = "Feugen",
["Fineous Darkvire"] = "Finoso Virunegro",
Firemaw = "Faucefogo",
["Fjola Lightbane"] = "Fjola Penívea",
Flamegor = "Flamagor",
["Flame Leviathan"] = "Leviatán de llamas",
["Foreman Thistlenettle"] = "Supervisor Cardortiga",
["Forgemaster Garfrost"] = "Maestro de Forja Gargelus",
["Four Horsemen Chest"] = "Cofre de los Cuatro Jinetes",
["Fras Siabi"] = "Fras Siabi",
Freya = "Freya",
["Gahz'ranka"] = "Gahz'ranka",
["Gahz'rilla"] = "Gahz'rilla",
["Gal'darah"] = "Gal'darah",
["Galgann Firehammer"] = "Galgann Flamartillo",
Garr = "Garr",
["Garrosh Hellscream"] = "Garrosh Garrosh Grito Inferna",
Gasher = "Gasher",
["Gatewatcher Gyro-Kill"] = "Vígia de las puertas Giromata",
["Gatewatcher Iron-Hand"] = "Vigía de las puertas Manoyerro",
["Gathios the Shatterer"] = "Gathios the Shatterer",
Gehennas = "Gehennas",
Gelihast = "Gelihast",
Gelk = "Gelk",
["General Angerforge"] = "General Forjira",
["General Bjarngrim"] = "General Bjarngrim",
["General Drakkisath"] = "General Drakkisath",
["General Rajaxx"] = "General Rajaxx",
["General Vezax"] = "General Vezax",
-- ["General Zarithrian"] = "",
["Ghamoo-ra"] = "Ghamoo-ra",
["Ghaz'an"] = "Ghaz'an",
["Ghok Bashguud"] = "Ghok Bashguud",
Gilnid = "Gilnid",
["Gizrul the Slavener"] = "Gizrul el Esclavista",
["Gloom'rel"] = "Gloom'rel",
Gluth = "Gluth",
Glutton = "Glotón",
["Golemagg the Incinerator"] = "Golemagg el Incinerador",
["Golem Lord Argelmach"] = "Señor Golem Argelmach",
["Goraluk Anvilcrack"] = "Goraluk Yunquegrieta",
["Gormok the Impaler"] = "Gormok el Empalador",
["Gorosh the Dervish"] = "Gorosh el Endemoniado",
["Gortok Palehoof"] = "Gortok Pezuña Pálida",
["Gothik the Harvester"] = "Gothik el Cosechador",
["Grand Astromancer Capernian"] = "Gran astromántica Capernian",
["Grand Champions"] = "Grandes Campeones",
["Grand Magus Telestra"] = "Gran maga Telestra",
["Grandmaster Vorpil"] = "Maestro mayor Vorpil",
Grandmother = "Abuela",
["Grand Warlock Alythess"] = "Bruja suprema Alythess",
["Grand Warlock Nethekurse"] = "Brujo supremo Malbisal",
["Grand Widow Faerlina"] = "Gran Viuda Faerlina",
["Grethok the Controller"] = "Grethok el Controlador",
["Gri'lek"] = "Gri'lek",
Grimlok = "Grimlok",
Grizzle = "\009Grisez",
Grobbulus = "Grobbulus",
Grubbis = "Grubbis",
["Gruul the Dragonkiller"] = "Gruul el Asesino de Dragones",
["Guard Fengus"] = "Guardia Fengus",
["Guardian of Yogg-Saron"] = "Guardián de Yogg-Saron",
["Guard Mol'dar"] = "Guardia Mol'dar",
["Guard Slip'kik"] = "Guardia Slip'kik",
["Gurtogg Bloodboil"] = "Gurtogg Sangre Hirviente",
Gyth = "Gyth",
Hadronox = "Hadronox",
Hakkar = "Hakkar",
Halazzi = "Halazzi",
-- Halion = "",
Halycon = "Halycon",
Hamhock = "Hamhock",
["Harbinger Skyriss"] = "Presagista Cieloriss",
["Hate'rel"] = "Odio'rel",
["Hazza'rah"] = "Hazza'rah",
Hazzas = "Hazzas",
["Headless Horseman"] = "Jinete sin Cabeza",
["Hearthsinger Forresten"] = "Escupezones Foreste",
["Hedrum the Creeper"] = "Hedrum el Trepador",
["Heigan the Unclean"] = "Heigan el Impuro",
["Hellfire Channeler"] = "Canalizador Fuego Infernal",
["Henry Stern"] = "Henry Stern",
["Herald Volazj"] = "Heraldo Volazj",
Herod = "Herod",
["Hex Lord Malacrass"] = "Señor aojador Malacrass",
["High Astromancer Solarian"] = "Gran astromántica Solarian",
["High Botanist Freywinn"] = "Gran botánico Freywinn",
["High Inquisitor Fairbanks"] = "Alto Inquisidor Ribalimpia",
["High Inquisitor Whitemane"] = "Alta Inquisidora Melenablanca",
["High Interrogator Gerstahn"] = "Alto Interrogador Gerstahn",
["High King Maulgar"] = "Su majestad Maulgar",
["Highlord Mograine"] = "Alto Señor Mograine",
["Highlord Omokk"] = "Alto Señor Omokk",
["High Marshal Whirlaxis"] = "High Marshal Whirlaxis",
["High Nethermancer Zerevor"] = "High Nethermancer Zerevor",
["High Overlord Saurfang"] = "Alto señor supremo Colmillosauro",
["High Priestess Arlokk"] = "Suma Sacerdotisa Arlokk",
["High Priestess Jeklik"] = "Suma Sacerdotisa Jeklik",
["High Priestess Mar'li"] = "Suma Sacerdotisa Mar'li",
["High Priestess of Thaurissan"] = "Alta Sacerdotisa de Thaurissan",
["High Priest Thekal"] = "Sumo Sacerdote Thekal",
["High Priest Venoxis"] = "Sumo Sacerdote Venoxis",
["High Warlord Naj'entus"] = "Gran Señor de la Guerra Naj'entus",
Hodir = "Hodir",
["Houndmaster Grebmar"] = "Maestro de canes Grebmar",
["Houndmaster Loksey"] = "Maestro de canes Loksey",
Hukku = "Hukku",
Hungarfen = "Panthambre",
["Hurley Blackbreath"] = "Hurley Negrálito",
["Hyakiss the Lurker"] = "Hyakiss el Rondador",
["Hydromancer Thespia"] = "Hidromántico Thespia",
["Hydromancer Velratha"] = "Hidromántica Velratha",
Hydrospawn = "Hidromilecio",
["Hydross the Unstable"] = "Hydross el Inestable",
["Icecrown Gunship Battle"] = "Batalla de las Aeronaves de Corona de Hielo",
Icehowl = "Aullahielo",
["Ice Sphere"] = "Esfera de hielo",
Ichoron = "Ícoron",
Ick = "Agh",
["Ignis the Furnace Master"] = "Ignis el Maestro de la Caldera",
["Illidan Stormrage"] = "Illidan Tempestira",
["Illidari Council"] = "Concilio Illidari",
["Illyanna Ravenoak"] = "Illyanna Roblecuervo",
["Immol'thar"] = "Immol'thar",
["Infinite Corruptor"] = "Corruptor Infinito",
["Infinity Blades"] = "Hojas de infinidad",
["Ingvar the Plunderer"] = "Ingvar the Plunderer",
["Instructor Malicia"] = "Instructor Malicia",
["Instructor Razuvious"] = "Instructor Razuvious",
["Interrogator Vishas"] = "Interrogador Vishas",
Ionar = "Ionar",
Ironaya = "Hierraya",
Ironspine = "Dorsacerado",
Isalien = "Isalien",
Jade = "Jade",
["Jammal'an the Prophet"] = "Jammal'an el Profeta",
["Jan'alai"] = "Jan'alai",
["Jandice Barov"] = "Jandice Barov",
["Jedoga Shadowseeker"] = "Jedoga Buscasombras",
["Jed Runewatcher"] = "Jed vigía de las runas",
["Jergosh the Invoker"] = "Jergosh el Convocador",
["Jin'do the Hexxer"] = "Jin'do el Aojador",
["Jormungar Behemoth"] = "Behemoth Jormungar",
Jormungars = "Jormungars",
Julianne = "Julianne",
["Junk Bot"] = "Chatarrabot",
["Kael'thas Sunstrider"] = "Kael'thas Caminante del Sol",
Kalecgos = "Kalecgos",
["Kam Deepfury"] = "Kam Furiahonda",
["Kazkaz the Unholy"] = "Kazkaz el Blasfemo",
["Kaz'rogal"] = "Kaz'rogal",
["Keli'dan the Breaker"] = "Keli'dan el Ultrajador",
["Kel'Thuzad"] = "Kel'Thuzad",
Keristrasza = "Keristrasza",
["Kiggler the Crazed"] = "Kiggler el Enloquecido",
["Kil'jaeden"] = "Kil'jaeden",
["Kil'rek"] = "Kil'rek",
["King Dred"] = "Rey Dred",
["King Gordok"] = "Rey Gordok",
["King Llane Piece"] = "Rey Llane",
["King Ymiron"] = "Rey Ymiron",
["Kirtonos the Herald"] = "Kirtonos el Heraldo",
["Knot Thimblejack's Cache"] = "Carretilla de Knot Llavededo",
Kolk = "Kolk",
Kologarn = "Kologarn",
["Koralon the Flame Watcher"] = "Koralon el Vigía de las llamas",
Kormok = "Kormok",
Kresh = "Kresh",
Krick = "Puagh",
["Krick and Ick"] = "Agh y Puagh",
["Krik'thir the Gatewatcher"] = "Krik’thir el vígia de las puertas",
["Krosh Firehand"] = "Krosh Manofuego",
Krystallus = "Krystallus",
Kurinnaxx = "Kurinnaxx",
["Lady Anacondra"] = "Lady Anacondra",
["Lady Blaumeux"] = "Lady Blaumeux",
["Lady Deathwhisper"] = "Lady Susurramuerte",
["Lady Illucia Barov"] = "Lady Illucia Barov",
["Lady Malande"] = "Lady Malande",
["Lady Sacrolash"] = "Lady Sacrolash",
["Lady Sarevess"] = "Lady Sarevess",
["Lady Vashj"] = "Lady Vashj",
Laj = "Laj",
Landslide = "Derrumblo",
Lavanthor = "Lavanthor",
["Left Arm"] = "Brazo Izquierdo",
["Leotheras the Blind"] = "Leotheras el Ciego",
Lethon = "Lethon",
Lethtendris = "Lethtendris",
["Leviathan Mk II"] = "Mk II de leviatán",
["Ley-Guardian Eregos"] = "Guardián-Ley Eregos",
["Lieutenant Drake"] = "Teniente Draco",
["Lieutenant General Andorov"] = "Teniente General Andorov",
Loatheb = "Loatheb",
Loken = "Loken",
["Lord Alexei Barov"] = "Lord Alexei Barov",
["Lord Cobrahn"] = "Lord Cobrahn",
["Lord Hel'nurath"] = "Lord Hel'nurath",
["Lord Incendius"] = "Lord Incendius",
["Lord Jaraxxus"] = "Lord Jaraxxus",
["Lord Kazzak"] = "Lord Kazzak",
["Lord Kri"] = "Lord Kri",
["Lord Marrowgar"] = "Lord Tuétano",
["Lord Pythas"] = "Lord Pythas",
["Lord Roccor"] = "Lord Roccor",
["Lord Sanguinar"] = "Lord Sanguinar",
["Lord Serpentis"] = "Lord Serpentis",
["Lord Skwol"] = "Lord Skwol",
["Lord Valthalak"] = "Lord Valthalak",
["Lord Victor Nefarius"] = "Lord Víctor Nefarius",
["Lord Vyletongue"] = "Lord Lenguavil",
["Lorekeeper Polkelt"] = "Tradicionalista Polkelt",
Loro = "Loro",
Lucifron = "Lucifron",
["Mad Magglish"] = "Magglish el Loco",
Maexxna = "Maexxna",
["Mage-Lord Urom"] = "Señor de la Magia Urom",
["Magister Kalendris"] = "Magister Kalendris",
["Magistrate Barthilas"] = "Magistrado Barthilas",
Magmadar = "Magmadar",
Magmus = "Magmus",
Magra = "Magra",
Magtheridon = "Magtheridon",
["Maiden of Grief"] = "Doncella de Pena",
["Maiden of Virtue"] = "Doncella de Virtud",
["Majordomo Executus"] = "Mayordomo Executus",
Malacrass = "Malacrass",
["Maleki the Pallid"] = "Maleki el Pálido",
["Mal'Ganis"] = "Mal'Ganis",
Malygos = "Malygos",
Maraudos = "Maraudos",
["Marduk Blackpool"] = "Marduz Pozonegro",
["Marisa du'Paige"] = "Marisa du'Paige",
Marwyn = " Marwyn",
["Master Engineer Telonicus"] = "Maestro Ingeriero Telonicus",
["Maur Grimtotem"] = "Maur Tótem Siniestro",
Meathook = "Gancho",
["Mechano-Lord Capacitus"] = "Lord-mecano Capacitus",
Medivh = "Medivh",
["Mekgineer Steamrigger"] = "Mekigeniero Vaporino",
["Mekgineer Thermaplugg"] = "Mekigeniero Termochufe",
["Mennu the Betrayer"] = "Mennu el Traidor",
["Meshlok the Harvester"] = "Meshlok el Cosechador",
Midnight = "Medianoche",
Mijan = "Mijar",
Mimiron = "Mimiron",
["Miner Johnson"] = "Minero Johnson",
["Mistress of Pain"] = "Doncella de Dolor",
Moam = "Moam",
Mogor = "Mogor",
["Mokra the Skullcrusher"] = "Mokra el Trituracráneos",
Moorabi = "Moorabi",
Moragg = "Moragg",
["Mordresh Fire Eye"] = "Mordresh Ojo de Fuego",
["Mor Grayhoof"] = "Mor Grayhoof",
Moroes = "Moroes",
["Morogrim Tidewalker"] = "Morogrim Levantamareas",
Morphaz = "Morphaz",
["Mother Shahraz"] = "Madre Shahraz",
["Mother Smolderweb"] = "Madre Telabrasada",
["Mr. Smite"] = "Sr. Golpin",
["Muradin Bronzebeard"] = "Muradin Barbabronce",
["Murkblood Twin"] = "Gemelo Sangreoscura",
["Murkblood Twins"] = "Gemelos Sangreoscura",
Murmur = "Murmur",
["Murta Grimgut"] = "Murta Tripuriosa",
["M'uru"] = "M'uru",
Mushgog = "Mushgog",
["Mutanus the Devourer"] = "Mutanus el Devorador",
Nalorakk = "Nalorakk",
Nazan = "Nazan",
Nefarian = "Nefarian",
["Nekrum Gutchewer"] = "Nekrum Cometripas",
["Nerub'enkan"] = "Nerub'enkan",
["Nethermancer Sepethrea"] = "Abisálico Sepethrea",
Netherspite = "Rencor abisal",
["Netherstrand Longbow"] = "Arco largo de fibra abisal",
["Nexus-Prince Shaffar"] = "Príncipe-nexo Shaffar",
Nightbane = "Nocturno",
["Noth the Plaguebringer"] = "Noth el Pesteador",
["Novos the Summoner"] = "Novos el Invocador",
Noxxion = "Noxxion",
["Obsidian Sentinel"] = "Centinela Obsidiano",
["Odo the Blindwatcher"] = "Odo el vigía ciego",
["Ogom the Wretched"] = "Ogom el Desdichado",
["Ok'thor the Breaker"] = "Ok'thor el Rompedor",
["Old Serra'kis"] = "Viejo Serra'kis",
["Olm the Summoner"] = "Olm el Invocador",
["Omor the Unscarred"] = "Omor el Sinmarcas",
Onyxia = "Onyxia",
["Orgrim's Hammer"] = "Martillo de Orgrim",
["Ormorok the Tree-Shaper"] = "Ormorok el cortador de árboles",
["Oro Eyegouge"] = "Oro Bocojo ",
["Ossirian the Unscarred"] = "Osirio el Sinmarcas",
Ouro = "Ouro",
["Overlord Ramtusk"] = "Señor Supremo Colmicarnero",
["Overlord Wyrmthalak"] = "Señor Supremo Vermiothalak",
["Overmaster Pyron"] = "Maestro Supremo Pyron",
["Overseer Tidewrath"] = "Avizor Aleta de Cólera",
Pandemonius = "Pandemonius",
["Panzor the Invincible"] = "Panzor el Invencible",
Patchwerk = "Remendejo",
["Pathaleon the Calculator"] = "Panthaleon el Calculador",
Phalanx = "Falange",
["Phaseshift Bulwark"] = "Baluarte de cambio de fase",
Pimgib = "Pimgib",
["Plaguemaw the Rotting"] = "Fauzpeste el Putrefacto",
["Plugger Spazzring"] = "Plugger Aropatoso",
["Postmaster Malown"] = "Jefe de correos Malown",
["Priestess Delrissa"] = "Sacerdotisa Delrissa",
["Prince Keleseth"] = "Príncipe Keleseth",
["Prince Malchezaar"] = "Príncipe Malchezaar",
["Prince Skaldrenox"] = "Príncipe Skaldrenox",
["Princess Huhuran"] = "Princesa Huhuran",
["Princess Moira Bronzebeard"] = "Princesa Moira Barbabronce",
["Princess Tempestria"] = "Princesa Tempestria",
["Princess Theradras"] = "Princesa Theradras",
["Princess Yauj"] = "Princesa Yauj",
["Prince Taldaram"] = "Príncipe Taldaram",
["Prince Tenris Mirkblood"] = "Príncipe Tenris Sangre Penumbra",
["Prince Tortheldrin"] = "Príncipe Tortheldrin",
["Prince Valanar"] = "Principe Valanar",
["Professor Putricide"] = "Profesor Putricidio",
["Pure Spawn of Hydross"] = "Engendro puro de Hydross",
Pusillin = "Pusillín",
["Pyroguard Emberseer"] = "Piroguardián Brasadivino",
["Pyromancer Loregrain"] = "Piromántico Cultugrano",
Quagmirran = "Quagmirran",
["Quartermaster Zigris"] = "Intendente Zigris",
["Rage Winterchill"] = "Ira Fríoinvierno",
Ragglesnout = "Morrandrajos",
["Raging Spirit"] = "Espíritu enfurecido",
Ragnaros = "Ragnaros",
["Ramstein the Gorger"] = "Ramstein el Empachador",
["Ras Frostwhisper"] = "Ras Levescarcha",
Rattlegore = "Traquesangre",
["Razorclaw the Butcher"] = "Zarpador el Carnicero",
["Razorgore the Untamed"] = "Sangrevaja el Indomable",
Razorlash = "Lativaja",
Razorscale = "Tajoescama",
["Reliquary of Souls"] = "Relicario de Almas",
Renataki = "Renataki",
["Restless Skeleton"] = "Esqueleto inquieto",
Rethilgore = "Rethilgore",
Revelosh = "Revelosh",
["Rhahk'Zor"] = "Rhahk'Zor",
["Ribbly Screwspigot"] = "Ribbly Llavenrosca",
["Right Arm"] = "Brazo Derecho",
Roar = "Rugido",
["Rokad the Ravager"] = "Rokad el Devastador",
["Rokdar the Sundered Lord"] = "Rokdar el Señor Hendido",
["Rokmar the Crackler"] = "Rokmar el Crujidor",
Romulo = "Romulo",
["Romulo & Julianne"] = "Romeo y Julieta",
Rotface = "Carapútrea",
Rotgrip = "Escamapodrida",
["Runemaster Molgeim"] = "Maestro de runas Molgeim",
["Runok Wildmane"] = "Runok Ferocrín",
Ruuzlu = "Ruuzlu",
["Salramm the Fleshcrafter"] = "Salramm el Modelador de carne",
["Sanctum Sentry"] = "Centinela del sagrario",
["Sandarr Dunereaver"] = "Sandarr Asaltadunas",
["Sandfury Executioner"] = "Ejecutor Furiarena",
Sapphiron = "Sapphiron",
Sara = "Sara",
["Saronite Animus"] = "Animus de saronita",
Sartharion = "Sartharion",
["Sathrovarr the Corruptor"] = "Sathrovarr el Corruptor",
-- ["Saviana Ragefire"] = "",
["Scarlet Commander Mograine"] = "Comandante Escarlata Mograine",
["Scourgelord Tyrannus"] = "Señor de la Plaga Tyrannus",
["Seeth'rel"] = "Seeth'rel",
["Selin Fireheart"] = "Selin Corazón de Fuego",
["Sergeant Bly"] = "Sargento Bly",
["Shade of Akama"] = "Sombra de Akama",
["Shade of Aran"] = "Sombra de Aran",
["Shade of Eranikus"] = "Sombra de Eranikus",
["Shadikith the Glider"] = "Shadikith the Glider",
["Shadow Hunter Vosh'gajin"] = "Cazador de las Sombras Vosh'gajin",
["Shadow of Leotheras"] = "Sombra de Leotheras",
["Shadowpriest Sezz'ziz"] = "Sacerdote oscuro Sezz'ziz",
Shadron = "Shadron",
Shazzrah = "Shazzrah",
["Shirrak the Dead Watcher"] = "Shirrak el Vigía de los Muertos",
Sindragosa = "Sindragosa",
["Sir Zeliek"] = "Sir Zeliek",
["Sjonnir The Ironshaper"] = "Sjonnir el Afilador",
["Skadi the Ruthless"] = "Skadi el Despiadado",
["Skarr the Unbreakable"] = "Skarr el Inquebrantable",
["Skarvald the Constructor"] = "Skarvald el Constructor",
["Skra'gath"] = "Skra'gath",
Skul = "Skul",
Skum = "Skum",
["Slad'ran"] = "Slad'ran",
Sneed = "Sneed",
["Sneed's Shredder"] = "Machacador de Sneed",
["Solakar Flamewreath"] = "Solakar Corona de Fuego",
["Solarium Agent"] = "Agente Solarium",
["Solarium Priest"] = "Sacerdote Solarium",
["Spirestone Battle Lord"] = "Señor de batalla Cumbrerroca",
["Spirestone Butcher"] = "Carnicero Cumbrerroca",
["Spirestone Lord Magus"] = "Señor Magus Cumbrerroca",
["Staff of Disintegration"] = "Bastón de desintegración",
Stalagg = "Stalagg",
Steelbreaker = "Rompeacero",
["Stomper Kreeg"] = "Vapuleador Kreeg",
Stonespine = "Pidrespina",
["Stormcaller Brundir"] = "Clamatormentas Brundir",
Strawman = "Espantapájaros",
["Sulfuron Harbinger"] = "Sulfuron Presagista",
Supremus = "Supremus",
["Svala Sorrowgrave"] = "Svala Tumbapena",
["Swamplord Musel'ek"] = "Señor del pantano Musel'ek",
Taerar = "Taerar",
["Tainted Spawn of Hydross"] = "Engendro de Hydross corrupto",
["Talon King Ikiss"] = "Rey Garra Ikiss",
["Taragaman the Hungerer"] = "Taragaman el Hambriento",
["Targorr the Dread"] = "Targor el Pavoroso",
Tavarok = "Tavarok",
Techbot = "Tecnobot",
Temporus = "Temporus",
["Tendris Warpwood"] = "Tendris Madeguerra",
Tenebron = "Tenebron",
["Terestian Illhoof"] = "Terestian Pezuña Enferma",
["Teron Gorefiend"] = "Teron Sanguino",
Thaddius = "Thaddius",
["Thaladred the Darkener"] = "Thaladred el Oscurecedor",
["Thane Korth'azz"] = "Thane Korth'azz",
["The Beast"] = "La Bestia",
["The Beasts of Northrend"] = "Las bestias de Rasganorte ",
["The Big Bad Wolf"] = "El Gran Lobo Malvado",
["The Black Knight"] = "El Caballero Negro",
["The Black Stalker"] = "La acechadora negra",
["The Blue Brothers"] = "Los Hermanos Azules",
["The Bug Family"] = "La Familia Insecto",
["The Crone"] = "La Vieja Bruja",
["The Curator"] = "Curator",
["The Eredar Twins"] = "Los Gemelos Eredar",
["The Four Horsemen"] = "Los Cuatro Jinetes",
["The Illidari Council"] = "El concilio Illidari",
["The Iron Council"] = "Asamblea de Hierro",
["Theka the Martyr"] = "Theka la Mártir",
["The Lich King"] = "El Rey Exánime",
["The Lurker Below"] = "El Rondador de abajo",
["The Maker"] = "El Hacedor",
["The Prophet Skeram"] = "El profeta Skeram",
["The Prophet Tharon'ja"] = "El profeta Tharon'ja",
["The Ravenian"] = "El Devorador",
["The Razza"] = "El Razza",
["The Seven Dwarves"] = "Los Siete Enanitos",
["The Skybreaker"] = "El Rompecielos",
["The Tribunal of Ages"] = "El Tribunal de las Eras",
["The Twin Emperors"] = "Los Emperadores Gemelos",
["The Twin Val'kyr"] = "las Gemelas Val'kyr",
["The Unforgiven"] = "El Imperdonable",
["The Windreaver"] = "El Atracavientos",
Thorim = "Thorim",
["Thorngrin the Tender"] = "Thorngrin el Tierno",
["Tidewalker Lurker"] = "Rondador Levantamareas",
["Timmy the Cruel"] = "Timmy el Cruel",
Tinhead = "Cabezalata",
["Tinkerer Gizlock"] = "Manitas Gizlock",
["Tirion Fordring"] = "Tirion Vadín",
Tito = "Tito",
["Toravon the Ice Watcher"] = "Toravon el Vigía de Hielo",
["Trigore the Lasher"] = "Trigore el Azotador",
Trollgore = "Cuernotrol",
["Tsu'zee"] = "Tsu'zee",
["Tuten'kash"] = "Tuten'kash",
["Twilight Lord Kelris"] = "Señor Crepuscular Kelris",
["Urok Doomhowl"] = "Urok Aullapocalipsis",
["Vaelastrasz the Corrupt"] = "Vaelastrasz el Corrupto",
["Valithria Dreamwalker"] = "Valithria Caminasueños",
["Val'kyr Shadowguard"] = "Guardia de las Sombras Val'kyr",
["Varian Wrynn"] = "Varian Wrynn",
["Varos Cloudstrider"] = "Varos Zancanubes",
Vazruden = "Vazruden",
["Vazruden the Herald"] = "Vazruden el Heraldo",
Vectus = "Vectus",
Vem = "Vem",
Veng = "Veng",
["Veras Darkshadow"] = "Veras Darkshadow",
["Verdan the Everliving"] = "Verdan el Eterno",
Verek = "Verek",
Vesperon = "Vesperon",
Vexallus = "Vexallus",
["Veyzhak the Cannibal"] = "Veyzhak el Caníbal",
["Vile'rel"] = "Vil'rel",
Viscidus = "Viscidus",
["Viscous Fallout"] = "Radiactivo viscoso",
["Void Reaver"] = "Atracador del vacío",
Volkhan = "Volkhan",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "Belisario O'mrogg",
["Warchief Blackhand Piece"] = "Jefe de Guerra Mano Negra",
["Warchief Kargath Bladefist"] = "Jefe de Guerra Kargath Garrafilada",
["Warchief Rend Blackhand"] = "Jefe de Guerra Desgarro Puño Negro",
["Warden Mellichar"] = "Celador Mellichar",
["Warder Stilgiss"] = "Guarda Stilgiss",
["Warlord Kalithresh"] = "Señor de la Guerra Kalithresh",
["War Master Voone"] = "Maestro de guerra Voone",
["Warmaul Champion"] = "Campeón Mazo de Guerra",
["Warp Slicer"] = "Cercenadora de distorsión",
["Warp Splinter"] = "Disidente de distorsión",
["Watchkeeper Gargolmar"] = "Guardián vigía Gargolmar",
Weaver = "Sastrón",
["Witch Doctor Zum'rah"] = "Médico brujo Zum'rah",
["Wolf Master Nandos"] = "Maestro de lobos Nandos",
["Wrath-Scryer Soccothrates"] = "Arúspice de cólera Soccothrates",
Wushoolay = "Wushoolay",
Xevozz = "Xevozz",
["XT-002 Deconstructor"] = "Desarmarmador XA-002",
["Yogg-Saron"] = "Yogg-Saron",
Ysondre = "Ysondre",
Zekkis = "Zekkis",
["Zelemar the Wrathful"] = "Zelemar el Colérico",
["Zereketh the Unbound"] = "Zereketh el Desatado",
Zerillis = "Zerillis",
["Zevrim Thornhoof"] = "Zevrim Pezuñahendida",
Zolo = "Zolo",
["Zul'Farrak Dead Hero"] = "Héroe muerto Zul'Farrak",
["Zul'jin"] = "Zul'jin",
["Zul'Lor"] = "Zul'Lor",
["Zul'tore"] = "Zul'tore",
["Zuramat the Obliterator"] = "Zuramat el Obliterador",
}
elseif GAME_LOCALE == "ruRU" then
lib:SetCurrentTranslations {
Acidmaw = "Кислотная Утроба",
Aeonus = "Эонус",
["Aerial Command Unit"] = "Воздушное судно",
["Agathelos the Raging"] = "Агателос Свирепый",
Ahune = "Ахун",
["Akil'zon"] = "Акил'зон",
["Aku'mai"] = "Аку'май",
["Al'ar"] = "Ал'ар",
["Algalon the Observer"] = "Алгалон Наблюдатель",
["Alzzin the Wildshaper"] = "Алззин Перевертень",
Amanitar = "Аманитар",
["Ambassador Flamelash"] = "Посол Огнехлыст",
["Ambassador Hellmaw"] = "Посол Гиблочрев",
["Amnennar the Coldbringer"] = "Амненнар Хладовей",
["Ancient Stone Keeper"] = "Древний Хранитель Камня",
Anetheron = "Анетерон",
["Anger'rel"] = "Гнев'рел",
Anomalus = "Аномалус",
["Antu'sul"] = "Анту'сул",
["Anub'arak"] = "Ануб'арак",
["Anubisath Defender"] = "Защитник-анубисат",
["Anubisath Guardian"] = "Анубисат-страж",
["Anub'Rekhan"] = "Ануб'Рекан",
["Anub'shiah"] = "Ануб'шиа",
Anzu = "Анзу",
["Arcane Watchman"] = "Чародейский стражник",
["Arcanist Doan"] = "Чародей Доан",
Archaedas = "Аркедас",
["Archavon the Stone Watcher"] = "Аркавон Страж Камня",
Archimonde = "Архимонд",
["Archivist Galford"] = "Архивариус Галфорд",
["Archmage Arugal"] = "Верховный маг Аругал",
["Argent Confessor Paletress"] = "Исповедница Серебряного Авангарда Пейлтресс",
["Arugal's Voidwalker"] = "Демон Бездны Аругала",
["Assault Bot"] = "Штурмовой робот",
["Atal'alarion"] = "Атал'аларион",
["Attumen the Huntsman"] = "Ловчий Аттумен",
Auriaya = "Ауриайя",
Avalanchion = "Лавинион",
["Avatar of Hakkar"] = "Аватара Хаккара",
["Ayamiss the Hunter"] = "Айамисса Охотница",
Azgalor = "Азгалор",
["Azshir the Sleepless"] = "Азшир Неспящий",
Azuregos = "Азурегос",
["Bael'Gar"] = "Бейл'Гор",
Baelog = "Бейлог",
Balnazzar = "Балназзар",
-- ["Baltharus the Warborn"] = "",
["Bannok Grimaxe"] = "Баннок Люторез",
["Baron Aquanis"] = "Барон Акванис",
["Baron Charr"] = "Барон Огнерр",
["Baroness Anastari"] = "Баронесса Анастари",
["Baron Geddon"] = "Барон Геддон",
["Baron Kazum"] = "Барон Казум",
["Baron Rivendare"] = "Барон Ривендер",
["Baron Silverlaine"] = "Барон Сребролен",
["Battleguard Sartura"] = "Боевой страж Сартура",
["Bazil Thredd"] = "Базиль Тредд",
Bazzalan = "Баззалан",
["Black Guard Swordsmith"] = "Оружейник Черной Стражи",
["Blackheart the Inciter"] = "Черносерд Проповедник",
["Blindeye the Seer"] = "Слепоглаз Ясновидец",
["Blind Hunter"] = "Слепой охотник",
["Blood Guard Porung"] = "Кровавый страж Порунг",
["Bloodlord Mandokir"] = "Мандокир Повелитель Крови",
["Bloodmage Thalnos"] = "Волшебник Крови Талнос",
["Blood Prince Council"] = "Совет Принцев Крови",
["Blood Princes"] = "Совет Принцев Крови",
["Blood-Queen Lana'thel"] = "Кровавая королева Лана'тель",
["Blood Steward of Kirtonos"] = "Кровавая прислужница Киртоноса",
Boahn = "Боан",
["Bomb Bot"] = "Бомбот",
["Brain of Yogg-Saron"] = "Мозг Йогг-Сарона",
["Brainwashed Noble"] = "Зомбированный дворянин",
Broggok = "Броггок",
Brokentoe = "Хромоног",
Bronjahm = "Броньям",
["Broodlord Lashlayer"] = "Предводитель драконов Разящий Бич",
["Bruegal Ironknuckle"] = "Бругал Железный Кулак",
Brutallus = "Бруталл",
["Burning Felguard"] = "Пылающий страж Скверны",
["Buru the Gorger"] = "Буру Ненасытный",
["Cache of the Firelord"] = "Тайник повелителя огня",
["Cannon Master Willey"] = "Мастер-канонир Вилли",
["Captain Greenskin"] = "Капитан Зеленямс",
["Captain Kromcrush"] = "Капитан Давигром",
["Captain Skarloc"] = "Капитан Скарлок",
["Celebras the Cursed"] = "Селебрас Проклятый",
["Charlga Razorflank"] = "Чарлга Остробок",
["Chess Event"] = "Шахматы",
["Chest of The Seven"] = "Сундук Семерых",
["Chief Ukorz Sandscalp"] = "Вождь Укорз Песчаная Плешь",
["Cho'Rush the Observer"] = "Чо'Раш Наблюдатель",
Chromaggus = "Хроммагус",
["Chrono Lord Deja"] = "Повелитель времени Дежа",
["Chrono-Lord Epoch"] = "Хронолорд Эпох",
Claw = "Коготь",
["Coilfang Elite"] = "Гвардеец резервуара Кривого Клыка",
["Coilfang Strider"] = "Странник резервуара Кривого Клыка",
["Commander Kolurg"] = "Командир Колург",
["Commander Sarannis"] = "Командир Сараннис",
["Commander Springvale"] = "Командир Ручьедол",
["Commander Stoutbeard"] = "Командир Пивобород",
["Constructor & Controller"] = "Строитель и Контролирующий",
Cookie = "Пирожок",
["Coren Direbrew"] = "Корен Худовар",
["Cosmic Infuser"] = "Вселенский вдохновитель",
["Crimson Hammersmith"] = "Молотобоец из Багрового Легиона",
["Crowd Pummeler 9-60"] = "Толпогон 9-60",
["Crystal Fang"] = "Хрустальный Клык",
["C'Thun"] = "К'Тун",
Cyanigosa = "Синигоса",
["Dalliah the Doomsayer"] = "Далия Глашатай Судьбы",
["Dalronn the Controller"] = "Далронн Контролирующий",
["Dark Iron Ambassador"] = "Посол из клана Черного Железа",
["Darkmaster Gandling"] = "Темный магистр Гандлинг",
["Darkweaver Syth"] = "Темнопряд Сит",
-- ["Deathbound Ward"] = "",
["Deathbringer Saurfang"] = "Саурфанг Смертоносный",
["Death Knight Darkreaver"] = "Рыцарь смерти Темный Терзатель",
["Death Knight Understudy"] = "Ученик рыцаря смерти",
-- ["Deathspeaker High Priest"] = "",
["Death Speaker Jargba"] = "Вестник смерти Джаргба",
["Deathstalker Visceri"] = "Страж смерти Визери",
["Deathsworn Captain"] = "Капитан служителей Смерти",
Devastation = "Сокрушитель",
["Deviate Faerie Dragon"] = "Загадочный волшебный дракон",
["Devourer of Souls"] = "Пожиратель Душ",
["Dextren Ward"] = "Декстрен Вард",
["Digmaster Shovelphlange"] = "Мастер Лопаторук",
["Doctor Theolen Krastinov"] = "Доктор Теолен Крастинов",
["Doom Lord Kazzak"] = "Владыка Судеб Каззак",
["Doom'rel"] = "Рок'рел",
Doomwalker = "Судьболом",
["Dope'rel"] = "Праздн'рел",
Dorothee = "Дороти",
["Drakkari Colossus"] = "Колосс Драккари",
["Drakos the Interrogator"] = "Дракос Дознаватель",
Dreadscale = "Жуткая Чешуя",
Dreamscythe = "Жнец Снов",
["Dust Covered Chest"] = "Пыльный сундук",
Dustwraith = "Пыльный Призрак",
["Eadric the Pure"] = "Эдрик Чистый",
["Earthcaller Halmgar"] = "Заклинательница земли Халмгар",
Ebonroc = "Черноскал",
["Eck the Ferocious"] = "Эк Свирепый",
["Edwin VanCleef"] = "Эдвин ван Клиф",
["Elder Brightleaf"] = "Древень Яркий Лист",
["Elder Ironbranch"] = "Древень Железная Ветвь",
["Elder Nadox"] = "Старейшина Надокс",
["Elder Stonebark"] = "Древень Каменная Кора",
["Electrocutioner 6000"] = "Электрошокер 6000",
["Emalon the Storm Watcher"] = "Эмалон Страж Бури",
Emeriss = "Эмерисс",
["Emperor Dagran Thaurissan"] = "Император Дагран Таурисан",
["Emperor Vek'lor"] = "Император Век'лор",
["Emperor Vek'nilash"] = "Император Век'нилаш",
Entropius = "Энтропий",
["Eonar's Gift"] = "Дар Эонара",
["Epoch Hunter"] = "Охотник Вечности",
Erekem = "Эрекем",
["Eressea Dawnsinger"] = "Эрессея Певица Рассвета",
["Essence of Anger"] = "Воплощение гнева",
["Essence of Desire"] = "Воплощение желания",
["Essence of Suffering"] = "Воплощение страдания",
Eviscerator = "Потрошитель",
["Exarch Maladaar"] = "Экзарх Маладаар",
["Expedition Commander"] = "Начальник экспедиции",
["Eydis Darkbane"] = "Эйдис Погибель Тьмы",
["Eye of C'Thun"] = "Око К'Туна",
["Faction Champions"] = "Чемпионы фракций",
["Fallen Champion"] = "Павший воитель",
Falric = "Фалрик",
["Falric and Marwyn"] = "Фалрик и Марвин",
["Fankriss the Unyielding"] = "Фанкрисс Неприклонный",
["Fathom-Lord Karathress"] = "Повелитель глубин Каратресс",
Felmyst = "Пророк Скверны",
["Fenrus the Devourer"] = "Фенрус Пожиратель",
["Feral Defender"] = "Дикий защитник",
Festergut = "Тухлопуз",
Feugen = "Фойген",
["Fineous Darkvire"] = "Точень Темнострой",
Firemaw = "Огнечрев",
["Fjola Lightbane"] = "Фьола Погибель Света",
Flamegor = "Пламегор",
["Flame Leviathan"] = "Огненный Левиафан",
["Foreman Thistlenettle"] = "Штейгер Чертополох",
["Forgemaster Garfrost"] = "Начальник кузни Гархлад", -- Needs review
["Four Horsemen Chest"] = "Сундук Четырех Всадников",
["Fras Siabi"] = "Фрас Сиаби",
Freya = "Фрейя",
["Gahz'ranka"] = "Газ'ранка",
["Gahz'rilla"] = "Газ'рилла",
["Gal'darah"] = "Гал'дара",
["Galgann Firehammer"] = "Галганн Огнемолот",
Garr = "Гарр",
["Garrosh Hellscream"] = "Гаррош Адский Крик",
Gasher = "Ранокол",
["Gatewatcher Gyro-Kill"] = "Страж ворот Точеный Нож",
["Gatewatcher Iron-Hand"] = "Страж ворот Стальная Клешня",
["Gathios the Shatterer"] = "Гатиос Изувер",
Gehennas = "Гееннас",
Gelihast = "Гелихаст",
Gelk = "Джелк",
["General Angerforge"] = "Генерал Кузня Гнева",
["General Bjarngrim"] = "Генерал Бьярнгрин",
["General Drakkisath"] = "Генерал Драккисат",
["General Rajaxx"] = "Генерал Раджакс",
["General Vezax"] = "Генерал Везакс",
-- ["General Zarithrian"] = "",
["Ghamoo-ra"] = "Гхаму-ра",
["Ghaz'an"] = "Газ'ан",
["Ghok Bashguud"] = "Гок Крепкобив",
Gilnid = "Гилнид",
["Gizrul the Slavener"] = "Гизрул Поработитель",
["Gloom'rel"] = "Мрак'нел",
Gluth = "Глут",
Glutton = "Обжора",
["Golemagg the Incinerator"] = "Маг-лорд из клана Гордок",
["Golem Lord Argelmach"] = "Повелитель големов Аргелмах",
["Goraluk Anvilcrack"] = "Горалук Треснувшая Наковальня",
["Gormok the Impaler"] = "Гормок Пронзающий Бивень",
["Gorosh the Dervish"] = "Горош Дервиш",
["Gortok Palehoof"] = "Горток Бледное Копыто",
["Gothik the Harvester"] = "Готик Жнец",
["Grand Astromancer Capernian"] = "Верховный звездочет Каперниан",
["Grand Champions"] = "Абсолютные чемпионы",
["Grand Magus Telestra"] = "Великая ведунья Телестра",
["Grandmaster Vorpil"] = "Великий мастер Ворпил",
Grandmother = "Бабушка",
["Grand Warlock Alythess"] = "Главная чернокнижница Алитесса",
["Grand Warlock Nethekurse"] = "Главный чернокнижник Пустоклят",
["Grand Widow Faerlina"] = "Великая вдова Фарлина",
["Grethok the Controller"] = "Греток Регулятор",
["Gri'lek"] = "Гри'лек",
Grimlok = "Гримлок",
Grizzle = "Гриззл",
Grobbulus = "Гроббулус",
Grubbis = "Грязнюк",
["Gruul the Dragonkiller"] = "Груул Драконобой",
["Guard Fengus"] = "Стражник Фенгус",
["Guardian of Yogg-Saron"] = "Страж Йогг-Сарона",
["Guard Mol'dar"] = "Стражник Мол'дар",
["Guard Slip'kik"] = "Стражник Слип'кик",
["Gurtogg Bloodboil"] = "Гуртогг Кипящая Кровь",
Gyth = "Гит",
Hadronox = "Хадронокс",
Hakkar = "Хаккар",
Halazzi = "Халаззи",
Halion = "Халион",
Halycon = "Халикон",
Hamhock = "Хрупконог",
["Harbinger Skyriss"] = "Предвестник Скайрисс",
["Hate'rel"] = "Злоб'рел",
["Hazza'rah"] = "Хазза'рах",
Hazzas = "Хаззас",
["Headless Horseman"] = "Всадник без головы",
["Hearthsinger Forresten"] = "Певчий Форрестен",
["Hedrum the Creeper"] = "Хедрум Ползун",
["Heigan the Unclean"] = "Хейган Нечестивый",
["Hellfire Channeler"] = "Чаротворец из цитадели Адского Пламени",
["Henry Stern"] = "Генри Штерн",
["Herald Volazj"] = "Глашатай Волаж",
Herod = "Герод",
["Hex Lord Malacrass"] = "Повелитель проклятий Малакрасс",
["High Astromancer Solarian"] = "Верховный звездочет Солариан",
["High Botanist Freywinn"] = "Верховный ботаник Фрейвин",
["High Inquisitor Fairbanks"] = "Верховный инквизитор Фэйрбанкс",
["High Inquisitor Whitemane"] = "Верховный инквизитор Вайтмейн",
["High Interrogator Gerstahn"] = "Верховный дознаватель Герштан",
["High King Maulgar"] = "Король Молгар",
["Highlord Mograine"] = "Верховный лорд Могрейн",
["Highlord Omokk"] = "Вождь Омокк",
["High Marshal Whirlaxis"] = "Маршал Кольцекрут",
["High Nethermancer Zerevor"] = "Верховный пустомант Зеревор",
["High Overlord Saurfang"] = "Верховный правитель Саурфанг",
["High Priestess Arlokk"] = "Верховная жрица Арлокк",
["High Priestess Jeklik"] = "Верховная жрица Джеклик",
["High Priestess Mar'li"] = "Верховная жрица Мар'ли",
["High Priestess of Thaurissan"] = "Верховная жрица Тауриссана",
["High Priest Thekal"] = "Верховный жрец Текал",
["High Priest Venoxis"] = "Верховный жрец Веноксис",
["High Warlord Naj'entus"] = "Верховный Полководец Надж'ентус",
Hodir = "Ходир",
["Houndmaster Grebmar"] = "Псарь Гребмар",
["Houndmaster Loksey"] = "Псарь Локси",
Hukku = "Хукку",
Hungarfen = "Топеглад",
["Hurley Blackbreath"] = "Харли Чернопых",
["Hyakiss the Lurker"] = "Хиакисс Скрытень",
["Hydromancer Thespia"] = "Гидромант Теспия",
["Hydromancer Velratha"] = "Гидромант Велрата",
Hydrospawn = "Гидротварь",
["Hydross the Unstable"] = "Гидросс Нестабильный",
["Icecrown Gunship Battle"] = "Бой на кораблях",
Icehowl = "Ледяной Рев",
["Ice Sphere"] = "Ледяная сфера",
Ichoron = "Гнойрон",
Ick = "Ик", -- Needs review
["Ignis the Furnace Master"] = "Повелитель Горнов Игнис",
["Illidan Stormrage"] = "Иллидан Ярость Бури",
["Illidari Council"] = "Совет Иллидари",
["Illyanna Ravenoak"] = "Иллиана Воронья Ольха",
["Immol'thar"] = "Бессмер'тер",
["Infinite Corruptor"] = "Осквернитель из рода Бесконечности",
["Infinity Blades"] = "Клинки Бесконечности",
["Ingvar the Plunderer"] = "Ингвар Расхититель",
["Instructor Malicia"] = "Инструктор Коварница",
["Instructor Razuvious"] = "Инструктор Разувий",
["Interrogator Vishas"] = "Дознаватель Вишас",
Ionar = "Ионар",
Ironaya = "Иронайа",
Ironspine = "Железноспин",
Isalien = "Изалиен",
Jade = "Нефрит",
["Jammal'an the Prophet"] = "Джаммал'ан Пророк",
["Jan'alai"] = "Джан'алай",
["Jandice Barov"] = "Джандис Барова",
["Jedoga Shadowseeker"] = "Джедога Искательница Теней",
["Jed Runewatcher"] = "Джед Руновед",
["Jergosh the Invoker"] = "Жергош Призыватель Духов",
["Jin'do the Hexxer"] = "Джин'до Проклинатель",
["Jormungar Behemoth"] = "Йормунгарское чудовище",
Jormungars = "Йормунгары",
Julianne = "Джулианна",
["Junk Bot"] = "Барахлобот",
["Kael'thas Sunstrider"] = "Кель'тас Солнечный Скиталец",
Kalecgos = "Калесгос",
["Kam Deepfury"] = "Кам Гневливый",
["Kazkaz the Unholy"] = "Казказ Нечистый",
["Kaz'rogal"] = "Каз'рогал",
["Keli'dan the Breaker"] = "Кели'дан Разрушитель",
["Kel'Thuzad"] = "Кел'Тузад",
Keristrasza = "Керистраза",
["Kiggler the Crazed"] = "Кигглер Безумный",
["Kil'jaeden"] = "Кил'джеден",
["Kil'rek"] = "Кил'рек",
["King Dred"] = "Король Дред",
["King Gordok"] = "Король Гордок",
["King Llane Piece"] = "Король Ллейн",
["King Ymiron"] = "Король Имирон",
["Kirtonos the Herald"] = "Киртонос Глашатай",
["Knot Thimblejack's Cache"] = "Тайник Уззла Наперстяка",
Kolk = "Колк",
Kologarn = "Кологарн",
["Koralon the Flame Watcher"] = "Коралон Страж Огня",
Kormok = "Кормок",
Kresh = "Криг",
Krick = "Крик",
["Krick and Ick"] = "Крик и Ик", -- Needs review
["Krik'thir the Gatewatcher"] = "Крик'Тир Хранитель Врат",
["Krosh Firehand"] = "Крош Огненная Рука",
Krystallus = "Кристаллус",
Kurinnaxx = "Куриннакс",
["Lady Anacondra"] = "Повелительница Анакондра",
["Lady Blaumeux"] = "Леди Бломе",
["Lady Deathwhisper"] = "Леди Смертный Шепот",
["Lady Illucia Barov"] = "Леди Иллюсия Барова",
["Lady Malande"] = "Леди Маланда",
["Lady Sacrolash"] = "Леди Сакролаш",
["Lady Sarevess"] = "Леди Саревесс",
["Lady Vashj"] = "Леди Вайш",
Laj = "Ладж",
Landslide = "Сель",
Lavanthor = "Лавантор",
["Left Arm"] = "Левая рука",
["Leotheras the Blind"] = "Леотерас Слепец",
Lethon = "Летон",
Lethtendris = "Лефтендрис",
["Leviathan Mk II"] = "Левиафан II",
["Ley-Guardian Eregos"] = "Хранитель энергии Эрегос",
["Lieutenant Drake"] = "Лейтенант Дрейк",
["Lieutenant General Andorov"] = "Генерал-лейтенант Андоров",
Loatheb = "Лотхиб",
Loken = "Локен",
["Lord Alexei Barov"] = "Лорд Алексей Баров",
["Lord Cobrahn"] = "Лорд Кобран",
["Lord Hel'nurath"] = "Лорд Хел'нурат",
["Lord Incendius"] = "Лорд Опалитель",
["Lord Jaraxxus"] = "Лорд Джараксус",
["Lord Kazzak"] = "Лорд Каззак",
["Lord Kri"] = "Лорд Кри",
["Lord Marrowgar"] = "Лорд Ребрад",
["Lord Pythas"] = "Лорд Питонас",
["Lord Roccor"] = "Лорд Роккор",
["Lord Sanguinar"] = "Лорд Сангвинар",
["Lord Serpentis"] = "Лорд Серпентис",
["Lord Skwol"] = "Лорд Сквол",
["Lord Valthalak"] = "Лорд Вальтхалак",
["Lord Victor Nefarius"] = "Лорд Виктор Нефариус",
["Lord Vyletongue"] = "Лорд Злоязыкий",
["Lorekeeper Polkelt"] = "Сказитель Полкелт",
Loro = "Лоро",
Lucifron = "Люцифрон",
["Mad Magglish"] = "Безумный Магглиш",
Maexxna = "Мексна",
["Mage-Lord Urom"] = "Маг-лорд Уром",
["Magister Kalendris"] = "Магистр Календрис",
["Magistrate Barthilas"] = "Мировой судья Бартилас",
Magmadar = "Магмадар",
Magmus = "Магмус",
Magra = "Магра",
Magtheridon = "Магтеридон",
["Maiden of Grief"] = "Дева Скорби",
["Maiden of Virtue"] = "Благочестивая дева",
["Majordomo Executus"] = "Мажордом Экзекутус",
Malacrass = "Малакрасс",
["Maleki the Pallid"] = "Малекай Бледный",
["Mal'Ganis"] = "Мал'Ганис",
Malygos = "Малигос",
Maraudos = "Мародос",
["Marduk Blackpool"] = "Мардук Блэкпул",
["Marisa du'Paige"] = "Мариса дю Пэж",
Marwyn = "Марвин",
["Master Engineer Telonicus"] = "Старший инженер Телоникус",
["Maur Grimtotem"] = "Маур Зловещий Тотем",
Meathook = "Мясной Крюк",
["Mechano-Lord Capacitus"] = "Механо-лорд Конденсарон",
Medivh = "Медив",
["Mekgineer Steamrigger"] = "Мекжинер Паропуск",
["Mekgineer Thermaplugg"] = "Мекжинер Термоштепсель",
["Mennu the Betrayer"] = "Менну Предатель",
["Meshlok the Harvester"] = "Мешлок Жнец",
Midnight = "Полночь",
Mijan = "Миджан",
Mimiron = "Мимирон",
["Miner Johnson"] = "Шахтер Джонсон",
["Mistress of Pain"] = "Госпожа Боли",
Moam = "Моам",
Mogor = "Могор",
["Mokra the Skullcrusher"] = "Мокра Дробитель Черепов",
Moorabi = "Мураби",
Moragg = "Морагг",
["Mordresh Fire Eye"] = "Мордреш Огненный Глаз",
["Mor Grayhoof"] = "Мор Серое Копыто",
Moroes = "Мороуз",
["Morogrim Tidewalker"] = "Морогрим Волноступ",
Morphaz = "Морфаз",
["Mother Shahraz"] = "Матушка Шахраз",
["Mother Smolderweb"] = "Мать Дымная Паутина",
["Mr. Smite"] = "Мистер Каюк",
["Muradin Bronzebeard"] = "Мурадин Бронзобород",
["Murkblood Twin"] = "Близнец Темной Крови",
["Murkblood Twins"] = "Близнецы Темной Крови",
Murmur = "Бормотун",
["Murta Grimgut"] = "Мурта Мрачнобрюх",
["M'uru"] = "М'ару",
Mushgog = "Мушгог",
["Mutanus the Devourer"] = "Мутанус Пожиратель",
Nalorakk = "Налоракк",
Nazan = "Назан",
Nefarian = "Нефариан",
["Nekrum Gutchewer"] = "Некрум Кишкожуй",
["Nerub'enkan"] = "Неруб'энкан",
["Nethermancer Sepethrea"] = "Пустомант Сепетрея",
Netherspite = "Гнев Пустоты",
["Netherstrand Longbow"] = "Длинный лук Края Пустоты",
["Nexus-Prince Shaffar"] = "Принц Шаффар",
Nightbane = "Ночная Погибель",
["Noth the Plaguebringer"] = "Нот Чумной",
["Novos the Summoner"] = "Новос Призыватель",
Noxxion = "Ноксион",
["Obsidian Sentinel"] = "Обсидиановый часовой",
["Odo the Blindwatcher"] = "Одо Слепой Страж",
["Ogom the Wretched"] = "Огом Презренный",
["Ok'thor the Breaker"] = "Ок'тор Разрушитель",
["Old Serra'kis"] = "Старина Серракис",
["Olm the Summoner"] = "Олм Созывающий",
["Omor the Unscarred"] = "Омор Неодолимый",
Onyxia = "Ониксия",
["Orgrim's Hammer"] = "Молот Оргрима",
["Ormorok the Tree-Shaper"] = "Орморок Воспитатель Дерев",
["Oro Eyegouge"] = "Оро Вырвиглаз",
["Ossirian the Unscarred"] = "Оссириан Неуязвимый",
Ouro = "Оуро",
["Overlord Ramtusk"] = "Властитель Таранный Клык",
["Overlord Wyrmthalak"] = "Властитель Змейталак",
["Overmaster Pyron"] = "Подчинитель Пирон",
["Overseer Tidewrath"] = "Наблюдатель Гнев Прилива",
Pandemonius = "Пандемоний",
["Panzor the Invincible"] = "Панцер Непобедимый",
Patchwerk = "Лоскутик",
["Pathaleon the Calculator"] = "Паталеон Вычислитель",
Phalanx = "Фаланкс",
["Phaseshift Bulwark"] = "Фазовый колет",
Pimgib = "Пимгиб",
["Plaguemaw the Rotting"] = "Чумобрюх Гнилой",
["Plugger Spazzring"] = "Штоппор Наливалс",
["Postmaster Malown"] = "Почтальон Мэлоун",
["Priestess Delrissa"] = "Жрица Делрисса",
["Prince Keleseth"] = "Принц Келесет",
["Prince Malchezaar"] = "Принц Малчезар",
["Prince Skaldrenox"] = "Принц Скальдренокс",
["Princess Huhuran"] = "Принцесса Хухуран",
["Princess Moira Bronzebeard"] = "Принцесса Мойра Бронзобород",
["Princess Tempestria"] = "Принцесса Бурилла",
["Princess Theradras"] = "Принцесса Терадрас",
["Princess Yauj"] = "Принцесса Яудж",
["Prince Taldaram"] = "Принц Талдарам",
["Prince Tenris Mirkblood"] = "Принц Тенрис Мутная Кровь",
["Prince Tortheldrin"] = "Принц Тортелдрин",
["Prince Valanar"] = "Принц Валанар",
["Professor Putricide"] = "Профессор Мерзоцид",
["Pure Spawn of Hydross"] = "Чистое порождение Гидросса",
Pusillin = "Пузиллин",
["Pyroguard Emberseer"] = "Пиростраж Созерцатель Углей",
["Pyromancer Loregrain"] = "Пироман Зерно Мудрости",
Quagmirran = "Квагмирран",
["Quartermaster Zigris"] = "Интендант Зигрис",
["Rage Winterchill"] = "Лютый Хлад",
Ragglesnout = "Круглорыл",
["Raging Spirit"] = "Гневный дух",
Ragnaros = "Рагнарос",
["Ramstein the Gorger"] = "Рамштайн Ненасытный",
["Ras Frostwhisper"] = "Рас Ледяной Шепот",
Rattlegore = "Громоклин",
["Razorclaw the Butcher"] = "Остроклык Мясник",
["Razorgore the Untamed"] = "Бритвосмерт Неукротимый",
Razorlash = "Бритвохлест",
Razorscale = "Острокрылая",
["Reliquary of Souls"] = "Гробница душ",
Renataki = "Ренатаки",
["Restless Skeleton"] = "Недремлющий скелет",
Rethilgore = "Ретилгор",
Revelosh = "Ревелош",
["Rhahk'Zor"] = "Рак'Зор",
["Ribbly Screwspigot"] = "Риббли Крутипроб",
["Right Arm"] = "Правая рука",
Roar = "Хохотун",
["Rokad the Ravager"] = "Рокад Опустошитель",
["Rokdar the Sundered Lord"] = "Рокдар Покинутый Лорд",
["Rokmar the Crackler"] = "Рокмар Трескун",
Romulo = "Ромуло",
["Romulo & Julianne"] = "Ромуло и Джульенна",
Rotface = "Гниломорд",
Rotgrip = "Гнилопасть",
["Runemaster Molgeim"] = "Мастер рун Молгейм",
["Runok Wildmane"] = "Рунок Буйногривый",
Ruuzlu = "Руузлу",
["Salramm the Fleshcrafter"] = "Салрамм Плоторез",
["Sanctum Sentry"] = "Часовой святилища",
["Sandarr Dunereaver"] = "Сандарр Разоритель Барханов",
["Sandfury Executioner"] = "Палач из клана Песчаной Бури",
Sapphiron = "Сапфирон",
Sara = "Сара",
["Saronite Animus"] = "Саронитовый враг",
Sartharion = "Сартарион",
["Sathrovarr the Corruptor"] = "Сатроварр Осквернитель",
-- ["Saviana Ragefire"] = "",
["Scarlet Commander Mograine"] = "Командир Могрейн из Алого ордена",
["Scourgelord Tyrannus"] = "Повелитель Плети Тираний",
["Seeth'rel"] = "Сит'рел",
["Selin Fireheart"] = "Селин Огненное Сердце",
["Sergeant Bly"] = "Сержант Блай",
["Shade of Akama"] = "Тень Акамы",
["Shade of Aran"] = "Тень Арана",
["Shade of Eranikus"] = "Тень Эраникуса",
["Shadikith the Glider"] = "Шадикит Скользящий",
["Shadow Hunter Vosh'gajin"] = "Темная охотница Вос'гаджин",
["Shadow of Leotheras"] = "Тень Леотераса",
["Shadowpriest Sezz'ziz"] = "Темный жрец Шезз'зиз",
Shadron = "Шадрон",
Shazzrah = "Шаззрах",
["Shirrak the Dead Watcher"] = "Ширрак Страж Мертвых",
Sindragosa = "Синдрагоса",
["Sir Zeliek"] = "Сэр Зелиек",
["Sjonnir The Ironshaper"] = "Сьоннир Литейщик",
["Skadi the Ruthless"] = "Скади Безжалостный",
["Skarr the Unbreakable"] = "Скарр Непреклонный",
["Skarvald the Constructor"] = "Скальвард Строитель",
["Skra'gath"] = "Скрагат",
Skul = "Череп",
Skum = "Шкам",
["Slad'ran"] = "Слад'ран",
Sneed = "Снид",
["Sneed's Shredder"] = "Крошшер Снида",
["Solakar Flamewreath"] = "Солакарский огнечервь",
["Solarium Agent"] = "Агент Солнечной террасы",
["Solarium Priest"] = "Жрец Солнечной террасы",
["Spirestone Battle Lord"] = "Полководец из клана Черной Вершины",
["Spirestone Butcher"] = "Мясник из клана Черной Вершины",
["Spirestone Lord Magus"] = "Лорд-волхв из клана Черной Вершины",
["Staff of Disintegration"] = "Посох Распыления",
Stalagg = "Сталагг",
Steelbreaker = "Сталелом",
["Stomper Kreeg"] = "Топотун Криг",
Stonespine = "Каменный Гребень",
["Stormcaller Brundir"] = "Буревестник Брундир",
Strawman = "Балбес",
["Sulfuron Harbinger"] = "Предвестник Сульфурон",
Supremus = "Супремус",
["Svala Sorrowgrave"] = "Свала Вечноскорбящая",
["Swamplord Musel'ek"] = "Владыка болота Мусел'ек",
Taerar = "Таэрар",
["Tainted Spawn of Hydross"] = "Оскверненное порождение Гидросса",
["Talon King Ikiss"] = "Король воронов Айкисс",
["Taragaman the Hungerer"] = "Тарагаман Ненасытный",
["Targorr the Dread"] = "Таргорр Ужасный",
Tavarok = "Таварок",
Techbot = "Техбот",
Temporus = "Темпорус",
["Tendris Warpwood"] = "Тендрис Криводрев",
Tenebron = "Тенеброн",
["Terestian Illhoof"] = "Терестиан Больное Копыто",
["Teron Gorefiend"] = "Терон Кровожад",
Thaddius = "Таддиус",
["Thaladred the Darkener"] = "Таладред Затемнитель",
["Thane Korth'azz"] = "Тан Кортазз",
["The Beast"] = "Зверь",
["The Beasts of Northrend"] = "Нордскольские чудовища",
["The Big Bad Wolf"] = "Злой и страшный серый волк",
["The Black Knight"] = "Черный рыцарь",
["The Black Stalker"] = "Черная Охотница",
["The Blue Brothers"] = "Синие братья",
["The Bug Family"] = "Семейство насекомых",
["The Crone"] = "Ведьма",
["The Curator"] = "Смотритель",
["The Eredar Twins"] = "Близнецы Эредара",
["The Four Horsemen"] = "Четыре Всадника",
["The Illidari Council"] = "Совет Иллидари",
["The Iron Council"] = "Железное собрание",
["Theka the Martyr"] = "Тека Мученик",
["The Lich King"] = "Король-лич",
["The Lurker Below"] = "Скрытень глубин",
["The Maker"] = "Мастер",
["The Prophet Skeram"] = "Пророк Скерам",
["The Prophet Tharon'ja"] = "Пророк Тарон'джа",
["The Ravenian"] = "Равениан",
["The Razza"] = "Разза",
["The Seven Dwarves"] = "Темные хранители",
["The Skybreaker"] = "Усмиритель небес",
["The Tribunal of Ages"] = "Трибунал веков",
["The Twin Emperors"] = "Близнецы Императора",
["The Twin Val'kyr"] = "Валь'киры-близнецы",
["The Unforgiven"] = "Непрощенный",
["The Windreaver"] = "Ветробой",
Thorim = "Торим",
["Thorngrin the Tender"] = "Скалезуб Скорбный",
["Tidewalker Lurker"] = "Приливный крадень",
["Timmy the Cruel"] = "Тайлер",
Tinhead = "Медноголовый",
["Tinkerer Gizlock"] = "Ремонтник Гизлок",
["Tirion Fordring"] = "Тирион Фордринг",
Tito = "Тито",
["Toravon the Ice Watcher"] = "Торавон Страж Льда",
["Trigore the Lasher"] = "Тригор Хлестун",
Trollgore = "Кровотролль",
["Tsu'zee"] = "Цу'зи",
["Tuten'kash"] = "Тутен'каш",
["Twilight Lord Kelris"] = "Повелитель сумрака Келрис",
["Urok Doomhowl"] = "Аррок Смертный Вопль",
["Vaelastrasz the Corrupt"] = "Валестраз Порочный",
["Valithria Dreamwalker"] = "Валитрия Сноходица",
["Val'kyr Shadowguard"] = "Валь'кира - страж Тьмы",
["Varian Wrynn"] = "Вариан Ринн",
["Varos Cloudstrider"] = "Варос Заоблачный Странник",
Vazruden = "Вазруден",
["Vazruden the Herald"] = "Геральд Вазруден",
Vectus = "Вектус",
Vem = "Вем",
Veng = "Венг",
["Veras Darkshadow"] = "Верас Глубокий Мрак",
["Verdan the Everliving"] = "Вердан Бессмертный",
Verek = "Верек",
Vesperon = "Весперон",
Vexallus = "Вексалиус",
["Veyzhak the Cannibal"] = "Вейжак Каннибал",
["Vile'rel"] = "Гнус'рел",
Viscidus = "Нечистотон",
["Viscous Fallout"] = "Липкая муть",
["Void Reaver"] = "Страж Бездны",
Volkhan = "Волхан",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "О'мрогг Завоеватель",
["Warchief Blackhand Piece"] = "Боевой вождь Чернорук",
["Warchief Kargath Bladefist"] = "Вождь Каргат Острорук",
["Warchief Rend Blackhand"] = "Вождь Ренд Чернорук",
["Warden Mellichar"] = "Страж Мелличар",
["Warder Stilgiss"] = "Тюремщик Стилгисс",
["Warlord Kalithresh"] = "Полководец Калитреш",
["War Master Voone"] = "Воевода Вун",
["Warmaul Champion"] = "Чемпион клана Боевого Молота",
["Warp Slicer"] = "Искореженная ломтерезка",
["Warp Splinter"] = "Узлодревень",
["Watchkeeper Gargolmar"] = "Начальник стражи Гарголмар",
Weaver = "Ткачик",
["Witch Doctor Zum'rah"] = "Знахарь Зум'рах",
["Wolf Master Nandos"] = "Командир воргенов Нандос",
["Wrath-Scryer Soccothrates"] = "Провидец Гнева Соккорат",
Wushoolay = "Вушулай",
Xevozz = "Ксевозз",
["XT-002 Deconstructor"] = "Разрушитель XT-002",
["Yogg-Saron"] = "Йогг-Сарон",
Ysondre = "Исондра",
Zekkis = "Зеккис",
["Zelemar the Wrathful"] = "Зелемар Гневный",
["Zereketh the Unbound"] = "Зерекет Бездонный",
Zerillis = "Зериллис",
["Zevrim Thornhoof"] = "Зеврим Терновое Копыто",
Zolo = "Золо",
["Zul'Farrak Dead Hero"] = "Мертвый Герой Зул'Фаррака",
["Zul'jin"] = "Зул'джин",
["Zul'Lor"] = "Зул'Лор",
["Zul'tore"] = "Зул'тор",
["Zuramat the Obliterator"] = "Зурамат Уничтожитель",
}
elseif GAME_LOCALE == "zhCN" then
lib:SetCurrentTranslations {
Acidmaw = "酸喉",
Aeonus = "埃欧努斯",
["Aerial Command Unit"] = "空中指挥单位",
["Agathelos the Raging"] = "暴怒的阿迦赛罗斯",
Ahune = "埃霍恩",
["Akil'zon"] = "埃基尔松",
["Aku'mai"] = "阿库麦尔",
["Al'ar"] = "奥",
["Algalon the Observer"] = "观察者奥尔加隆",
["Alzzin the Wildshaper"] = "奥兹恩",
Amanitar = "埃曼尼塔",
["Ambassador Flamelash"] = "弗莱拉斯大使",
["Ambassador Hellmaw"] = "赫尔默大使",
["Amnennar the Coldbringer"] = "寒冰之王亚门纳尔",
["Ancient Stone Keeper"] = "古代的石头看守者",
Anetheron = "安纳塞隆",
["Anger'rel"] = "安格雷尔",
Anomalus = "阿诺玛鲁斯",
["Antu'sul"] = "安图苏尔",
["Anub'arak"] = "阿努巴拉克",
["Anubisath Defender"] = "阿努比萨斯防御者",
["Anubisath Guardian"] = "阿努比萨斯守卫者",
["Anub'Rekhan"] = "阿努布雷坎",
["Anub'shiah"] = "阿努希尔",
Anzu = "安苏",
["Arcane Watchman"] = "奥术看守",
["Arcanist Doan"] = "奥法师杜安",
Archaedas = "阿扎达斯",
["Archavon the Stone Watcher"] = "岩石看守者阿尔卡冯",
Archimonde = "阿克蒙德",
["Archivist Galford"] = "档案管理员加尔福特",
["Archmage Arugal"] = "大法师阿鲁高",
["Argent Confessor Paletress"] = "银色神官帕尔崔丝",
["Arugal's Voidwalker"] = "阿鲁高的虚空行者",
["Assault Bot"] = "突击机器人",
["Atal'alarion"] = "阿塔拉利恩",
["Attumen the Huntsman"] = "猎手阿图门",
Auriaya = "欧尔莉亚",
Avalanchion = "阿瓦兰奇奥",
["Avatar of Hakkar"] = "哈卡的化身",
["Ayamiss the Hunter"] = "狩猎者阿亚米斯",
Azgalor = "阿兹加洛",
["Azshir the Sleepless"] = "永醒的艾希尔",
Azuregos = "艾索雷葛斯",
["Bael'Gar"] = "贝尔加",
Baelog = "巴尔洛戈",
Balnazzar = "巴纳扎尔",
["Baltharus the Warborn"] = "Baltharus the Warborn", -- Needs review
["Bannok Grimaxe"] = "班诺克·巨斧",
["Baron Aquanis"] = "阿奎尼斯男爵",
["Baron Charr"] = "火焰男爵查尔",
["Baroness Anastari"] = "安娜丝塔丽男爵夫人",
["Baron Geddon"] = "迦顿男爵",
["Baron Kazum"] = "卡苏姆男爵",
["Baron Rivendare"] = "瑞文戴尔男爵",
["Baron Silverlaine"] = "席瓦莱恩男爵",
["Battleguard Sartura"] = "沙尔图拉",
["Bazil Thredd"] = "巴基尔·斯瑞德",
Bazzalan = "巴扎兰",
["Black Guard Swordsmith"] = "黑衣守卫铸剑师",
["Blackheart the Inciter"] = "煽动者布莱卡特",
["Blindeye the Seer"] = "盲眼先知",
["Blind Hunter"] = "盲眼猎手",
["Blood Guard Porung"] = "血卫士伯鲁恩",
["Bloodlord Mandokir"] = "血领主曼多基尔",
["Bloodmage Thalnos"] = "血法师萨尔诺斯",
["Blood Prince Council"] = "鲜血王子议会",
["Blood Princes"] = "鲜血王子",
["Blood-Queen Lana'thel"] = "鲜血女王兰娜瑟尔",
["Blood Steward of Kirtonos"] = "基尔图诺斯的卫士",
Boahn = "博艾恩",
["Bomb Bot"] = "炸弹机器人",
["Brain of Yogg-Saron"] = "尤格-萨隆的大脑",
["Brainwashed Noble"] = "被洗脑的贵族",
Broggok = "布洛戈克",
Brokentoe = "断蹄",
Bronjahm = "布隆亚姆",
["Broodlord Lashlayer"] = "勒什雷尔",
["Bruegal Ironknuckle"] = "布鲁高·铁拳",
Brutallus = "布鲁塔卢斯",
["Burning Felguard"] = "燃烧地狱卫士",
["Buru the Gorger"] = "吞咽者布鲁",
["Cache of the Firelord"] = "火焰之王的宝箱",
["Cannon Master Willey"] = "炮手威利",
["Captain Greenskin"] = "绿皮队长",
["Captain Kromcrush"] = "克罗卡斯",
["Captain Skarloc"] = "斯卡洛克上尉",
["Celebras the Cursed"] = "被诅咒的塞雷布拉斯",
["Charlga Razorflank"] = "卡尔加·刺肋",
["Chess Event"] = "国际象棋",
["Chest of The Seven"] = "七贤之箱",
["Chief Ukorz Sandscalp"] = "乌克兹·沙顶",
["Cho'Rush the Observer"] = "观察者克鲁什",
Chromaggus = "克洛玛古斯",
["Chrono Lord Deja"] = "时空领主德亚",
["Chrono-Lord Epoch"] = "时光领主埃博克",
Claw = "克劳恩",
["Coilfang Elite"] = "盘牙精英",
["Coilfang Strider"] = "盘牙巡逻者",
["Commander Kolurg"] = "指挥官库鲁尔格",
["Commander Sarannis"] = "指挥官萨拉妮丝",
["Commander Springvale"] = "指挥官斯普林瓦尔",
["Commander Stoutbeard"] = "指挥官斯托比德",
["Constructor & Controller"] = "建筑师与控制者",
Cookie = "曲奇",
["Coren Direbrew"] = "科林·烈酒",
["Cosmic Infuser"] = "宇宙灌注者",
["Crimson Hammersmith"] = "红衣铸锤师",
["Crowd Pummeler 9-60"] = "群体打击者9-60",
["Crystal Fang"] = "水晶之牙",
["C'Thun"] = "克苏恩",
Cyanigosa = "塞安妮苟萨",
["Dalliah the Doomsayer"] = "末日预言者达尔莉安",
["Dalronn the Controller"] = "控制者达尔隆",
["Dark Iron Ambassador"] = "黑铁大师",
["Darkmaster Gandling"] = "黑暗院长加丁",
["Darkweaver Syth"] = "黑暗编织者塞斯",
["Deathbound Ward"] = "缚亡守卫",
["Deathbringer Saurfang"] = "死亡使者萨鲁法尔",
["Death Knight Darkreaver"] = "死亡骑士达克雷尔",
["Death Knight Understudy"] = "见习死亡骑士",
["Deathspeaker High Priest"] = "亡语高阶祭司",
["Death Speaker Jargba"] = "亡语者贾格巴",
["Deathstalker Visceri"] = "死亡猎手维瑟里",
["Deathsworn Captain"] = "死亡之誓",
Devastation = "毁坏",
["Deviate Faerie Dragon"] = "变异精灵龙",
["Devourer of Souls"] = "噬魂者",
["Dextren Ward"] = "迪克斯特·瓦德",
["Digmaster Shovelphlange"] = "挖掘专家舒尔弗拉格",
["Doctor Theolen Krastinov"] = "瑟尔林·卡斯迪诺夫教授",
["Doom Lord Kazzak"] = "末日领主卡扎克",
["Doom'rel"] = "杜姆雷尔",
Doomwalker = "末日行者",
["Dope'rel"] = "多普雷尔",
Dorothee = "多萝茜",
["Drakkari Colossus"] = "达卡莱巨像",
["Drakos the Interrogator"] = "审讯者达库斯",
Dreadscale = "恐鳞",
Dreamscythe = "德姆塞卡尔",
["Dust Covered Chest"] = "灰尘覆盖的箱子",
Dustwraith = "灰尘怨灵",
["Eadric the Pure"] = "纯洁者耶德瑞克",
["Earthcaller Halmgar"] = "唤地者哈穆加",
Ebonroc = "埃博诺克",
["Eck the Ferocious"] = "凶残的伊克",
["Edwin VanCleef"] = "艾德温·范克里夫",
["Elder Brightleaf"] = "明叶长老",
["Elder Ironbranch"] = "铁枝长老",
["Elder Nadox"] = "纳多克斯长老",
["Elder Stonebark"] = "石树长老",
["Electrocutioner 6000"] = "电刑器6000型",
["Emalon the Storm Watcher"] = "风暴看守者埃玛尔隆",
Emeriss = "艾莫莉丝",
["Emperor Dagran Thaurissan"] = "达格兰·索瑞森大帝",
["Emperor Vek'lor"] = "维克洛尔大帝",
["Emperor Vek'nilash"] = "维克尼拉斯大帝",
Entropius = "熵魔",
["Eonar's Gift"] = "艾欧娜尔的礼物",
["Epoch Hunter"] = "时空猎手",
Erekem = "埃雷克姆",
["Eressea Dawnsinger"] = "伊蕾希亚·晨歌",
["Essence of Anger"] = "愤怒精华",
["Essence of Desire"] = "欲望精华",
["Essence of Suffering"] = "苦痛精华",
Eviscerator = "剜眼者",
["Exarch Maladaar"] = "大主教玛拉达尔",
["Expedition Commander"] = "远征军指挥官",
["Eydis Darkbane"] = "黑暗邪使艾蒂丝",
["Eye of C'Thun"] = "克苏恩之眼",
["Faction Champions"] = "阵营冠军",
["Fallen Champion"] = "死灵勇士",
Falric = "法瑞克",
["Falric and Marwyn"] = "法瑞克和玛维恩",
["Fankriss the Unyielding"] = "顽强的范克瑞斯",
["Fathom-Lord Karathress"] = "深水领主卡拉瑟雷斯",
Felmyst = "菲米丝",
["Fenrus the Devourer"] = "吞噬者芬鲁斯",
["Feral Defender"] = "野性防御者",
Festergut = "烂肠",
Feugen = "费尔根",
["Fineous Darkvire"] = "弗诺斯·达克维尔",
Firemaw = "费尔默",
["Fjola Lightbane"] = "光明邪使菲奥拉",
Flamegor = "弗莱格尔",
["Flame Leviathan"] = "烈焰巨兽",
["Foreman Thistlenettle"] = "工头希斯耐特",
["Forgemaster Garfrost"] = "熔炉之主加弗斯特",
["Four Horsemen Chest"] = "四骑士之箱",
["Fras Siabi"] = "弗拉斯·希亚比",
Freya = "弗蕾亚",
["Gahz'ranka"] = "加兹兰卡",
["Gahz'rilla"] = "加兹瑞拉",
["Gal'darah"] = "迦尔达拉",
["Galgann Firehammer"] = "加加恩·火锤",
Garr = "加尔",
["Garrosh Hellscream"] = "加尔鲁什·地狱咆哮",
Gasher = "加什尔",
["Gatewatcher Gyro-Kill"] = "看守者盖罗基尔",
["Gatewatcher Iron-Hand"] = "看守者埃隆汉",
["Gathios the Shatterer"] = "击碎者加西奥斯",
Gehennas = "基赫纳斯",
Gelihast = "格里哈斯特",
Gelk = "吉尔克",
["General Angerforge"] = "安格弗将军",
["General Bjarngrim"] = "比亚格里将军",
["General Drakkisath"] = "达基萨斯将军",
["General Rajaxx"] = "拉贾克斯将军",
["General Vezax"] = "维扎克斯将军",
["General Zarithrian"] = "General Zarithrian", -- Needs review
["Ghamoo-ra"] = "加摩拉",
["Ghaz'an"] = "加兹安",
["Ghok Bashguud"] = "霍克·巴什古德",
Gilnid = "基尔尼格",
["Gizrul the Slavener"] = "奴役者基兹鲁尔",
["Gloom'rel"] = "格鲁雷尔",
Gluth = "格拉斯",
Glutton = "暴食者",
["Golemagg the Incinerator"] = "焚化者古雷曼格",
["Golem Lord Argelmach"] = "傀儡统帅阿格曼奇",
["Goraluk Anvilcrack"] = "古拉鲁克",
["Gormok the Impaler"] = "穿刺者哥莫克",
["Gorosh the Dervish"] = "修行者高罗什",
["Gortok Palehoof"] = "戈托克·苍蹄",
["Gothik the Harvester"] = "收割者戈提克",
["Grand Astromancer Capernian"] = "星术师卡波妮娅",
["Grand Champions"] = "总冠军",
["Grand Magus Telestra"] = "大魔导师泰蕾丝塔",
["Grandmaster Vorpil"] = "沃匹尔大师",
Grandmother = "老奶奶",
["Grand Warlock Alythess"] = "高阶术士奥蕾塞丝",
["Grand Warlock Nethekurse"] = "高阶术士奈瑟库斯",
["Grand Widow Faerlina"] = "黑女巫法琳娜",
["Grethok the Controller"] = "黑翼控制者",
["Gri'lek"] = "格里雷克",
Grimlok = "格瑞姆洛克",
Grizzle = "格里兹尔",
Grobbulus = "格罗布鲁斯",
Grubbis = "格鲁比斯",
["Gruul the Dragonkiller"] = "屠龙者格鲁尔",
["Guard Fengus"] = "卫兵芬古斯",
["Guardian of Yogg-Saron"] = "尤格-萨隆的卫士",
["Guard Mol'dar"] = "卫兵摩尔达",
["Guard Slip'kik"] = "卫兵斯里基克",
["Gurtogg Bloodboil"] = "古尔图格·血沸",
Gyth = "盖斯",
Hadronox = "哈多诺克斯",
Hakkar = "哈卡",
Halazzi = "哈尔拉兹",
Halion = "Halion", -- Needs review
Halycon = "哈雷肯",
Hamhock = "哈姆霍克",
["Harbinger Skyriss"] = "预言者斯克瑞斯",
["Hate'rel"] = "黑特雷尔",
["Hazza'rah"] = "哈扎拉尔",
Hazzas = "哈扎斯",
["Headless Horseman"] = "无头骑士",
["Hearthsinger Forresten"] = "弗雷斯特恩",
["Hedrum the Creeper"] = "爬行者赫杜姆",
["Heigan the Unclean"] = "肮脏的希尔盖",
["Hellfire Channeler"] = "地狱火导魔者",
["Henry Stern"] = "亨利·斯特恩",
["Herald Volazj"] = "传令官沃拉兹",
Herod = "赫洛德",
["Hex Lord Malacrass"] = "妖术领主玛拉卡斯",
["High Astromancer Solarian"] = "大星术师索兰莉安",
["High Botanist Freywinn"] = "高级植物学家弗雷温",
["High Inquisitor Fairbanks"] = "大检察官法尔班克斯",
["High Inquisitor Whitemane"] = "大检察官怀特迈恩",
["High Interrogator Gerstahn"] = "审讯官格斯塔恩",
["High King Maulgar"] = "莫加尔大王",
["Highlord Mograine"] = "大领主莫格莱尼",
["Highlord Omokk"] = "欧莫克大王",
["High Marshal Whirlaxis"] = "大元帅维拉希斯",
["High Nethermancer Zerevor"] = "高阶灵术师塞勒沃尔",
["High Overlord Saurfang"] = "萨鲁法尔大王",
["High Priestess Arlokk"] = "高阶祭司娅尔罗",
["High Priestess Jeklik"] = "高阶祭司耶克里克",
["High Priestess Mar'li"] = "高阶祭司玛尔里",
["High Priestess of Thaurissan"] = "索瑞森高阶女祭司",
["High Priest Thekal"] = "高阶祭司塞卡尔",
["High Priest Venoxis"] = "高阶祭司温诺希斯",
["High Warlord Naj'entus"] = "高阶督军纳因图斯",
Hodir = "霍迪尔",
["Houndmaster Grebmar"] = "驯犬者格雷布玛尔",
["Houndmaster Loksey"] = "驯犬者洛克希",
Hukku = "胡库",
Hungarfen = "霍加尔芬",
["Hurley Blackbreath"] = "霍尔雷·黑须",
["Hyakiss the Lurker"] = "潜伏者希亚其斯",
["Hydromancer Thespia"] = "水术师瑟丝比娅",
["Hydromancer Velratha"] = "水占师维蕾萨",
Hydrospawn = "海多斯博恩",
["Hydross the Unstable"] = "不稳定的海度斯",
["Icecrown Gunship Battle"] = "冰冠炮舰战斗",
Icehowl = "冰吼",
["Ice Sphere"] = "Ice Sphere", -- Needs review
Ichoron = "艾库隆",
Ick = "伊克",
["Ignis the Furnace Master"] = "掌炉者伊格尼斯",
["Illidan Stormrage"] = "伊利丹·怒风",
["Illidari Council"] = "伊利达雷议会",
["Illyanna Ravenoak"] = "伊琳娜·暗木",
["Immol'thar"] = "伊莫塔尔",
["Infinite Corruptor"] = "永恒腐蚀者",
["Infinity Blades"] = "无尽之刃",
["Ingvar the Plunderer"] = "劫掠者因格瓦尔",
["Instructor Malicia"] = "讲师玛丽希亚",
["Instructor Razuvious"] = "教官拉苏维奥斯",
["Interrogator Vishas"] = "审讯员韦沙斯",
Ionar = "艾欧纳尔",
Ironaya = "艾隆纳亚",
Ironspine = "铁脊死灵",
Isalien = "伊萨利恩",
Jade = "玉龙",
["Jammal'an the Prophet"] = "预言者迦玛兰",
["Jan'alai"] = "加亚莱",
["Jandice Barov"] = "詹迪斯·巴罗夫",
["Jedoga Shadowseeker"] = "耶戈达·觅影者",
["Jed Runewatcher"] = "杰德",
["Jergosh the Invoker"] = "祈求者耶戈什",
["Jin'do the Hexxer"] = "妖术师金度",
["Jormungar Behemoth"] = "蛰猛巨虫",
Jormungars = "冰虫",
Julianne = "朱丽叶",
["Junk Bot"] = "废物机器人",
["Kael'thas Sunstrider"] = "凯尔萨斯·逐日者",
Kalecgos = "卡雷苟斯",
["Kam Deepfury"] = "卡姆·深怒",
["Kazkaz the Unholy"] = "邪恶的卡萨卡兹",
["Kaz'rogal"] = "卡兹洛加",
["Keli'dan the Breaker"] = "击碎者克里丹",
["Kel'Thuzad"] = "克尔苏加德",
Keristrasza = "克莉斯塔萨",
["Kiggler the Crazed"] = "疯狂的基戈尔",
["Kil'jaeden"] = "基尔加丹",
["Kil'rek"] = "基尔里克",
["King Dred"] = "暴龙之王爵德",
["King Gordok"] = "戈多克大王",
["King Llane Piece"] = "莱恩国王",
["King Ymiron"] = "伊米隆国王",
["Kirtonos the Herald"] = "传令官基尔图诺斯",
["Knot Thimblejack's Cache"] = "诺特·希姆加克的储物箱",
Kolk = "考尔克",
Kologarn = "科隆加恩",
["Koralon the Flame Watcher"] = "火焰看守者科拉隆",
Kormok = "库尔莫克",
Kresh = "克雷什",
Krick = "科里克",
["Krick and Ick"] = "科里克和伊克",
["Krik'thir the Gatewatcher"] = "看门者克里克希尔",
["Krosh Firehand"] = "克洛什·火拳",
Krystallus = "克莱斯塔卢斯",
Kurinnaxx = "库林纳克斯",
["Lady Anacondra"] = "安娜科德拉",
["Lady Blaumeux"] = "女公爵布劳缪克丝",
["Lady Deathwhisper"] = "亡语者女士",
["Lady Illucia Barov"] = "伊露希亚·巴罗夫",
["Lady Malande"] = "女公爵玛兰德",
["Lady Sacrolash"] = "萨洛拉丝女王",
["Lady Sarevess"] = "萨利维丝",
["Lady Vashj"] = "瓦丝琪",
Laj = "拉伊",
Landslide = "兰斯利德",
Lavanthor = "拉文索尔",
["Left Arm"] = "左臂",
["Leotheras the Blind"] = "盲眼者莱欧瑟拉斯",
Lethon = "莱索恩",
Lethtendris = "蕾瑟塔蒂丝",
["Leviathan Mk II"] = "巨兽二型",
["Ley-Guardian Eregos"] = "魔网守护者埃雷苟斯",
["Lieutenant Drake"] = "德拉克中尉",
["Lieutenant General Andorov"] = "安多洛夫中将",
Loatheb = "洛欧塞布",
Loken = "洛肯",
["Lord Alexei Barov"] = "阿雷克斯·巴罗夫",
["Lord Cobrahn"] = "考布莱恩",
["Lord Hel'nurath"] = "赫尔努拉斯",
["Lord Incendius"] = "伊森迪奥斯",
["Lord Jaraxxus"] = "加拉克苏斯大王",
["Lord Kazzak"] = "末日领主卡扎克",
["Lord Kri"] = "克里勋爵",
["Lord Marrowgar"] = "玛洛加尔领主",
["Lord Pythas"] = "皮萨斯",
["Lord Roccor"] = "洛考尔",
["Lord Sanguinar"] = "萨古纳尔男爵",
["Lord Serpentis"] = "瑟芬迪斯",
["Lord Skwol"] = "斯古恩男爵",
["Lord Valthalak"] = "瓦塔拉克公爵",
["Lord Victor Nefarius"] = "维克多·奈法里奥斯",
["Lord Vyletongue"] = "维利塔恩",
["Lorekeeper Polkelt"] = "博学者普克尔特",
Loro = "洛若尔",
Lucifron = "鲁西弗隆",
["Mad Magglish"] = "疯狂的马格利什",
Maexxna = "迈克斯纳",
["Mage-Lord Urom"] = "法师领主伊洛姆",
["Magister Kalendris"] = "卡雷迪斯镇长",
["Magistrate Barthilas"] = "巴瑟拉斯镇长",
Magmadar = "玛格曼达",
Magmus = "玛格姆斯",
Magra = "玛格拉",
Magtheridon = "玛瑟里顿",
["Maiden of Grief"] = "悲伤圣女",
["Maiden of Virtue"] = "贞节圣女",
["Majordomo Executus"] = "管理者埃克索图斯",
Malacrass = "玛拉卡斯",
["Maleki the Pallid"] = "苍白的玛勒基",
["Mal'Ganis"] = "玛尔加尼斯",
Malygos = "玛里苟斯",
Maraudos = "玛拉多斯",
["Marduk Blackpool"] = "马杜克·布莱克波尔",
["Marisa du'Paige"] = "玛里莎·杜派格",
Marwyn = "玛维恩",
["Master Engineer Telonicus"] = "首席技师塔隆尼库斯",
["Maur Grimtotem"] = "玛尔·恐怖图腾",
Meathook = "肉钩",
["Mechano-Lord Capacitus"] = "机械领主卡帕西图斯",
Medivh = "麦迪文",
["Mekgineer Steamrigger"] = "机械师斯蒂里格",
["Mekgineer Thermaplugg"] = "麦克尼尔·瑟玛普拉格",
["Mennu the Betrayer"] = "背叛者门努",
["Meshlok the Harvester"] = "收割者麦什洛克",
Midnight = "午夜",
Mijan = "米杉",
Mimiron = "米米尔隆",
["Miner Johnson"] = "矿工约翰森",
["Mistress of Pain"] = "痛苦女王",
Moam = "莫阿姆",
Mogor = "穆戈尔",
["Mokra the Skullcrusher"] = "碎颅者莫克拉",
Moorabi = "莫拉比",
Moragg = "摩拉格",
["Mordresh Fire Eye"] = "火眼莫德雷斯",
["Mor Grayhoof"] = "莫尔·灰蹄",
Moroes = "莫罗斯",
["Morogrim Tidewalker"] = "莫洛格里·踏潮者",
Morphaz = "摩弗拉斯",
["Mother Shahraz"] = "莎赫拉丝主母",
["Mother Smolderweb"] = "烟网蛛后",
["Mr. Smite"] = "重拳先生",
["Muradin Bronzebeard"] = "穆拉丁·铜须",
["Murkblood Twin"] = "暗血双子",
["Murkblood Twins"] = "暗血双子",
Murmur = "摩摩尔",
["Murta Grimgut"] = "穆尔塔",
["M'uru"] = "穆鲁",
Mushgog = "姆斯高格",
["Mutanus the Devourer"] = "吞噬者穆坦努斯",
Nalorakk = "纳洛拉克",
Nazan = "纳杉",
Nefarian = "奈法利安",
["Nekrum Gutchewer"] = "耐克鲁姆",
["Nerub'enkan"] = "奈鲁布恩坎",
["Nethermancer Sepethrea"] = "灵术师塞比瑟蕾",
Netherspite = "虚空幽龙",
["Netherstrand Longbow"] = "灵弦长弓",
["Nexus-Prince Shaffar"] = "节点亲王沙法尔",
Nightbane = "夜之魇",
["Noth the Plaguebringer"] = "瘟疫使者诺斯",
["Novos the Summoner"] = "召唤者诺沃斯",
Noxxion = "诺克赛恩",
["Obsidian Sentinel"] = "黑曜石哨兵",
["Odo the Blindwatcher"] = "盲眼守卫奥杜",
["Ogom the Wretched"] = "可悲的奥戈姆",
["Ok'thor the Breaker"] = "破坏者奥科索尔",
["Old Serra'kis"] = "瑟拉吉斯",
["Olm the Summoner"] = "召唤者沃尔姆",
["Omor the Unscarred"] = "无疤者奥摩尔",
Onyxia = "奥妮克希亚",
["Orgrim's Hammer"] = "奥格瑞姆之锤",
["Ormorok the Tree-Shaper"] = "塑树者奥莫洛克",
["Oro Eyegouge"] = "欧罗·血眼",
["Ossirian the Unscarred"] = "无疤者奥斯里安",
Ouro = "奥罗",
["Overlord Ramtusk"] = "主宰拉姆塔斯",
["Overlord Wyrmthalak"] = "维姆萨拉克",
["Overmaster Pyron"] = "征服者派隆",
["Overseer Tidewrath"] = "工头泰德瓦斯",
Pandemonius = "潘德莫努斯",
["Panzor the Invincible"] = "无敌的潘佐尔",
Patchwerk = "帕奇维克",
["Pathaleon the Calculator"] = "计算者帕萨雷恩",
Phalanx = "方阵",
["Phaseshift Bulwark"] = "相位壁垒",
Pimgib = "匹姆吉布",
["Plaguemaw the Rotting"] = "腐烂的普雷莫尔",
["Plugger Spazzring"] = "普拉格",
["Postmaster Malown"] = "邮差马龙",
["Priestess Delrissa"] = "女祭司德莉希亚",
["Prince Keleseth"] = "凯雷塞斯王子",
["Prince Malchezaar"] = "玛克扎尔王子",
["Prince Skaldrenox"] = "斯卡德诺克斯王子",
["Princess Huhuran"] = "哈霍兰公主",
["Princess Moira Bronzebeard"] = "铁炉堡公主茉艾拉·铜须",
["Princess Tempestria"] = "泰比斯蒂亚公主",
["Princess Theradras"] = "瑟莱德丝公主",
["Princess Yauj"] = "亚尔基公主",
["Prince Taldaram"] = "塔达拉姆王子",
["Prince Tenris Mirkblood"] = "特里斯·黯血王子",
["Prince Tortheldrin"] = "托塞德林王子",
["Prince Valanar"] = "瓦拉纳王子",
["Professor Putricide"] = "普崔塞德教授",
["Pure Spawn of Hydross"] = "纯净的海度斯爪牙",
Pusillin = "普希林",
["Pyroguard Emberseer"] = "烈焰卫士艾博希尔",
["Pyromancer Loregrain"] = "控火师罗格雷恩",
Quagmirran = "夸格米拉",
["Quartermaster Zigris"] = "军需官兹格雷斯",
["Rage Winterchill"] = "雷基·冬寒",
Ragglesnout = "拉戈斯诺特",
["Raging Spirit"] = "Raging Spirit", -- Needs review
Ragnaros = "拉格纳罗斯",
["Ramstein the Gorger"] = "吞咽者拉姆斯登",
["Ras Frostwhisper"] = "莱斯·霜语",
Rattlegore = "血骨傀儡",
["Razorclaw the Butcher"] = "屠夫拉佐克劳",
["Razorgore the Untamed"] = "狂野的拉佐格尔",
Razorlash = "锐刺鞭笞者",
Razorscale = "锋鳞",
["Reliquary of Souls"] = "灵魂之匣",
Renataki = "雷纳塔基",
["Restless Skeleton"] = "无法安息的骷髅",
Rethilgore = "雷希戈尔",
Revelosh = "鲁维罗什",
["Rhahk'Zor"] = "拉克佐",
["Ribbly Screwspigot"] = "雷布里·斯库比格特",
["Right Arm"] = "右臂",
Roar = "胆小的狮子",
["Rokad the Ravager"] = "蹂躏者洛卡德",
["Rokdar the Sundered Lord"] = "裂石之王洛卡达尔",
["Rokmar the Crackler"] = "巨钳鲁克玛尔",
Romulo = "罗密欧",
["Romulo & Julianne"] = "罗密欧与朱丽叶",
Rotface = "腐面",
Rotgrip = "洛特格里普",
["Runemaster Molgeim"] = "符文大师莫尔基姆",
["Runok Wildmane"] = "鲁诺克·蛮鬃",
Ruuzlu = "卢兹鲁",
["Salramm the Fleshcrafter"] = "塑血者沙尔拉姆",
["Sanctum Sentry"] = "圣所警卫",
["Sandarr Dunereaver"] = "杉达尔·沙掠者",
["Sandfury Executioner"] = "沙怒刽子手",
Sapphiron = "萨菲隆",
Sara = "萨拉",
["Saronite Animus"] = "萨隆邪铁畸体",
Sartharion = "萨塔里奥",
["Sathrovarr the Corruptor"] = "腐蚀者萨索瓦尔",
["Saviana Ragefire"] = "Saviana Ragefire", -- Needs review
["Scarlet Commander Mograine"] = "血色十字军指挥官莫格莱尼",
["Scourgelord Tyrannus"] = "天灾领主泰兰努斯",
["Seeth'rel"] = "西斯雷尔",
["Selin Fireheart"] = "塞林·火心",
["Sergeant Bly"] = "布莱中士",
["Shade of Akama"] = "阿卡玛之影",
["Shade of Aran"] = "埃兰之影",
["Shade of Eranikus"] = "伊兰尼库斯的阴影",
["Shadikith the Glider"] = "滑翔者沙德基斯",
["Shadow Hunter Vosh'gajin"] = "暗影猎手沃什加斯",
["Shadow of Leotheras"] = "莱欧瑟拉斯之影",
["Shadowpriest Sezz'ziz"] = "暗影祭司塞瑟斯",
Shadron = "沙德隆",
Shazzrah = "沙斯拉尔",
["Shirrak the Dead Watcher"] = "死亡观察者希尔拉克",
Sindragosa = "辛达苟萨",
["Sir Zeliek"] = "瑟里耶克爵士",
["Sjonnir The Ironshaper"] = "塑铁者斯约尼尔",
["Skadi the Ruthless"] = "残忍的斯卡迪",
["Skarr the Unbreakable"] = "无敌的斯卡尔",
["Skarvald the Constructor"] = "建筑师斯卡瓦尔德",
["Skra'gath"] = "瑟克拉加斯",
Skul = "斯库尔",
Skum = "斯卡姆",
["Slad'ran"] = "斯拉德兰",
Sneed = "斯尼德",
["Sneed's Shredder"] = "斯尼德的伐木机",
["Solakar Flamewreath"] = "索拉卡·火冠",
["Solarium Agent"] = "日晷密探",
["Solarium Priest"] = "日晷祭司",
["Spirestone Battle Lord"] = "尖石统帅",
["Spirestone Butcher"] = "尖石屠夫",
["Spirestone Lord Magus"] = "尖石首席法师",
["Staff of Disintegration"] = "瓦解法杖",
Stalagg = "斯塔拉格",
Steelbreaker = "断钢者",
["Stomper Kreeg"] = "践踏者克雷格",
Stonespine = "石脊",
["Stormcaller Brundir"] = "唤雷者布隆迪尔",
Strawman = "稻草人",
["Sulfuron Harbinger"] = "萨弗隆先驱者",
Supremus = "苏普雷姆斯",
["Svala Sorrowgrave"] = "席瓦拉·索格蕾",
["Swamplord Musel'ek"] = "沼地领主穆塞雷克",
Taerar = "泰拉尔",
["Tainted Spawn of Hydross"] = "污染的海度斯爪牙",
["Talon King Ikiss"] = "利爪之王艾吉斯",
["Taragaman the Hungerer"] = "饥饿者塔拉加曼",
["Targorr the Dread"] = "可怕的塔格尔",
Tavarok = "塔瓦洛克",
Techbot = "尖端机器人",
Temporus = "坦普卢斯",
["Tendris Warpwood"] = "特迪斯·扭木",
Tenebron = "塔尼布隆",
["Terestian Illhoof"] = "特雷斯坦·邪蹄",
["Teron Gorefiend"] = "塔隆·血魔",
Thaddius = "塔迪乌斯",
["Thaladred the Darkener"] = "亵渎者萨拉德雷",
["Thane Korth'azz"] = "库尔塔兹领主",
["The Beast"] = "比斯巨兽",
["The Beasts of Northrend"] = "诺森德猛兽",
["The Big Bad Wolf"] = "大灰狼",
["The Black Knight"] = "黑骑士",
["The Black Stalker"] = "黑色阔步者",
["The Blue Brothers"] = "蓝色兄弟",
["The Bug Family"] = "虫子一家",
["The Crone"] = "巫婆",
["The Curator"] = "馆长",
["The Eredar Twins"] = "艾瑞达双子",
["The Four Horsemen"] = "四骑士",
["The Illidari Council"] = "伊利达雷议会",
["The Iron Council"] = "钢铁议会",
["Theka the Martyr"] = "殉教者塞卡",
["The Lich King"] = "巫妖王",
["The Lurker Below"] = "鱼斯拉",
["The Maker"] = "制造者",
["The Prophet Skeram"] = "预言者斯克拉姆",
["The Prophet Tharon'ja"] = "先知萨隆亚",
["The Ravenian"] = "拉文尼亚",
["The Razza"] = "拉扎尔",
["The Seven Dwarves"] = "七贤矮人",
["The Skybreaker"] = "破天号",
["The Tribunal of Ages"] = "远古法庭",
["The Twin Emperors"] = "双子皇帝",
["The Twin Val'kyr"] = "瓦格里双子",
["The Unforgiven"] = "不可宽恕者",
["The Windreaver"] = "烈风掠夺者",
Thorim = "托里姆",
["Thorngrin the Tender"] = "看管者索恩格林",
["Tidewalker Lurker"] = "踏潮潜伏者",
["Timmy the Cruel"] = "悲惨的提米",
Tinhead = "铁皮人",
["Tinkerer Gizlock"] = "工匠吉兹洛克",
["Tirion Fordring"] = "提里奧·弗丁",
Tito = "托托",
["Toravon the Ice Watcher"] = "寒冰看守者图拉旺",
["Trigore the Lasher"] = "鞭笞者特里高雷",
Trollgore = "托尔戈",
["Tsu'zee"] = "苏斯",
["Tuten'kash"] = "图特卡什",
["Twilight Lord Kelris"] = "梦游者克尔里斯",
["Urok Doomhowl"] = "乌洛克",
["Vaelastrasz the Corrupt"] = "堕落的瓦拉斯塔兹",
["Valithria Dreamwalker"] = "踏梦者瓦莉瑟瑞娅",
["Val'kyr Shadowguard"] = "Val'kyr Shadowguard", -- Needs review
["Varian Wrynn"] = "瓦里安·乌瑞恩",
["Varos Cloudstrider"] = "瓦尔洛斯·云击",
Vazruden = "瓦兹德",
["Vazruden the Herald"] = "传令官瓦兹德",
Vectus = "维克图斯",
Vem = "维姆",
Veng = "温格",
["Veras Darkshadow"] = "维尔莱斯·深影",
["Verdan the Everliving"] = "永生者沃尔丹",
Verek = "维雷克",
Vesperon = "维斯匹隆",
Vexallus = "维萨鲁斯",
["Veyzhak the Cannibal"] = "食尸者维萨克",
["Vile'rel"] = "瓦勒雷尔",
Viscidus = "维希度斯",
["Viscous Fallout"] = "粘性辐射尘",
["Void Reaver"] = "空灵机甲",
Volkhan = "沃尔坎",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "战争使者沃姆罗格",
["Warchief Blackhand Piece"] = "黑手酋长",
["Warchief Kargath Bladefist"] = "酋长卡加斯·刃拳",
["Warchief Rend Blackhand"] = "大酋长雷德·黑手",
["Warden Mellichar"] = "监护者梅里卡尔",
["Warder Stilgiss"] = "典狱官斯迪尔基斯",
["Warlord Kalithresh"] = "督军卡利瑟里斯",
["War Master Voone"] = "指挥官沃恩",
["Warmaul Champion"] = "战槌勇士",
["Warp Slicer"] = "迁跃切割者",
["Warp Splinter"] = "迁跃扭木",
["Watchkeeper Gargolmar"] = "巡视者加戈玛",
Weaver = "德拉维沃尔",
["Witch Doctor Zum'rah"] = "巫医祖穆拉恩",
["Wolf Master Nandos"] = "狼王南杜斯",
["Wrath-Scryer Soccothrates"] = "天怒预言者苏克拉底",
Wushoolay = "乌苏雷",
Xevozz = "谢沃兹",
["XT-002 Deconstructor"] = "XT-002拆解者",
["Yogg-Saron"] = "尤格-萨隆",
Ysondre = "伊森德雷",
Zekkis = "泽基斯",
["Zelemar the Wrathful"] = "愤怒者塞雷玛尔",
["Zereketh the Unbound"] = "自由的瑟雷凯斯",
Zerillis = "泽雷利斯",
["Zevrim Thornhoof"] = "瑟雷姆·刺蹄",
Zolo = "祖罗",
["Zul'Farrak Dead Hero"] = "祖尔法拉克阵亡英雄",
["Zul'jin"] = "祖尔金",
["Zul'Lor"] = "祖罗尔",
["Zul'tore"] = "祖尔托",
["Zuramat the Obliterator"] = "湮灭者祖拉玛特",
}
elseif GAME_LOCALE == "zhTW" then
lib:SetCurrentTranslations {
Acidmaw = "酸喉",
Aeonus = "艾奧那斯",
["Aerial Command Unit"] = "空中指揮裝置",
["Agathelos the Raging"] = "暴怒的阿迦賽羅斯",
Ahune = "艾胡恩",
["Akil'zon"] = "阿奇爾森",
["Aku'mai"] = "阿庫麥爾",
["Al'ar"] = "歐爾",
["Algalon the Observer"] = "『觀察者』艾爾加隆",
["Alzzin the Wildshaper"] = "『狂野變形者』奧茲恩",
Amanitar = "毒蕈魔",
["Ambassador Flamelash"] = "弗萊拉斯大使",
["Ambassador Hellmaw"] = "海爾瑪大使",
["Amnennar the Coldbringer"] = "『寒冰使者』亞門納爾",
["Ancient Stone Keeper"] = "古代的石頭看守者",
Anetheron = "安納塞隆",
["Anger'rel"] = "安格雷爾",
Anomalus = "艾諾瑪路斯",
["Antu'sul"] = "安圖蘇爾",
["Anub'arak"] = "阿努巴拉克",
["Anubisath Defender"] = "阿努比薩斯防衛者",
["Anubisath Guardian"] = "阿努比薩斯守衛者",
["Anub'Rekhan"] = "阿努比瑞克漢",
["Anub'shiah"] = "阿努希爾",
Anzu = "安祖",
["Arcane Watchman"] = "秘法警備者",
["Arcanist Doan"] = "秘法師杜安",
Archaedas = "阿札達斯",
["Archavon the Stone Watcher"] = "『石之看守者』亞夏梵",
Archimonde = "阿克蒙德",
["Archivist Galford"] = "檔案管理員加爾福特",
["Archmage Arugal"] = "大法師阿魯高",
["Argent Confessor Paletress"] = "銀白告解者帕爾璀絲",
["Arugal's Voidwalker"] = "阿魯高的虛無行者",
["Assault Bot"] = "突襲機器人",
["Atal'alarion"] = "阿塔拉利恩",
["Attumen the Huntsman"] = "獵人阿圖曼",
Auriaya = "奧芮雅",
Avalanchion = "阿瓦蘭奇奧",
["Avatar of Hakkar"] = "哈卡的化身",
["Ayamiss the Hunter"] = "『狩獵者』阿亞米斯",
Azgalor = "亞茲加洛",
["Azshir the Sleepless"] = "不眠的艾希爾",
Azuregos = "艾索雷葛斯",
["Bael'Gar"] = "貝爾加",
Baelog = "巴爾洛戈",
Balnazzar = "巴納札爾",
["Baltharus the Warborn"] = "『戰爭之子』巴爾薩魯斯",
["Bannok Grimaxe"] = "班諾克·巨斧",
["Baron Aquanis"] = "阿奎尼斯男爵",
["Baron Charr"] = "火焰男爵查爾",
["Baroness Anastari"] = "安娜絲塔麗男爵夫人",
["Baron Geddon"] = "迦頓男爵",
["Baron Kazum"] = "卡蘇姆男爵",
["Baron Rivendare"] = "瑞文戴爾男爵",
["Baron Silverlaine"] = "席瓦萊恩男爵",
["Battleguard Sartura"] = "沙爾圖拉",
["Bazil Thredd"] = "巴基爾·斯瑞德",
Bazzalan = "巴札蘭",
["Black Guard Swordsmith"] = "黑衣守衛鑄劍師",
["Blackheart the Inciter"] = "煽動者黑心",
["Blindeye the Seer"] = "先知盲眼",
["Blind Hunter"] = "盲眼獵手",
["Blood Guard Porung"] = "血衛士波洛克",
["Bloodlord Mandokir"] = "血領主曼多基爾",
["Bloodmage Thalnos"] = "血法師薩爾諾斯",
["Blood Prince Council"] = "血親王議會",
["Blood Princes"] = "血親王",
["Blood-Queen Lana'thel"] = "血腥女王菈娜薩爾",
["Blood Steward of Kirtonos"] = "基爾圖諾斯的衛士",
Boahn = "博艾恩",
["Bomb Bot"] = "炸彈機器人",
["Brain of Yogg-Saron"] = "尤格薩倫的腦部",
["Brainwashed Noble"] = "被洗腦的貴族",
Broggok = "布洛克",
Brokentoe = "斷趾",
Bronjahm = "布朗吉姆",
["Broodlord Lashlayer"] = "龍領主勒西雷爾",
["Bruegal Ironknuckle"] = "布魯戈·艾爾克納寇",
Brutallus = "布魯托魯斯",
["Burning Felguard"] = "燃燒惡魔守衛",
["Buru the Gorger"] = "『暴食者』布魯",
["Cache of the Firelord"] = "火焰之王的寶箱",
["Cannon Master Willey"] = "砲手威利",
["Captain Greenskin"] = "綠皮隊長",
["Captain Kromcrush"] = "克羅卡斯",
["Captain Skarloc"] = "史卡拉克上尉",
["Celebras the Cursed"] = "被詛咒的塞雷布拉斯",
["Charlga Razorflank"] = "卡爾加·刺肋",
["Chess Event"] = "西洋棋事件",
["Chest of The Seven"] = "七賢之箱",
["Chief Ukorz Sandscalp"] = "烏克茲·沙頂",
["Cho'Rush the Observer"] = "『觀察者』克魯什",
Chromaggus = "克洛瑪古斯",
["Chrono Lord Deja"] = "時間領主迪賈",
["Chrono-Lord Epoch"] = "紀元時間領主",
Claw = "裂爪",
["Coilfang Elite"] = "盤牙精英",
["Coilfang Strider"] = "盤牙旅行者",
["Commander Kolurg"] = "指揮官寇勒格",
["Commander Sarannis"] = "指揮官薩瑞尼斯",
["Commander Springvale"] = "指揮官斯普林瓦爾",
["Commander Stoutbeard"] = "指揮官厚鬚",
["Constructor & Controller"] = "『建造者』與『控制者』",
Cookie = "廚師",
["Coren Direbrew"] = "寇仁·恐酒",
["Cosmic Infuser"] = "宇宙灌溉者",
["Crimson Hammersmith"] = "紅衣鑄錘師",
["Crowd Pummeler 9-60"] = "群體打擊者9-60",
["Crystal Fang"] = "水晶之牙",
["C'Thun"] = "克蘇恩",
Cyanigosa = "霞妮苟莎",
["Dalliah the Doomsayer"] = "末日預言者達利亞",
["Dalronn the Controller"] = "『控制者』達隆恩",
["Dark Iron Ambassador"] = "黑鐵大使",
["Darkmaster Gandling"] = "黑暗院長加丁",
["Darkweaver Syth"] = "暗法師希斯",
["Deathbound Ward"] = "亡縛守衛",
["Deathbringer Saurfang"] = "死亡使者薩魯法爾",
["Death Knight Darkreaver"] = "死亡騎士達克雷爾",
["Death Knight Understudy"] = "死亡騎士實習者",
["Deathspeaker High Priest"] = "亡頌者高階祭司",
["Death Speaker Jargba"] = "亡語者賈格巴",
["Deathstalker Visceri"] = "亡靈哨兵威瑟瑞",
["Deathsworn Captain"] = "死亡誓言者隊長",
Devastation = "毀滅",
["Deviate Faerie Dragon"] = "變異精靈龍",
["Devourer of Souls"] = "眾魂吞噬者",
["Dextren Ward"] = "迪克斯特·瓦德",
["Digmaster Shovelphlange"] = "挖掘專家舒爾弗拉格",
["Doctor Theolen Krastinov"] = "瑟爾林·卡斯迪諾夫教授",
["Doom Lord Kazzak"] = "毀滅領主卡札克",
["Doom'rel"] = "杜姆雷爾",
Doomwalker = "厄運行者",
["Dope'rel"] = "多普雷爾",
Dorothee = "桃樂絲",
["Drakkari Colossus"] = "德拉克瑞巨像",
["Drakos the Interrogator"] = "『審問者』德拉高斯",
Dreadscale = "懼鱗",
Dreamscythe = "德姆塞卡爾",
["Dust Covered Chest"] = "滿佈灰塵箱子",
Dustwraith = "灰塵怨靈",
["Eadric the Pure"] = "『純淨者』埃卓克",
["Earthcaller Halmgar"] = "喚地者哈穆加",
Ebonroc = "埃博諾克",
["Eck the Ferocious"] = "『兇猛』埃克",
["Edwin VanCleef"] = "艾德溫·范克里夫",
["Elder Brightleaf"] = "亮葉長者",
["Elder Ironbranch"] = "鐵枝長者",
["Elder Nadox"] = "老那杜斯",
["Elder Stonebark"] = "石木長者",
["Electrocutioner 6000"] = "電刑器6000型",
["Emalon the Storm Watcher"] = "『風暴看守者』艾瑪隆",
Emeriss = "艾莫莉絲",
["Emperor Dagran Thaurissan"] = "達格蘭·索瑞森大帝",
["Emperor Vek'lor"] = "維克洛爾大帝",
["Emperor Vek'nilash"] = "維克尼拉斯大帝",
Entropius = "安卓普斯",
["Eonar's Gift"] = "伊歐娜的贈禮",
["Epoch Hunter"] = "紀元狩獵者",
Erekem = "伊銳坎",
["Eressea Dawnsinger"] = "艾瑞西雅·曦詠",
["Essence of Anger"] = "憤怒精華",
["Essence of Desire"] = "慾望精華",
["Essence of Suffering"] = "受難精華",
Eviscerator = "剜眼者",
["Exarch Maladaar"] = "主教瑪拉達爾",
["Expedition Commander"] = "遠征隊指揮官",
["Eydis Darkbane"] = "艾狄絲·暗寂",
["Eye of C'Thun"] = "克蘇恩之眼",
["Faction Champions"] = "陣營勇士",
["Fallen Champion"] = "亡靈勇士",
Falric = "法勒瑞克",
["Falric and Marwyn"] = "法勒瑞克和麥爾溫",
["Fankriss the Unyielding"] = "不屈的范克里斯",
["Fathom-Lord Karathress"] = "深淵之王卡拉薩瑞斯",
Felmyst = "魔龍謎霧",
["Fenrus the Devourer"] = "『吞噬者』芬魯斯",
["Feral Defender"] = "野性防衛者",
Festergut = "膿腸",
Feugen = "伏晨",
["Fineous Darkvire"] = "弗諾斯·達克維爾",
Firemaw = "費爾默",
["Fjola Lightbane"] = "菲歐拉·光寂",
Flamegor = "弗萊格爾",
["Flame Leviathan"] = "烈焰戰輪",
["Foreman Thistlenettle"] = "工頭希斯耐特",
["Forgemaster Garfrost"] = "鍛造大師加弗羅斯",
["Four Horsemen Chest"] = "四騎士箱子",
["Fras Siabi"] = "弗拉斯·希亞比",
Freya = "芙蕾雅",
["Gahz'ranka"] = "加茲蘭卡",
["Gahz'rilla"] = "加茲瑞拉",
["Gal'darah"] = "蓋爾達拉",
["Galgann Firehammer"] = "加加恩·火錘",
Garr = "加爾",
["Garrosh Hellscream"] = "卡爾洛斯·地獄吼",
Gasher = "加什爾",
["Gatewatcher Gyro-Kill"] = "看守者蓋洛奇歐",
["Gatewatcher Iron-Hand"] = "看守者鐵手",
["Gathios the Shatterer"] = "粉碎者高希歐",
Gehennas = "基赫納斯",
Gelihast = "格里哈斯特",
Gelk = "吉爾克",
["General Angerforge"] = "安格弗將軍",
["General Bjarngrim"] = "畢亞格林將軍",
["General Drakkisath"] = "達基薩斯將軍",
["General Rajaxx"] = "拉賈克斯將軍",
["General Vezax"] = "威札斯將軍",
["General Zarithrian"] = "扎里斯利安將軍",
["Ghamoo-ra"] = "加摩拉",
["Ghaz'an"] = "高薩安",
["Ghok Bashguud"] = "霍克·巴什古德",
Gilnid = "基爾尼格",
["Gizrul the Slavener"] = "『奴役者』基茲盧爾",
["Gloom'rel"] = "格魯雷爾",
Gluth = "古魯斯",
Glutton = "暴食者",
["Golemagg the Incinerator"] = "『焚化者』古雷曼格",
["Golem Lord Argelmach"] = "魔像領主阿格曼奇",
["Goraluk Anvilcrack"] = "古拉魯克",
["Gormok the Impaler"] = "「穿刺者」戈莫克",
["Gorosh the Dervish"] = "『修行者』高羅什",
["Gortok Palehoof"] = "戈托克·白蹄",
["Gothik the Harvester"] = "『收割者』高希",
["Grand Astromancer Capernian"] = "大星術師卡普尼恩",
["Grand Champions"] = "大勇士",
["Grand Magus Telestra"] = "大魔導師特雷斯翠",
["Grandmaster Vorpil"] = "領導者瓦皮歐",
Grandmother = "外婆",
["Grand Warlock Alythess"] = "大術士艾黎瑟絲",
["Grand Warlock Nethekurse"] = "大術士奈德克斯",
["Grand Widow Faerlina"] = "大寡婦費琳娜",
["Grethok the Controller"] = "『控制者』葛瑞托克",
["Gri'lek"] = "格里雷克",
Grimlok = "格瑞姆洛克",
Grizzle = "格里茲爾",
Grobbulus = "葛羅巴斯",
Grubbis = "格魯比斯",
["Gruul the Dragonkiller"] = "弒龍者戈魯爾",
["Guard Fengus"] = "衛兵芬古斯",
["Guardian of Yogg-Saron"] = "尤格薩倫守護者",
["Guard Mol'dar"] = "衛兵摩爾達",
["Guard Slip'kik"] = "衛兵斯里基克",
["Gurtogg Bloodboil"] = "葛塔格·血沸",
Gyth = "蓋斯",
Hadronox = "哈卓諾克斯",
Hakkar = "哈卡",
Halazzi = "哈拉齊",
Halion = "海萊恩",
Halycon = "哈雷肯",
Hamhock = "哈姆霍克",
["Harbinger Skyriss"] = "先驅者史蓋力司",
["Hate'rel"] = "黑特雷爾",
["Hazza'rah"] = "哈札拉爾",
Hazzas = "哈札斯",
["Headless Horseman"] = "無頭騎士",
["Hearthsinger Forresten"] = "弗雷斯特恩",
["Hedrum the Creeper"] = "『爬行者』赫杜姆",
["Heigan the Unclean"] = "『不潔者』海根",
["Hellfire Channeler"] = "地獄火導魔師",
["Henry Stern"] = "亨利·斯特恩",
["Herald Volazj"] = "信使沃菈齊",
Herod = "赫洛德",
["Hex Lord Malacrass"] = "妖術領主瑪拉克雷斯",
["High Astromancer Solarian"] = "高階星術師索拉瑞恩",
["High Botanist Freywinn"] = "大植物學家費瑞衛恩",
["High Inquisitor Fairbanks"] = "高等審判官法爾班克斯",
["High Inquisitor Whitemane"] = "高等審判官懷特邁恩",
["High Interrogator Gerstahn"] = "審訊官格斯塔恩",
["High King Maulgar"] = "大君王莫卡爾",
["Highlord Mograine"] = "大領主莫格萊尼",
["Highlord Omokk"] = "歐莫克大王",
["High Marshal Whirlaxis"] = "大元帥維拉希斯",
["High Nethermancer Zerevor"] = "高等虛空術師札瑞佛",
["High Overlord Saurfang"] = "薩魯法爾霸王",
["High Priestess Arlokk"] = "哈卡萊先知",
["High Priestess Jeklik"] = "高階祭司耶克里克",
["High Priestess Mar'li"] = "哈卡萊安魂者",
["High Priestess of Thaurissan"] = "索瑞森高階女祭司",
["High Priest Thekal"] = "高階祭司塞卡爾",
["High Priest Venoxis"] = "高階祭司溫諾希斯",
["High Warlord Naj'entus"] = "高階督軍納珍塔斯",
Hodir = "霍迪爾",
["Houndmaster Grebmar"] = "馴犬者格雷布瑪爾",
["Houndmaster Loksey"] = "馴犬者洛克希",
Hukku = "胡庫",
Hungarfen = "飢餓之牙",
["Hurley Blackbreath"] = "霍爾雷·黑鬚",
["Hyakiss the Lurker"] = "潛伏者亞奇斯",
["Hydromancer Thespia"] = "海法師希斯比亞",
["Hydromancer Velratha"] = "水占師維蕾薩",
Hydrospawn = "海多斯博恩",
["Hydross the Unstable"] = "不穩定者海卓司",
["Icecrown Gunship Battle"] = "寒冰皇冠空中艦艇戰",
Icehowl = "冰嚎",
["Ice Sphere"] = "寒冰球體",
Ichoron = "伊仇隆",
Ick = "艾克",
["Ignis the Furnace Master"] = "『火爐之主』伊格尼司",
["Illidan Stormrage"] = "伊利丹·怒風",
["Illidari Council"] = "伊利達瑞議會",
["Illyanna Ravenoak"] = "伊琳娜·鴉橡",
["Immol'thar"] = "伊莫塔爾",
["Infinite Corruptor"] = "恆龍墮落者",
["Infinity Blades"] = "無盡之刃",
["Ingvar the Plunderer"] = "『盜掠者』因格瓦",
["Instructor Malicia"] = "講師瑪麗希亞",
["Instructor Razuvious"] = "講師拉祖維斯",
["Interrogator Vishas"] = "審訊員韋沙斯",
Ionar = "埃歐納",
Ironaya = "艾隆納亞",
Ironspine = "鐵脊死靈",
Isalien = "依薩利恩",
Jade = "玉龍",
["Jammal'an the Prophet"] = "『預言者』迦瑪蘭",
["Jan'alai"] = "賈納雷",
["Jandice Barov"] = "詹迪斯·巴羅夫",
["Jedoga Shadowseeker"] = "潔杜佳·尋影者",
["Jed Runewatcher"] = "傑德",
["Jergosh the Invoker"] = "『塑能師』耶戈什",
["Jin'do the Hexxer"] = "『妖術師』金度",
["Jormungar Behemoth"] = "蟄猛巨獸",
Jormungars = "巨蟲",
Julianne = "茱麗葉",
["Junk Bot"] = "垃圾機器人",
["Kael'thas Sunstrider"] = "凱爾薩斯·逐日者",
Kalecgos = "卡雷苟斯",
["Kam Deepfury"] = "卡姆·深怒",
["Kazkaz the Unholy"] = "邪惡的卡薩卡茲",
["Kaz'rogal"] = "卡茲洛加",
["Keli'dan the Breaker"] = "『破壞者』凱利丹",
["Kel'Thuzad"] = "科爾蘇加德",
Keristrasza = "凱瑞史卓莎",
["Kiggler the Crazed"] = "瘋癲者奇克勒",
["Kil'jaeden"] = "基爾加丹",
["Kil'rek"] = "基瑞克",
["King Dred"] = "崔德王",
["King Gordok"] = "戈多克大王",
["King Llane Piece"] = "萊恩王棋子",
["King Ymiron"] = "依米倫王",
["Kirtonos the Herald"] = "傳令官基爾圖諾斯",
["Knot Thimblejack's Cache"] = "諾特·希姆加克的儲物箱",
Kolk = "考爾克",
Kologarn = "柯洛剛恩",
["Koralon the Flame Watcher"] = "『烈焰看守者』寇拉隆",
Kormok = "科爾莫克",
Kresh = "克雷什",
Krick = "克瑞克",
["Krick and Ick"] = "艾克與克瑞克",
["Krik'thir the Gatewatcher"] = "『守門者』齊力克西爾",
["Krosh Firehand"] = "克羅斯·火手",
Krystallus = "克利斯托魯斯",
Kurinnaxx = "庫林納克斯",
["Lady Anacondra"] = "安娜科德拉",
["Lady Blaumeux"] = "布洛莫斯女士",
["Lady Deathwhisper"] = "亡語女士",
["Lady Illucia Barov"] = "伊露希亞·巴羅夫女士",
["Lady Malande"] = "瑪蘭黛女士",
["Lady Sacrolash"] = "莎珂蕾希女士",
["Lady Sarevess"] = "薩利維絲女士",
["Lady Vashj"] = "瓦許女士",
Laj = "拉杰",
Landslide = "蘭斯利德",
Lavanthor = "拉方索",
["Left Arm"] = "左臂",
["Leotheras the Blind"] = "『盲目者』李奧薩拉斯",
Lethon = "雷索",
Lethtendris = "蕾瑟塔蒂絲",
["Leviathan Mk II"] = "戰輪MK II",
["Ley-Guardian Eregos"] = "地脈守護者伊瑞茍斯",
["Lieutenant Drake"] = "中尉崔克",
["Lieutenant General Andorov"] = "安多洛夫中將",
Loatheb = "憎恨者",
Loken = "洛肯",
["Lord Alexei Barov"] = "阿萊克斯·巴羅夫領主",
["Lord Cobrahn"] = "考布萊恩領主",
["Lord Hel'nurath"] = "赫爾努拉斯領主",
["Lord Incendius"] = "伊森迪奧斯領主",
["Lord Jaraxxus"] = "賈拉克瑟斯領主",
["Lord Kazzak"] = "毀滅領主卡札克",
["Lord Kri"] = "克里領主",
["Lord Marrowgar"] = "瑪洛嘉領主",
["Lord Pythas"] = "皮薩斯領主",
["Lord Roccor"] = "洛考爾領主",
["Lord Sanguinar"] = "桑古納爾領主",
["Lord Serpentis"] = "瑟芬迪斯領主",
["Lord Skwol"] = "斯古恩領主",
["Lord Valthalak"] = "瓦薩拉克領主",
["Lord Victor Nefarius"] = "維克多·奈法利斯領主",
["Lord Vyletongue"] = "維利塔恩領主",
["Lorekeeper Polkelt"] = "博學者普克爾特",
Loro = "洛若爾",
Lucifron = "魯西弗隆",
["Mad Magglish"] = "瘋狂的馬格利什",
Maexxna = "梅克絲娜",
["Mage-Lord Urom"] = "法師領主厄隆",
["Magister Kalendris"] = "卡雷迪斯鎮長",
["Magistrate Barthilas"] = "巴瑟拉斯鎮長",
Magmadar = "瑪格曼達",
Magmus = "瑪格姆斯",
Magra = "瑪格拉",
Magtheridon = "瑪瑟里頓",
["Maiden of Grief"] = "悲嘆少女",
["Maiden of Virtue"] = "貞潔聖女",
["Majordomo Executus"] = "管理者埃克索圖斯",
Malacrass = "瑪拉克雷斯",
["Maleki the Pallid"] = "蒼白的瑪勒基",
["Mal'Ganis"] = "瑪爾加尼斯",
Malygos = "瑪里苟斯",
Maraudos = "瑪拉多斯",
["Marduk Blackpool"] = "馬杜克·布萊克波爾",
["Marisa du'Paige"] = "瑪里莎·杜派格",
Marwyn = "麥爾溫",
["Master Engineer Telonicus"] = "工程大師泰隆尼卡斯",
["Maur Grimtotem"] = "瑪爾·恐怖圖騰",
Meathook = "肉鉤",
["Mechano-Lord Capacitus"] = "機械王卡帕希特斯",
Medivh = "麥迪文",
["Mekgineer Steamrigger"] = "米克吉勒·蒸氣操控者",
["Mekgineer Thermaplugg"] = "麥克尼爾·瑟瑪普拉格",
["Mennu the Betrayer"] = "背叛者曼紐",
["Meshlok the Harvester"] = "『收割者』麥什洛克",
Midnight = "午夜",
Mijan = "米杉",
Mimiron = "彌米倫",
["Miner Johnson"] = "礦工約翰森",
["Mistress of Pain"] = "痛苦仕女",
Moam = "莫阿姆",
Mogor = "莫古",
["Mokra the Skullcrusher"] = "『碎顱者』莫克拉",
Moorabi = "慕拉比",
Moragg = "摩拉革",
["Mordresh Fire Eye"] = "火眼莫德雷斯",
["Mor Grayhoof"] = "莫爾·灰蹄",
Moroes = "摩洛",
["Morogrim Tidewalker"] = "莫洛葛利姆·潮行者",
Morphaz = "摩弗拉斯",
["Mother Shahraz"] = "薩拉茲女士",
["Mother Smolderweb"] = "煙網蛛后",
["Mr. Smite"] = "重拳先生",
["Muradin Bronzebeard"] = "穆拉丁·銅鬚",
["Murkblood Twin"] = "黑暗之血雙子",
["Murkblood Twins"] = "黑暗之血雙子",
Murmur = "莫爾墨",
["Murta Grimgut"] = "莫爾塔",
["M'uru"] = "莫魯",
Mushgog = "姆斯高格",
["Mutanus the Devourer"] = "『吞噬者』穆坦努斯",
Nalorakk = "納羅拉克",
Nazan = "納桑",
Nefarian = "奈法利安",
["Nekrum Gutchewer"] = "耐克魯姆",
["Nerub'enkan"] = "奈幽布恩坎",
["Nethermancer Sepethrea"] = "虛空術師賽菲瑞雅",
Netherspite = "尼德斯",
["Netherstrand Longbow"] = "虛空之絃長弓",
["Nexus-Prince Shaffar"] = "奈薩斯王子薩法爾",
Nightbane = "夜禍",
["Noth the Plaguebringer"] = "『瘟疫使者』諾斯",
["Novos the Summoner"] = "『召喚者』諾沃司",
Noxxion = "諾克賽恩",
["Obsidian Sentinel"] = "黑曜石哨兵",
["Odo the Blindwatcher"] = "『盲眼守衛』奧杜",
["Ogom the Wretched"] = "可悲的奧戈姆",
["Ok'thor the Breaker"] = "『破壞者』奧科索爾",
["Old Serra'kis"] = "瑟拉吉斯",
["Olm the Summoner"] = "召喚者歐莫",
["Omor the Unscarred"] = "無疤者歐瑪爾",
Onyxia = "奧妮克希亞",
["Orgrim's Hammer"] = "奧格林之錘",
["Ormorok the Tree-Shaper"] = "『樹木造形者』歐爾莫洛克",
["Oro Eyegouge"] = "歐魯·鑿眼",
["Ossirian the Unscarred"] = "『無疤者』奧斯里安",
Ouro = "奧羅",
["Overlord Ramtusk"] = "拉姆塔斯主宰",
["Overlord Wyrmthalak"] = "維姆薩拉克主宰",
["Overmaster Pyron"] = "征服者派隆",
["Overseer Tidewrath"] = "監督者泰洛斯",
Pandemonius = "班提蒙尼厄斯",
["Panzor the Invincible"] = "無敵的潘佐爾",
Patchwerk = "縫補者",
["Pathaleon the Calculator"] = "操縱者帕薩里歐",
Phalanx = "法拉克斯",
["Phaseshift Bulwark"] = "相位壁壘",
Pimgib = "匹姆吉布",
["Plaguemaw the Rotting"] = "腐爛的普雷莫爾",
["Plugger Spazzring"] = "普拉格",
["Postmaster Malown"] = "郵差瑪羅恩",
["Priestess Delrissa"] = "女牧師戴利莎",
["Prince Keleseth"] = "凱雷希斯親王",
["Prince Malchezaar"] = "莫克札王子",
["Prince Skaldrenox"] = "斯卡德諾克斯王子",
["Princess Huhuran"] = "哈霍蘭公主",
["Princess Moira Bronzebeard"] = "茉艾拉·銅鬚公主",
["Princess Tempestria"] = "泰比斯蒂亞公主",
["Princess Theradras"] = "瑟萊德絲公主",
["Princess Yauj"] = "亞爾基公主",
["Prince Taldaram"] = "泰爾達朗親王",
["Prince Tenris Mirkblood"] = "坦瑞斯·暗血王子",
["Prince Tortheldrin"] = "托塞德林王子",
["Prince Valanar"] = "瓦拉納爾親王",
["Professor Putricide"] = "普崔希德教授",
["Pure Spawn of Hydross"] = "純正的海卓司子嗣",
Pusillin = "普希林",
["Pyroguard Emberseer"] = "烈焰衛士艾博希爾",
["Pyromancer Loregrain"] = "控火師羅格雷恩",
Quagmirran = "奎克米瑞",
["Quartermaster Zigris"] = "軍需官茲格雷斯",
["Rage Winterchill"] = "瑞齊·凜冬",
Ragglesnout = "拉戈斯諾特",
["Raging Spirit"] = "狂怒的鬼魂",
Ragnaros = "拉格納羅斯",
["Ramstein the Gorger"] = "『暴食者』拉姆斯登",
["Ras Frostwhisper"] = "萊斯·霜語",
Rattlegore = "血骨傀儡",
["Razorclaw the Butcher"] = "屠夫拉佐克勞",
["Razorgore the Untamed"] = "狂野的拉佐格爾",
Razorlash = "銳刺鞭笞者",
Razorscale = "銳鱗",
["Reliquary of Souls"] = "靈魂之匣",
Renataki = "雷納塔基",
["Restless Skeleton"] = "永不安息的骷髏",
Rethilgore = "雷希戈爾",
Revelosh = "魯維羅什",
["Rhahk'Zor"] = "拉克佐",
["Ribbly Screwspigot"] = "雷布里·斯庫比格特",
["Right Arm"] = "右臂",
Roar = "獅子",
["Rokad the Ravager"] = "劫毀者拉卡",
["Rokdar the Sundered Lord"] = "『碎裂領主』洛克達",
["Rokmar the Crackler"] = "爆裂者洛克瑪",
Romulo = "羅慕歐",
["Romulo & Julianne"] = "羅慕歐與茱麗葉",
Rotface = "腐臉",
Rotgrip = "洛特格里普",
["Runemaster Molgeim"] = "符文大師墨吉姆",
["Runok Wildmane"] = "魯諾克·蠻鬃",
Ruuzlu = "盧茲魯",
["Salramm the Fleshcrafter"] = "『血肉工匠』塞歐朗姆",
["Sanctum Sentry"] = "聖所哨兵",
["Sandarr Dunereaver"] = "杉達爾·沙掠者",
["Sandfury Executioner"] = "沙怒劊子手",
Sapphiron = "薩菲隆",
Sara = "薩拉",
["Saronite Animus"] = "薩倫聚惡體",
Sartharion = "撒爾薩里安",
["Sathrovarr the Corruptor"] = "『墮落者』塞斯諾瓦",
["Saviana Ragefire"] = "薩薇安娜‧怒焰",
["Scarlet Commander Mograine"] = "血色十字軍指揮官莫格萊尼",
["Scourgelord Tyrannus"] = "天譴領主提朗紐斯",
["Seeth'rel"] = "西斯雷爾",
["Selin Fireheart"] = "賽林·炎心",
["Sergeant Bly"] = "布萊中士",
["Shade of Akama"] = "阿卡瑪的黑暗面",
["Shade of Aran"] = "埃蘭之影",
["Shade of Eranikus"] = "伊蘭尼庫斯的陰影",
["Shadikith the Glider"] = "滑翔者薛迪依斯",
["Shadow Hunter Vosh'gajin"] = "暗影獵手沃許加斯",
["Shadow of Leotheras"] = "李奧薩拉斯的陰影",
["Shadowpriest Sezz'ziz"] = "暗影祭司塞瑟斯",
Shadron = "夏德朗",
Shazzrah = "沙斯拉爾",
["Shirrak the Dead Watcher"] = "死亡看守者辛瑞克",
Sindragosa = "辛德拉苟莎",
["Sir Zeliek"] = "札里克爵士",
["Sjonnir The Ironshaper"] = "『塑鐵者』斯雍尼爾",
["Skadi the Ruthless"] = "無情的斯卡迪",
["Skarr the Unbreakable"] = "無敵的斯卡爾",
["Skarvald the Constructor"] = "『建造者』史卡沃",
["Skra'gath"] = "史卡拉克斯",
Skul = "斯庫爾",
Skum = "斯卡姆",
["Slad'ran"] = "史拉德銳",
Sneed = "斯尼德",
["Sneed's Shredder"] = "斯尼德的伐木機",
["Solakar Flamewreath"] = "索拉卡·火冠",
["Solarium Agent"] = "日光之室密探",
["Solarium Priest"] = "日光之室牧師",
["Spirestone Battle Lord"] = "尖石戰鬥統帥",
["Spirestone Butcher"] = "尖石屠夫",
["Spirestone Lord Magus"] = "尖石首席魔導師",
["Staff of Disintegration"] = "瓦解之杖",
Stalagg = "斯塔拉格",
Steelbreaker = "破鋼者",
["Stomper Kreeg"] = "踐踏者克雷格",
Stonespine = "石脊",
["Stormcaller Brundir"] = "風暴召喚者布倫迪爾",
Strawman = "稻草人",
["Sulfuron Harbinger"] = "薩弗隆先驅者",
Supremus = "瑟普莫斯",
["Svala Sorrowgrave"] = "絲瓦拉·悲傷亡墓",
["Swamplord Musel'ek"] = "沼澤之王莫斯萊克",
Taerar = "泰拉爾",
["Tainted Spawn of Hydross"] = "腐化的海卓司之子",
["Talon King Ikiss"] = "鷹王伊奇斯",
["Taragaman the Hungerer"] = "『飢餓者』塔拉加曼",
["Targorr the Dread"] = "可怕的塔高爾",
Tavarok = "塔瓦洛克",
Techbot = "尖端機器人",
Temporus = "坦普拉斯",
["Tendris Warpwood"] = "特迪斯·扭木",
Tenebron = "坦納伯朗",
["Terestian Illhoof"] = "泰瑞斯提安·疫蹄",
["Teron Gorefiend"] = "泰朗·血魔",
Thaddius = "泰迪斯",
["Thaladred the Darkener"] = "扭曲預言家薩拉瑞德",
["Thane Korth'azz"] = "寇斯艾茲族長",
["The Beast"] = "比斯巨獸",
["The Beasts of Northrend"] = "北裂境巨獸",
["The Big Bad Wolf"] = "大野狼",
["The Black Knight"] = "黑騎士",
["The Black Stalker"] = "黑色捕獵者",
["The Blue Brothers"] = "憂鬱兄弟黨",
["The Bug Family"] = "蟲子家族",
["The Crone"] = "老巫婆",
["The Curator"] = "館長",
["The Eredar Twins"] = "埃雷達爾雙子",
["The Four Horsemen"] = "四騎士",
["The Illidari Council"] = "伊利達瑞議事",
["The Iron Council"] = "鐵之集會",
["Theka the Martyr"] = "『殉教者』塞卡",
["The Lich King"] = "巫妖王",
["The Lurker Below"] = "海底潛伏者",
["The Maker"] = "創造者",
["The Prophet Skeram"] = "預言者斯克拉姆",
["The Prophet Tharon'ja"] = "預言者薩隆杰",
["The Ravenian"] = "拉文尼亞",
["The Razza"] = "拉札",
["The Seven Dwarves"] = "七賢人",
["The Skybreaker"] = "破天者號",
["The Tribunal of Ages"] = "歲月議庭",
["The Twin Emperors"] = "雙子皇帝",
["The Twin Val'kyr"] = "華爾琪雙子",
["The Unforgiven"] = "不可寬恕者",
["The Windreaver"] = "烈風搶奪者",
Thorim = "索林姆",
["Thorngrin the Tender"] = "『看管者』索古林",
["Tidewalker Lurker"] = "潮行者潛伏者",
["Timmy the Cruel"] = "悲慘的提米",
Tinhead = "機器人",
["Tinkerer Gizlock"] = "技工吉茲洛克",
["Tirion Fordring"] = "提里奧·弗丁",
Tito = "多多",
["Toravon the Ice Watcher"] = "『寒冰看守者』拓拉梵",
["Trigore the Lasher"] = "『鞭笞者』特里高雷",
Trollgore = "血角食人妖",
["Tsu'zee"] = "蘇斯",
["Tuten'kash"] = "圖特卡什",
["Twilight Lord Kelris"] = "暮光領主克爾里斯",
["Urok Doomhowl"] = "烏洛克",
["Vaelastrasz the Corrupt"] = "墮落的瓦拉斯塔茲",
["Valithria Dreamwalker"] = "瓦莉絲瑞雅·夢行者",
["Val'kyr Shadowguard"] = "華爾琪影衛",
["Varian Wrynn"] = "瓦里安·烏瑞恩",
["Varos Cloudstrider"] = "瓦羅斯·雲行者",
Vazruden = "維斯路登",
["Vazruden the Herald"] = "『信使』維斯路登",
Vectus = "維克圖斯",
Vem = "維姆",
Veng = "溫格",
["Veras Darkshadow"] = "維拉斯·深影",
["Verdan the Everliving"] = "永生的沃爾丹",
Verek = "維雷克",
Vesperon = "維斯佩朗",
Vexallus = "維克索魯斯",
["Veyzhak the Cannibal"] = "『食人者』維薩克",
["Vile'rel"] = "瓦勒雷爾",
Viscidus = "維希度斯",
["Viscous Fallout"] = "粘性輻射塵",
["Void Reaver"] = "虛無搶奪者",
Volkhan = "渥克瀚",
["VX-001"] = "VX-001",
["Warbringer O'mrogg"] = "戰爭製造者·歐姆拉格",
["Warchief Blackhand Piece"] = "黑手大酋長棋子",
["Warchief Kargath Bladefist"] = "大酋長卡加斯·刃拳",
["Warchief Rend Blackhand"] = "大酋長雷德·黑手",
["Warden Mellichar"] = "看守者米利恰爾",
["Warder Stilgiss"] = "守衛斯迪爾基斯",
["Warlord Kalithresh"] = "督軍卡利斯瑞",
["War Master Voone"] = "指揮官沃恩",
["Warmaul Champion"] = "戰槌勇士",
["Warp Slicer"] = "扭曲分割者",
["Warp Splinter"] = "扭曲分裂者",
["Watchkeeper Gargolmar"] = "看護者卡爾古瑪",
Weaver = "德拉維沃爾",
["Witch Doctor Zum'rah"] = "巫醫·祖穆拉恩",
["Wolf Master Nandos"] = "狼王南杜斯",
["Wrath-Scryer Soccothrates"] = "怒鐮者索寇斯瑞特",
Wushoolay = "烏蘇雷",
Xevozz = "基沃滋",
["XT-002 Deconstructor"] = "XT-002拆解者",
["Yogg-Saron"] = "尤格薩倫",
Ysondre = "伊索德雷",
Zekkis = "澤基斯",
["Zelemar the Wrathful"] = "憤怒的賽勒瑪爾",
["Zereketh the Unbound"] = "無約束的希瑞奇斯",
Zerillis = "澤雷利斯",
["Zevrim Thornhoof"] = "瑟雷姆·刺蹄",
Zolo = "祖羅",
["Zul'Farrak Dead Hero"] = "祖爾法拉克陣亡英雄",
["Zul'jin"] = "祖爾金",
["Zul'Lor"] = "祖羅爾",
["Zul'tore"] = "祖爾拓",
["Zuramat the Obliterator"] = "『消滅者』舒拉邁特",
}
 
else
error(("%s: Locale %q not supported"):format(MAJOR_VERSION, GAME_LOCALE))
end
trunk/Libs/LibBabble-Boss-3.0/LibBabble-Boss-3.0.toc New file
0,0 → 1,21
## Interface: 30300
## LoadOnDemand: 1
## Title: Lib: Babble-Boss-3.0
## Notes: A library to help with localization of bosses.
## Notes-zhCN: 为本地化服务的支持库[首领名称]
## Notes-zhTW: 為本地化服務的函式庫[首領名稱]
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll.
## Notes-frFR: Une bibliothèque d'aide à la localisation.
## Notes-esES: Una biblioteca para ayudar con las localizaciones.
## Author: ckknight
## X-eMail: ckknight@gmail.com
## X-Category: Library
## X-License: MIT
## X-Curse-Packaged-Version: r287
## X-Curse-Project-Name: LibBabble-Boss-3.0
## X-Curse-Project-ID: libbabble-boss-3-0
## X-Curse-Repository-ID: wow/libbabble-boss-3-0/mainline
 
LibStub\LibStub.lua
lib.xml
 
trunk/Libs/LibBabble-Boss-3.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibBabble-Boss-3.0/lib.xml New file
0,0 → 1,5
<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="LibBabble-3.0.lua" />
<Script file="LibBabble-Boss-3.0.lua" />
</Ui>
trunk/Libs/LibTalentQuery-1.0/lib.xml New file
0,0 → 1,3
<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="LibTalentQuery-1.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/LibTalentQuery-1.0/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,239
--[[ $Id: CallbackHandler-1.0.lua 60697 2008-02-09 16:51:20Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 3
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}
 
local type = type
local pcall = pcall
local pairs = pairs
local assert = assert
local concat = table.concat
local loadstring = loadstring
local next = next
local select = select
local type = type
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local next, xpcall, eh = ...
 
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 = ...
repeat
xpcall(call, eh)
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 = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(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, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
 
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[select('#', ...) + 1](events[eventname], eventname, ...)
 
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 select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId"
if type(self)~="table" and type(self)~="string" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
end
 
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(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 select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
 
 
for i=1,select("#",...) do
local self = select(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.
 
trunk/Libs/LibTalentQuery-1.0/LibTalentQuery-1.0.lua New file
0,0 → 1,356
--[[
Name: LibTalentQuery-1.0
Revision: $Rev: 80 $
Author: Rich Martel (richmartel@gmail.com)
Documentation: http://wowace.com/wiki/LibTalentQuery-1.0
SVN: svn://svn.wowace.com/wow/libtalentquery-1-0/mainline/trunk
Description: Library to help with querying unit talents
Dependancies: LibStub, CallbackHandler-1.0
License: LGPL v2.1
 
Example Usage:
local TalentQuery = LibStub:GetLibrary("LibTalentQuery-1.0")
TalentQuery.RegisterCallback(self, "TalentQuery_Ready")
 
local raidTalents = {}
...
TalentQuery:Query(unit)
...
function MyAddon:TalentQuery_Ready(e, name, realm, unitid)
local isnotplayer = not UnitIsUnit(unitid, "player")
local spec = {}
for tab = 1, GetNumTalentTabs(isnotplayer) do
local treename, _, pointsspent = GetTalentTabInfo(tab, isnotplayer)
tinsert(spec, pointsspent)
end
raidTalents[UnitGUID(unitid)] = spec
end
]]
 
local MAJOR, MINOR = "LibTalentQuery-1.0", 90000 + tonumber(("$Rev: 80 $"):match("(%d+)"))
 
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
 
local INSPECTDELAY = 1
local INSPECTTIMEOUT = 5
if not lib.events then
lib.events = LibStub("CallbackHandler-1.0"):New(lib)
end
 
local validateTrees
local enteredWorld = IsLoggedIn()
local frame = lib.frame
if not frame then
frame = CreateFrame("Frame", MAJOR .. "_Frame")
lib.frame = frame
end
frame:UnregisterAllEvents()
frame:RegisterEvent("INSPECT_TALENT_READY")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("PLAYER_LEAVING_WORLD")
frame:RegisterEvent("PLAYER_LOGIN")
frame:SetScript("OnEvent", function(this, event, ...)
return lib[event](lib, ...)
end)
 
do
local lastUpdateTime = 0
frame:SetScript("OnUpdate", function(this, elapsed)
lastUpdateTime = lastUpdateTime + elapsed
if lastUpdateTime > INSPECTDELAY then
lib:CheckInspectQueue()
lastUpdateTime = 0
end
end)
frame:Hide()
end
 
local inspectQueue = lib.inspectQueue or {}
lib.inspectQueue = inspectQueue
local garbageQueue = lib.garbageQueue or {} -- Added a second queue to things. Inspects that initially fail are now
lib.garbageQueue = garbageQueue -- thrown into second queue will will be processed once main queue is empty
 
if next(inspectQueue) then
frame:Show()
end
 
local UnitIsPlayer = _G.UnitIsPlayer
local UnitName = _G.UnitName
local UnitExists = _G.UnitExists
local UnitGUID = _G.UnitGUID
local GetNumRaidMembers = _G.GetNumRaidMembers
local GetNumPartyMembers = _G.GetNumPartyMembers
local UnitIsVisible = _G.UnitIsVisible
local UnitIsConnected = _G.UnitIsConnected
local UnitCanAttack = _G.UnitCanAttack
local CanInspect = _G.CanInspect
 
local function UnitFullName(unit)
local name, realm = UnitName(unit)
local namerealm = realm and realm ~= "" and name .. "-" .. realm or name
return namerealm
end
 
-- GuidToUnitID
local function GuidToUnitID(guid)
local prefix, min, max = "raid", 1, GetNumRaidMembers()
if max == 0 then
prefix, min, max = "party", 0, GetNumPartyMembers()
end
 
-- Prioritise getting direct units first because other players targets
-- can change between notify and event which can bugger things up
for i = min, max do
local unit = i == 0 and "player" or prefix .. i
if (UnitGUID(unit) == guid) then
return unit
end
end
 
-- This properly detects target units
if (UnitGUID("target") == guid) then
return "target"
elseif (UnitGUID("focus") == guid) then
return "focus"
end
 
for i = min, max + 3 do
local unit
if i == 0 then
unit = "player"
elseif i == max + 1 then
unit = "target"
elseif i == max + 2 then
unit = "focus"
elseif i == max + 3 then
unit = "mouseover"
else
unit = prefix .. i
end
if (UnitGUID(unit .. "target") == guid) then
return unit .. "target"
elseif (i <= max and UnitGUID(unit.."pettarget") == guid) then
return unit .. "pettarget"
end
end
return nil
end
 
-- Query
function lib:Query(unit)
if (UnitLevel(unit) < 10 or UnitName(unit) == UNKNOWN) then
return
end
 
self.lastQueuedInspectReceived = nil
if UnitIsUnit(unit, "player") then
self.events:Fire("TalentQuery_Ready", UnitName("player"), nil, "player")
else
if type(unit) ~= "string" then
error(("Bad argument #2 to 'Query'. Expected %q, received %q (%s)"):format("string", type(unit), tostring(unit)), 2)
elseif not UnitExists(unit) or not UnitIsPlayer(unit) then
error(("Bad argument #2 to 'Query'. %q is not a valid player unit"):format(tostring(unit)), 2)
elseif not UnitExists(unit) or not UnitIsPlayer(unit) then
error(("Bad argument #2 to 'Query'. %q does not require a server query before reading talents"):format("player"), 2)
else
local name = UnitFullName(unit)
if (not inspectQueue[name]) then
inspectQueue[name] = UnitGUID(unit)
garbageQueue[name] = nil
end
frame:Show()
end
end
end
 
-- CheckInspectQueue
-- Originally, it would wait until no pending NotifyInspect() were expected, and then do it's own.
-- It was also only bother looking at ready results if it had triggered the Notify for that occasion.
-- For the changes I've done, no assumption is made about which mod is performing NotifyInspect().
-- We note the name, unit, time of any inspects done whether from this queue or any other source,
-- we remove from our queue any we were expecting, and use a seperate event in case extra talent
-- info is any time wanted (opportunistic refreshes etc) - Zeksie, 20th May 2009
function lib:CheckInspectQueue()
if (_G.InspectFrame and _G.InspectFrame:IsShown()) then
return
end
 
if (not self.lastInspectTime or self.lastInspectTime < GetTime() - INSPECTTIMEOUT) then
self.lastInspectPending = 0
end
 
if (self.lastInspectPending > 0 or not enteredWorld) then
return
end
 
if (self.lastQueuedInspectReceived and self.lastQueuedInspectReceived < GetTime() - 60) then
-- No queued results received for a minute, so purge the queue as invalid and move on with our lives
self.lastQueuedInspectReceived = nil
inspectQueue = {}
lib.inspectQueue = inspectQueue
garbageQueue = {}
lib.garbageQueue = garbageQueue
frame:Hide()
return
end
 
for name,guid in pairs(inspectQueue) do
local unit = GuidToUnitID(guid)
if (not unit) then
inspectQueue[name] = nil
else
if (UnitIsVisible(unit) and UnitIsConnected(unit) and not UnitCanAttack("player", unit) and not UnitCanAttack(unit, "player") and CanInspect(unit) and UnitClass(unit)) then
NotifyInspect(unit)
break
else
garbageQueue[name] = guid -- Not available, throw into secondary queue and continue
inspectQueue[name] = nil
end
end
end
 
if (not next(inspectQueue)) then
if (next(garbageQueue)) then
-- Retry initially failed inspects
lib.inspectQueue = garbageQueue
inspectQueue = lib.inspectQueue
lib.garbageQueue = {}
garbageQueue = lib.garbageQueue
else
frame:Hide()
end
end
end
 
-- NotifyInspect
if not lib.NotifyInspect then -- don't hook twice
hooksecurefunc("NotifyInspect", function(...) return lib:NotifyInspect(...) end)
end
function lib:NotifyInspect(unit)
if (not (UnitExists(unit) and UnitIsVisible(unit) and UnitIsConnected(unit) and CheckInteractDistance(unit, 4))) then
return
end
self.lastInspectUnit = unit
self.lastInspectGUID = UnitGUID(unit)
self.lastInspectTime = GetTime()
self.lastInspectName = UnitFullName(unit)
self.lastInspectPending = self.lastInspectPending + 1
local isnotplayer = not UnitIsUnit("player", unit)
self.lastInspectTree = GetTalentTabInfo(1, isnotplayer) -- Talent tree names are available immediately
end
 
-- Reset
function lib:Reset()
self.lastInspectPending = 0
self.lastInspectUnit = nil
self.lastInspectTime = nil
self.lastInspectName = nil
self.lastInspectGUID = nil
self.lastInspectTree = nil
end
 
-- INSPECT_TALENT_READY
function lib:INSPECT_TALENT_READY()
self.lastInspectPending = self.lastInspectPending - 1
 
-- Results are valid only when we have received as many events as we have posted notifies
if (self.lastInspectName and self.lastInspectPending == 0) then
-- Check unit ID is still pointing to same actual unit
if (UnitGUID(self.lastInspectUnit) == self.lastInspectGUID) then
local guid = inspectQueue[self.lastInspectName]
inspectQueue[self.lastInspectName] = nil
 
local name, realm = strsplit("-", self.lastInspectName)
 
self.lastQueuedInspectReceived = GetTime()
 
-- Notify of expected talent results
local isnotplayer = not UnitIsUnit("player", self.lastInspectName)
local group = GetActiveTalentGroup(isnotplayer)
local tree1, _, spent1 = GetTalentTabInfo(1, isnotplayer, nil, group)
if (tree1 ~= self.lastInspectTree) then
-- Expected talent tree name to be the same as it was when we triggered the NotifyInspect()
garbageQueue[self.lastInspectName] = self.lastInspectGUID
self:Reset()
self:CheckInspectQueue()
return
 
elseif (validateTrees) then
-- Double checking here. Check the tree name matches what we expect for this class
local _, class = UnitClass(self.lastInspectUnit)
if (tree1 ~= validateTrees[class]) then
garbageQueue[self.lastInspectName] = self.lastInspectGUID
self:Reset()
self:CheckInspectQueue()
return
end
end
 
local tree2, _, spent2 = GetTalentTabInfo(2, isnotplayer, nil, group)
local tree3, _, spent3 = GetTalentTabInfo(3, isnotplayer, nil, group)
if ((spent1 or 0) + (spent2 or 0) + (spent3 or 0) > 0) then
if (guid) then
-- It was in our queue
self.events:Fire("TalentQuery_Ready", name, realm, self.lastInspectUnit)
else
-- Also notify of non-expected ones, as it's entirely useful to refresh them if they're there
-- It is up to the receiving applicating to determine whether they want to receive the information
self.events:Fire("TalentQuery_Ready_Outsider", name, realm, self.lastInspectUnit)
end
else
-- Tree came back with zero points spent, probably an issue while logging in
garbageQueue[self.lastInspectName] = guid
end
end
 
self:Reset()
self:CheckInspectQueue()
end
end
 
function lib:PLAYER_ENTERING_WORLD()
-- We can't inspect other's talents until now
-- We just get 0/0/0 back even though we get an INSPECT_TALENT_READY event
enteredWorld = true
end
 
function lib:PLAYER_LEAVING_WORLD()
enteredWorld = nil
end
 
function lib:PLAYER_LOGIN()
validateTrees = {
DRUID = "Balance",
PRIEST = "Discipline",
ROGUE = "Assassination",
HUNTER = "Beast Mastery",
WARLOCK = "Affliction",
WARRIOR = "Arms",
DEATHKNIGHT = "Blood",
PALADIN = "Holy",
SHAMAN = "Elemental",
MAGE = "Arcane",
}
 
if (GetLocale() ~= "enUS" and GetLocale() ~= "enGB") then
-- LibBabble-TalentTree-3.0 only loaded if present and not enUS
local LBT = LibStub("LibBabble-TalentTree-3.0", true)
if (not LBT) then
LoadAddOn("LibBabble-TalentTree-3.0")
LBT = LibStub("LibBabble-TalentTree-3.0", true)
end
LBT = LBT and LBT:GetLookupTable()
if (LBT) then
for class,tree1 in pairs(validateTrees) do
validateTrees[class] = LBT[tree1]
end
else
validateTrees = nil
end
end
 
self.PLAYER_LOGIN = nil
end
 
lib:Reset()
trunk/Libs/LibTalentQuery-1.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibTalentQuery-1.0/LibStub/LibStub.toc New file
0,0 → 1,13
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: r82
## X-Curse-Project-Name: LibTalentQuery-1.0
## X-Curse-Project-ID: libtalentquery-1-0
## X-Curse-Repository-ID: wow/libtalentquery-1-0/mainline
 
LibStub.lua
trunk/Libs/LibTalentQuery-1.0/LibTalentQuery-1.0.toc New file
0,0 → 1,18
## Interface: 30300
## LoadOnDemand: 1
## Title: Lib: TalentQuery 1.0
## Notes: Library to help with querying unit talents.
## Author: Peragor
## Version: $Rev: 82 $
## X-Category: Library
## X-ReleaseDate: $Date: 2009-12-09 11:08:46 +0000 (Wed, 09 Dec 2009) $
## X-Website: http://wowace.com/wiki/LibTalentQuery-1.0
## X-License: LGPL v2.1
## X-Curse-Packaged-Version: r82
## X-Curse-Project-Name: LibTalentQuery-1.0
## X-Curse-Project-ID: libtalentquery-1-0
## X-Curse-Repository-ID: wow/libtalentquery-1-0/mainline
 
LibStub\LibStub.lua
CallbackHandler-1.0\CallbackHandler-1.0.lua
lib.xml
trunk/Libs/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibStub/LibStub.toc New file
0,0 → 1,13
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
 
LibStub.lua
trunk/Libs/LibBabble-Zone-3.0/LibBabble-Zone-3.0.toc New file
0,0 → 1,18
## Interface: 30300
## LoadOnDemand: 1
## Title: Lib: Babble-Zone-3.0
## Notes: A library to help with localization of Zones.
## Notes-deDE: BabbleLib ist eine Bibliothek, die bei der Lokalisierung helfen soll.
## Notes-frFR: Une bibliothèque d'aide à la localisation.
## Notes-esES: Una biblioteca para ayudar con las localizaciones.
## Author: ckknight
## X-eMail: ckknight@gmail.com
## X-Category: Library
## X-License: MIT
## X-Curse-Packaged-Version: r268
## X-Curse-Project-Name: LibBabble-Zone-3.0
## X-Curse-Project-ID: libbabble-zone-3-0
## X-Curse-Repository-ID: wow/libbabble-zone-3-0/mainline
 
LibStub\LibStub.lua
lib.xml
trunk/Libs/LibBabble-Zone-3.0/LibBabble-3.0.lua New file
0,0 → 1,292
-- LibBabble-3.0 is hereby placed in the Public Domain
-- Credits: ckknight
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2
 
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR)
if not LibBabble then
return
end
 
local data = LibBabble.data or {}
for k,v in pairs(LibBabble) do
LibBabble[k] = nil
end
LibBabble.data = data
 
local tablesToDB = {}
for namespace, db in pairs(data) do
for k,v in pairs(db) do
tablesToDB[v] = db
end
end
 
local function warn(message)
local _, ret = pcall(error, message, 3)
geterrorhandler()(ret)
end
 
local lookup_mt = { __index = function(self, key)
local db = tablesToDB[self]
local current_key = db.current[key]
if current_key then
self[key] = current_key
return current_key
end
local base_key = db.base[key]
local real_MAJOR_VERSION
for k,v in pairs(data) do
if v == db then
real_MAJOR_VERSION = k
break
end
end
if not real_MAJOR_VERSION then
real_MAJOR_VERSION = LIBBABBLE_MAJOR
end
if base_key then
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GetLocale()))
rawset(self, key, base_key)
return base_key
end
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key))
rawset(self, key, key)
return key
end }
 
local function initLookup(module, lookup)
local db = tablesToDB[module]
for k in pairs(lookup) do
lookup[k] = nil
end
setmetatable(lookup, lookup_mt)
tablesToDB[lookup] = db
db.lookup = lookup
return lookup
end
 
local function initReverse(module, reverse)
local db = tablesToDB[module]
for k in pairs(reverse) do
reverse[k] = nil
end
for k,v in pairs(db.current) do
reverse[v] = k
end
tablesToDB[reverse] = db
db.reverse = reverse
db.reverseIterators = nil
return reverse
end
 
local prototype = {}
local prototype_mt = {__index = prototype}
 
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will warn but allow the code to pass through.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BL = B:GetLookupTable()
assert(BL["Some english word"] == "Some localized word")
DoSomething(BL["Some english word that doesn't exist"]) -- warning!
-----------------------------------------------------------------------------]]
function prototype:GetLookupTable()
local db = tablesToDB[self]
 
local lookup = db.lookup
if lookup then
return lookup
end
return initLookup(self, {})
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_has = B:GetUnstrictLookupTable()
assert(B_has["Some english word"] == "Some localized word")
assert(B_has["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetUnstrictLookupTable()
local db = tablesToDB[self]
 
return db.current
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_hasBase = B:GetBaseLookupTable()
assert(B_hasBase["Some english word"] == "Some english word")
assert(B_hasBase["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetBaseLookupTable()
local db = tablesToDB[self]
 
return db.base
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word")
Returns:
A lookup table for localized to english words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BR = B:GetReverseLookupTable()
assert(BR["Some localized word"] == "Some english word")
assert(BR["Some localized word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetReverseLookupTable()
local db = tablesToDB[self]
 
local reverse = db.reverse
if reverse then
return reverse
end
return initReverse(self, {})
end
local blank = {}
local weakVal = {__mode='v'}
--[[---------------------------------------------------------------------------
Arguments:
string - the localized word to chek for.
Returns:
An iterator to traverse all English words that map to the given key
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for word in B:GetReverseIterator("Some localized word") do
DoSomething(word)
end
-----------------------------------------------------------------------------]]
function prototype:GetReverseIterator(key)
local db = tablesToDB[self]
local reverseIterators = db.reverseIterators
if not reverseIterators then
reverseIterators = setmetatable({}, weakVal)
db.reverseIterators = reverseIterators
elseif reverseIterators[key] then
return pairs(reverseIterators[key])
end
local t
for k,v in pairs(db.current) do
if v == key then
if not t then
t = {}
end
t[k] = true
end
end
reverseIterators[key] = t or blank
return pairs(reverseIterators[key])
end
--[[---------------------------------------------------------------------------
Returns:
An iterator to traverse all translations English to localized.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for english, localized in B:Iterate() do
DoSomething(english, localized)
end
-----------------------------------------------------------------------------]]
function prototype:Iterate()
local db = tablesToDB[self]
 
return pairs(db.current)
end
 
-- #NODOC
-- modules need to call this to set the base table
function prototype:SetBaseTranslations(base)
local db = tablesToDB[self]
local oldBase = db.base
if oldBase then
for k in pairs(oldBase) do
oldBase[k] = nil
end
for k, v in pairs(base) do
oldBase[k] = v
end
base = oldBase
else
db.base = base
end
for k,v in pairs(base) do
if v == true then
base[k] = k
end
end
end
 
local function init(module)
local db = tablesToDB[module]
if db.lookup then
initLookup(module, db.lookup)
end
if db.reverse then
initReverse(module, db.reverse)
end
db.reverseIterators = nil
end
 
-- #NODOC
-- modules need to call this to set the current table. if current is true, use the base table.
function prototype:SetCurrentTranslations(current)
local db = tablesToDB[self]
if current == true then
db.current = db.base
else
local oldCurrent = db.current
if oldCurrent then
for k in pairs(oldCurrent) do
oldCurrent[k] = nil
end
for k, v in pairs(current) do
oldCurrent[k] = v
end
current = oldCurrent
else
db.current = current
end
end
init(self)
end
 
for namespace, db in pairs(data) do
setmetatable(db.module, prototype_mt)
init(db.module)
end
 
-- #NODOC
-- modules need to call this to create a new namespace.
function LibBabble:New(namespace, minor)
local module, oldminor = LibStub:NewLibrary(namespace, minor)
if not module then
return
end
 
if not oldminor then
local db = {
module = module,
}
data[namespace] = db
tablesToDB[module] = db
else
for k,v in pairs(module) do
module[k] = nil
end
end
 
setmetatable(module, prototype_mt)
 
return module
end
trunk/Libs/LibBabble-Zone-3.0/LibStub/LibStub.lua New file
0,0 → 1,30
-- 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 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)")
minor = assert(tonumber(strmatch(minor, "%d+")), "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(("Cannot find a library instance of %q."):format(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
trunk/Libs/LibBabble-Zone-3.0/LibBabble-Zone-3.0.lua New file
0,0 → 1,2320
--[[
Name: LibBabble-Zone-3.0
Revision: $Rev: 268 $
Maintainers: ckknight, nevcairiel, Ackis
Website: http://www.wowace.com/projects/libbabble-zone-3-0/
Dependencies: None
License: MIT
]]
 
local MAJOR_VERSION = "LibBabble-Zone-3.0"
local MINOR_VERSION = 90000 + tonumber(("$Rev: 268 $"):match("%d+"))
 
if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end
local lib = LibStub("LibBabble-3.0"):New(MAJOR_VERSION, MINOR_VERSION)
if not lib then return end
 
local GAME_LOCALE = GetLocale()
 
lib:SetBaseTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ahn'kahet: The Old Kingdom",
["Ahn'Qiraj"] = "Ahn'Qiraj",
["Alliance Base"] = "Alliance Base",
["Alterac Mountains"] = "Alterac Mountains",
["Alterac Valley"] = "Alterac Valley",
["Amani Pass"] = "Amani Pass",
["Arathi Basin"] = "Arathi Basin",
["Arathi Highlands"] = "Arathi Highlands",
Armory = "Armory",
Ashenvale = "Ashenvale",
Auberdine = "Auberdine",
["Auchenai Crypts"] = "Auchenai Crypts",
Auchindoun = "Auchindoun",
Azeroth = "Azeroth",
["Azjol-Nerub"] = "Azjol-Nerub",
Azshara = "Azshara",
["Azuremyst Isle"] = "Azuremyst Isle",
Badlands = "Badlands",
["Bash'ir Landing"] = "Bash'ir Landing",
["Blackfathom Deeps"] = "Blackfathom Deeps",
["Blackrock Depths"] = "Blackrock Depths",
["Blackrock Mountain"] = "Blackrock Mountain",
["Blackrock Spire"] = "Blackrock Spire",
["Black Temple"] = "Black Temple",
["Blackwind Lake"] = "Blackwind Lake",
["Blackwing Lair"] = "Blackwing Lair",
["Blade's Edge Arena"] = "Blade's Edge Arena",
["Blade's Edge Mountains"] = "Blade's Edge Mountains",
["Blasted Lands"] = "Blasted Lands",
["Bloodmyst Isle"] = "Bloodmyst Isle",
["Booty Bay"] = "Booty Bay",
["Borean Tundra"] = "Borean Tundra",
["Burning Steppes"] = "Burning Steppes",
Cathedral = "Cathedral",
["Caverns of Time"] = "Caverns of Time",
["Champions' Hall"] = "Champions' Hall",
["Coilfang Reservoir"] = "Coilfang Reservoir",
Coldarra = "Coldarra",
["Cosmic map"] = "Cosmic map",
["Crystalsong Forest"] = "Crystalsong Forest",
["Crystal Spine"] = "Crystal Spine",
Dalaran = "Dalaran",
["Dalaran Arena"] = "Dalaran Arena",
["Dalaran Sewers"] = "Dalaran Sewers",
["Darkmoon Faire"] = "Darkmoon Faire",
Darkshore = "Darkshore",
Darnassus = "Darnassus",
["Deadwind Pass"] = "Deadwind Pass",
["Deeprun Tram"] = "Deeprun Tram",
Desolace = "Desolace",
["Dire Maul"] = "Dire Maul",
["Dire Maul (East)"] = "Dire Maul (East)",
["Dire Maul (North)"] = "Dire Maul (North)",
["Dire Maul (West)"] = "Dire Maul (West)",
Dragonblight = "Dragonblight",
["Drak'Tharon Keep"] = "Drak'Tharon Keep",
["Dun Morogh"] = "Dun Morogh",
Durotar = "Durotar",
Duskwood = "Duskwood",
["Dustwallow Marsh"] = "Dustwallow Marsh",
["Eastern Kingdoms"] = "Eastern Kingdoms",
["Eastern Plaguelands"] = "Eastern Plaguelands",
["Elwynn Forest"] = "Elwynn Forest",
Everlook = "Everlook",
["Eversong Woods"] = "Eversong Woods",
["Eye of the Storm"] = "Eye of the Storm",
Felwood = "Felwood",
Feralas = "Feralas",
["Forge Camp: Terror"] = "Forge Camp: Terror",
["Forge Camp: Wrath"] = "Forge Camp: Wrath",
["Frostwyrm Lair"] = "Frostwyrm Lair",
["Furywing's Perch"] = "Furywing's Perch",
Gadgetzan = "Gadgetzan",
["Gates of Ahn'Qiraj"] = "Gates of Ahn'Qiraj",
Ghostlands = "Ghostlands",
Gnomeregan = "Gnomeregan",
Graveyard = "Graveyard",
["Grizzly Hills"] = "Grizzly Hills",
["Grom'gol Base Camp"] = "Grom'gol Base Camp",
["Gruul's Lair"] = "Gruul's Lair",
Gundrak = "Gundrak",
["Hall of Champions"] = "Hall of Champions",
["Hall of Legends"] = "Hall of Legends",
["Halls of Lightning"] = "Halls of Lightning",
["Halls of Reflection"] = "Halls of Reflection",
["Halls of Stone"] = "Halls of Stone",
["Hellfire Citadel"] = "Hellfire Citadel",
["Hellfire Peninsula"] = "Hellfire Peninsula",
["Hellfire Ramparts"] = "Hellfire Ramparts",
["Hillsbrad Foothills"] = "Hillsbrad Foothills",
["Horde Encampment"] = "Horde Encampment",
["Howling Fjord"] = "Howling Fjord",
["Hrothgar's Landing"] = "Hrothgar's Landing",
Hyjal = "Hyjal",
["Hyjal Summit"] = "Hyjal Summit",
Icecrown = "Icecrown",
["Icecrown Citadel"] = "Icecrown Citadel",
["Insidion's Perch"] = "Insidion's Perch",
Ironforge = "Ironforge",
["Isle of Conquest"] = "Isle of Conquest",
["Isle of Quel'Danas"] = "Isle of Quel'Danas",
Kalimdor = "Kalimdor",
Karazhan = "Karazhan",
["Krasus' Landing"] = "Krasus' Landing",
Library = "Library",
["Loch Modan"] = "Loch Modan",
["Lower Blackrock Spire"] = "Lower Blackrock Spire",
["Magisters' Terrace"] = "Magisters' Terrace",
["Magtheridon's Lair"] = "Magtheridon's Lair",
["Mana-Tombs"] = "Mana-Tombs",
Maraudon = "Maraudon",
["Marshlight Lake"] = "Marshlight Lake",
["Menethil Harbor"] = "Menethil Harbor",
["Molten Core"] = "Molten Core",
Moonglade = "Moonglade",
Mulgore = "Mulgore",
Nagrand = "Nagrand",
["Nagrand Arena"] = "Nagrand Arena",
Naxxramas = "Naxxramas",
Netherstorm = "Netherstorm",
["Night Elf Village"] = "Night Elf Village",
Northrend = "Northrend",
["Obsidia's Perch"] = "Obsidia's Perch",
["Ogri'la"] = "Ogri'la",
["Old Hillsbrad Foothills"] = "Old Hillsbrad Foothills",
["Old Stratholme"] = "Old Stratholme",
["Onyxia's Lair"] = "Onyxia's Lair",
Orgrimmar = "Orgrimmar",
Outland = "Outland",
["Pit of Saron"] = "Pit of Saron",
["Plaguelands: The Scarlet Enclave"] = "Plaguelands: The Scarlet Enclave",
Plaguewood = "Plaguewood",
["Quel'thalas"] = "Quel'thalas",
["Ragefire Chasm"] = "Ragefire Chasm",
Ratchet = "Ratchet",
["Razorfen Downs"] = "Razorfen Downs",
["Razorfen Kraul"] = "Razorfen Kraul",
["Redridge Mountains"] = "Redridge Mountains",
["Ring of Observance"] = "Ring of Observance",
["Rivendark's Perch"] = "Rivendark's Perch",
["Ruins of Ahn'Qiraj"] = "Ruins of Ahn'Qiraj",
["Ruins of Lordaeron"] = "Ruins of Lordaeron",
["Scalebeard's Cave"] = "Scalebeard's Cave",
["Scarlet Monastery"] = "Scarlet Monastery",
Scholomance = "Scholomance",
["Searing Gorge"] = "Searing Gorge",
["Serpent Lake"] = "Serpent Lake",
["Serpentshrine Cavern"] = "Serpentshrine Cavern",
["Sethekk Halls"] = "Sethekk Halls",
["Shadowfang Keep"] = "Shadowfang Keep",
["Shadow Labyrinth"] = "Shadow Labyrinth",
["Shadowmoon Valley"] = "Shadowmoon Valley",
["Shartuul's Transporter"] = "Shartuul's Transporter",
Shattrath = "Shattrath",
["Shattrath City"] = "Shattrath City",
["Sholazar Basin"] = "Sholazar Basin",
Silithus = "Silithus",
["Silvermoon City"] = "Silvermoon City",
["Silverpine Forest"] = "Silverpine Forest",
["Skyguard Outpost"] = "Skyguard Outpost",
["Skysong Lake"] = "Skysong Lake",
["Sporewind Lake"] = "Sporewind Lake",
Stonard = "Stonard",
["Stonetalon Mountains"] = "Stonetalon Mountains",
Stormwind = "Stormwind",
["Stormwind City"] = "Stormwind City",
["Strand of the Ancients"] = "Strand of the Ancients",
["Stranglethorn Vale"] = "Stranglethorn Vale",
Stratholme = "Stratholme",
["Sunken Temple"] = "Sunken Temple",
["Sunwell Plateau"] = "Sunwell Plateau",
["Swamp of Sorrows"] = "Swamp of Sorrows",
Tanaris = "Tanaris",
Teldrassil = "Teldrassil",
["Tempest Keep"] = "Tempest Keep",
["Temple of Ahn'Qiraj"] = "Temple of Ahn'Qiraj",
["Terokkar Forest"] = "Terokkar Forest",
["Terokk's Rest"] = "Terokk's Rest",
["The Arachnid Quarter"] = "The Arachnid Quarter",
["The Arcatraz"] = "The Arcatraz",
["The Argent Coliseum"] = "The Argent Coliseum",
["The Barrens"] = "The Barrens",
["The Black Morass"] = "The Black Morass",
["The Blood Furnace"] = "The Blood Furnace",
["The Bone Wastes"] = "The Bone Wastes",
["The Botanica"] = "The Botanica",
["The Construct Quarter"] = "The Construct Quarter",
["The Culling of Stratholme"] = "The Culling of Stratholme",
["The Dark Portal"] = "The Dark Portal",
["The Deadmines"] = "The Deadmines",
["The Descent into Madness"] = "The Descent into Madness",
["The Exodar"] = "The Exodar",
["The Eye"] = "The Eye",
["The Eye of Eternity"] = "The Eye of Eternity",
["The Forbidding Sea"] = "The Forbidding Sea",
["The Forge of Souls"] = "The Forge of Souls",
["The Frozen Halls"] = "The Frozen Halls",
["The Frozen Sea"] = "The Frozen Sea",
["The Great Sea"] = "The Great Sea",
["The Halls of Winter"] = "The Halls of Winter",
["The Hinterlands"] = "The Hinterlands",
["The Mechanar"] = "The Mechanar",
["The Military Quarter"] = "The Military Quarter",
["The Nexus"] = "The Nexus",
["The North Sea"] = "The North Sea",
["The Obsidian Sanctum"] = "The Obsidian Sanctum",
["The Oculus"] = "The Oculus",
["The Plague Quarter"] = "The Plague Quarter",
["The Prison of Yogg-Saron"] = "The Prison of Yogg-Saron",
["Theramore Isle"] = "Theramore Isle",
["The Ring of Valor"] = "The Ring of Valor",
["The Ruby Sanctum"] = "The Ruby Sanctum",
["The Scarlet Enclave"] = "The Scarlet Enclave",
["The Shattered Halls"] = "The Shattered Halls",
["The Slave Pens"] = "The Slave Pens",
["The Spark of Imagination"] = "The Spark of Imagination",
["The Steamvault"] = "The Steamvault",
["The Stockade"] = "The Stockade",
["The Storm Peaks"] = "The Storm Peaks",
["The Temple of Atal'Hakkar"] = "The Temple of Atal'Hakkar",
["The Underbog"] = "The Underbog",
["The Veiled Sea"] = "The Veiled Sea",
["The Violet Hold"] = "The Violet Hold",
["Thousand Needles"] = "Thousand Needles",
["Thunder Bluff"] = "Thunder Bluff",
Tirisfal = "Tirisfal",
["Tirisfal Glades"] = "Tirisfal Glades",
["Trial of the Champion"] = "Trial of the Champion",
["Trial of the Crusader"] = "Trial of the Crusader",
["Twisting Nether"] = "Twisting Nether",
Uldaman = "Uldaman",
Ulduar = "Ulduar",
Undercity = "Undercity",
["Un'Goro Crater"] = "Un'Goro Crater",
["Upper Blackrock Spire"] = "Upper Blackrock Spire",
["Utgarde Keep"] = "Utgarde Keep",
["Utgarde Pinnacle"] = "Utgarde Pinnacle",
["Vault of Archavon"] = "Vault of Archavon",
["Vortex Pinnacle"] = "Vortex Pinnacle",
["Wailing Caverns"] = "Wailing Caverns",
["Warsong Gulch"] = "Warsong Gulch",
["Western Plaguelands"] = "Western Plaguelands",
Westfall = "Westfall",
Wetlands = "Wetlands",
Wintergrasp = "Wintergrasp",
Winterspring = "Winterspring",
["Wyrmrest Temple"] = "Wyrmrest Temple",
Zangarmarsh = "Zangarmarsh",
["Zul'Aman"] = "Zul'Aman",
["Zul'Drak"] = "Zul'Drak",
["Zul'Farrak"] = "Zul'Farrak",
["Zul'Gurub"] = "Zul'Gurub",
}
 
 
if GAME_LOCALE == "enUS" then
lib:SetCurrentTranslations(true)
elseif GAME_LOCALE == "deDE" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ahn'kahet: Das Alte Königreich",
["Ahn'Qiraj"] = "Ahn'Qiraj",
["Alliance Base"] = "Basis der Allianz",
["Alterac Mountains"] = "Alteracgebirge",
["Alterac Valley"] = "Alteractal",
["Amani Pass"] = "Amanipass",
["Arathi Basin"] = "Arathibecken",
["Arathi Highlands"] = "Arathihochland",
Armory = "Waffenkammer",
Ashenvale = "Eschental",
Auberdine = "Auberdine",
["Auchenai Crypts"] = "Auchenaikrypta",
Auchindoun = "Auchindoun",
Azeroth = "Azeroth",
["Azjol-Nerub"] = "Azjol-Nerub",
Azshara = "Azshara",
["Azuremyst Isle"] = "Azurmythosinsel",
Badlands = "Ödland",
["Bash'ir Landing"] = "Landeplatz von Bash'ir",
["Blackfathom Deeps"] = "Tiefschwarze Grotte",
["Blackrock Depths"] = "Schwarzfelstiefen",
["Blackrock Mountain"] = "Der Schwarzfels",
["Blackrock Spire"] = "Schwarzfelsspitze",
["Black Temple"] = "Der Schwarze Tempel",
["Blackwind Lake"] = "Schattenwindsee",
["Blackwing Lair"] = "Pechschwingenhort",
["Blade's Edge Arena"] = "Arena des Schergrats",
["Blade's Edge Mountains"] = "Schergrat",
["Blasted Lands"] = "Verwüstete Lande",
["Bloodmyst Isle"] = "Blutmythosinsel",
["Booty Bay"] = "Beutebucht",
["Borean Tundra"] = "Boreanische Tundra",
["Burning Steppes"] = "Brennende Steppe",
Cathedral = "Kathedrale",
["Caverns of Time"] = "Höhlen der Zeit",
["Champions' Hall"] = "Halle der Champions",
["Coilfang Reservoir"] = "Der Echsenkessel",
Coldarra = "Kaltarra",
["Cosmic map"] = "Kosmische Karte",
["Crystalsong Forest"] = "Kristallsangwald",
["Crystal Spine"] = "Kristallrücken",
Dalaran = "Dalaran",
["Dalaran Arena"] = "Arena von Dalaran",
["Dalaran Sewers"] = "Arena von Dalaran",
["Darkmoon Faire"] = "Dunkelmond-Jahrmarkt",
Darkshore = "Dunkelküste",
Darnassus = "Darnassus",
["Deadwind Pass"] = "Gebirgspass der Totenwinde",
["Deeprun Tram"] = "Die Tiefenbahn",
Desolace = "Desolace",
["Dire Maul"] = "Düsterbruch",
["Dire Maul (East)"] = "Düsterbruch (Ost)",
["Dire Maul (North)"] = "Düsterbruch (Nord)",
["Dire Maul (West)"] = "Düsterbruch (West)",
Dragonblight = "Drachenöde",
["Drak'Tharon Keep"] = "Feste Drak'Tharon",
["Dun Morogh"] = "Dun Morogh",
Durotar = "Durotar",
Duskwood = "Dämmerwald",
["Dustwallow Marsh"] = "Düstermarschen",
["Eastern Kingdoms"] = "Östliche Königreiche",
["Eastern Plaguelands"] = "Östliche Pestländer",
["Elwynn Forest"] = "Wald von Elwynn",
Everlook = "Ewige Warte",
["Eversong Woods"] = "Immersangwald",
["Eye of the Storm"] = "Auge des Sturms",
Felwood = "Teufelswald",
Feralas = "Feralas",
["Forge Camp: Terror"] = "Konstruktionslager: Terror",
["Forge Camp: Wrath"] = "Konstruktionslager: Wut",
["Frostwyrm Lair"] = "Frostwyrmbau",
["Furywing's Perch"] = "Isidions Hort",
Gadgetzan = "Gadgetzan",
["Gates of Ahn'Qiraj"] = "Tore von Ahn'Qiraj",
Ghostlands = "Geisterlande",
Gnomeregan = "Gnomeregan",
Graveyard = "Friedhof",
["Grizzly Hills"] = "Grizzlyhügel",
["Grom'gol Base Camp"] = "Basislager von Grom'gol",
["Gruul's Lair"] = "Gruuls Unterschlupf",
Gundrak = "Gundrak",
["Hall of Champions"] = "Halle der Champions",
["Hall of Legends"] = "Halle der Legenden",
["Halls of Lightning"] = "Die Hallen der Blitze",
["Halls of Reflection"] = "Hallen der Reflexion",
["Halls of Stone"] = "Die Hallen des Steins",
["Hellfire Citadel"] = "Höllenfeuerzitadelle",
["Hellfire Peninsula"] = "Höllenfeuerhalbinsel",
["Hellfire Ramparts"] = "Höllenfeuerbollwerk",
["Hillsbrad Foothills"] = "Vorgebirge des Hügellands",
["Horde Encampment"] = "Lager der Horde",
["Howling Fjord"] = "Der heulende Fjord",
["Hrothgar's Landing"] = "Hrothgars Landestelle",
Hyjal = "Hyjal",
["Hyjal Summit"] = "Hyjalgipfel",
Icecrown = "Eiskrone",
["Icecrown Citadel"] = "Eiskronenzitadelle",
["Insidion's Perch"] = "Isidions Hort",
Ironforge = "Eisenschmiede",
["Isle of Conquest"] = "Insel der Eroberung",
["Isle of Quel'Danas"] = "Insel von Quel'Danas",
Kalimdor = "Kalimdor",
Karazhan = "Karazhan",
["Krasus' Landing"] = "Krasus' Landeplatz",
Library = "Bibliothek",
["Loch Modan"] = "Loch Modan",
["Lower Blackrock Spire"] = "Untere Schwarzfelsspitze",
["Magisters' Terrace"] = "Terrasse der Magister",
["Magtheridon's Lair"] = "Magtheridons Kammer",
["Mana-Tombs"] = "Managruft",
Maraudon = "Maraudon",
["Marshlight Lake"] = "Sumpflichtsee",
["Menethil Harbor"] = "Hafen von Menethil",
["Molten Core"] = "Geschmolzener Kern",
Moonglade = "Mondlichtung",
Mulgore = "Mulgore",
Nagrand = "Nagrand",
["Nagrand Arena"] = "Arena von Nagrand",
Naxxramas = "Naxxramas",
Netherstorm = "Nethersturm",
["Night Elf Village"] = "Nachtelfen Dorf",
Northrend = "Nordend",
["Obsidia's Perch"] = "Obsidias Hort",
["Ogri'la"] = "Ogri'la",
["Old Hillsbrad Foothills"] = "Vorgebirge des Alten Hügellands",
["Old Stratholme"] = "Alt-Stratholme",
["Onyxia's Lair"] = "Onyxias Hort",
Orgrimmar = "Orgrimmar",
Outland = "Scherbenwelt",
["Pit of Saron"] = "Grube von Saron",
["Plaguelands: The Scarlet Enclave"] = "Pestländer: Die Scharlachrote Enklave",
Plaguewood = "Seuchenwald",
["Quel'thalas"] = "Quel'Thalas",
["Ragefire Chasm"] = "Der Flammenschlund",
Ratchet = "Ratschet",
["Razorfen Downs"] = "Hügel der Klingenhauer",
["Razorfen Kraul"] = "Kral der Klingenhauer",
["Redridge Mountains"] = "Rotkammgebirge",
["Ring of Observance"] = "Ring der Beobachtung",
["Rivendark's Perch"] = "Nachtreißers Hort",
["Ruins of Ahn'Qiraj"] = "Ruinen von Ahn'Qiraj",
["Ruins of Lordaeron"] = "Ruinen von Lordaeron",
["Scalebeard's Cave"] = "Schuppenbarts Höhle",
["Scarlet Monastery"] = "Das Scharlachrote Kloster",
Scholomance = "Scholomance",
["Searing Gorge"] = "Sengende Schlucht",
["Serpent Lake"] = "Schlangensee",
["Serpentshrine Cavern"] = "Höhle des Schlangenschreins",
["Sethekk Halls"] = "Sethekkhallen",
["Shadowfang Keep"] = "Burg Schattenfang",
["Shadow Labyrinth"] = "Schattenlabyrinth",
["Shadowmoon Valley"] = "Schattenmondtal",
["Shartuul's Transporter"] = "Shartuuls Transporter",
Shattrath = "Shattrath",
["Shattrath City"] = "Shattrath",
["Sholazar Basin"] = "Sholazarbecken",
Silithus = "Silithus",
["Silvermoon City"] = "Silbermond",
["Silverpine Forest"] = "Silberwald",
["Skyguard Outpost"] = "Außenposten der Himmelswache",
["Skysong Lake"] = "Himmelsweisensee",
["Sporewind Lake"] = "Sporenwindsee",
Stonard = "Steinard",
["Stonetalon Mountains"] = "Steinkrallengebirge",
Stormwind = "Sturmwind",
["Stormwind City"] = "Sturmwind",
["Strand of the Ancients"] = "Strand der Uralten",
["Stranglethorn Vale"] = "Schlingendorntal",
Stratholme = "Stratholme",
["Sunken Temple"] = "Versunkener Tempel",
["Sunwell Plateau"] = "Sonnenbrunnenplateau",
["Swamp of Sorrows"] = "Sümpfe des Elends",
Tanaris = "Tanaris",
Teldrassil = "Teldrassil",
["Tempest Keep"] = "Festung der Stürme",
["Temple of Ahn'Qiraj"] = "Tempel von Ahn'Qiraj",
["Terokkar Forest"] = "Wälder von Terokkar",
["Terokk's Rest"] = "Terokks Ruh",
["The Arachnid Quarter"] = "Das Arachnidenviertel",
["The Arcatraz"] = "Die Arkatraz",
["The Argent Coliseum"] = "Das Kolosseum der Kreuzfahrer",
["The Barrens"] = "Brachland",
["The Black Morass"] = "Der schwarze Morast",
["The Blood Furnace"] = "Der Blutkessel",
["The Bone Wastes"] = "Die Knochenwüste",
["The Botanica"] = "Die Botanika",
["The Construct Quarter"] = "Das Konstruktviertel",
["The Culling of Stratholme"] = "Das Ausmerzen von Stratholme",
["The Dark Portal"] = "Das Dunkle Portal",
["The Deadmines"] = "Die Todesminen",
["The Descent into Madness"] = "Der Abstieg in den Wahnsinn",
["The Exodar"] = "Die Exodar",
["The Eye"] = "Das Auge",
["The Eye of Eternity"] = "Das Auge der Ewigkeit",
["The Forbidding Sea"] = "Das verbotene Meer",
["The Forge of Souls"] = "Die Schmiede der Seelen",
["The Frozen Halls"] = "Die gefrorenen Hallen",
["The Frozen Sea"] = "Die gefrorene See",
["The Great Sea"] = "Das große Meer",
["The Halls of Winter"] = "Die Hallen des Winters",
["The Hinterlands"] = "Hinterland",
["The Mechanar"] = "Die Mechanar",
["The Military Quarter"] = "Das Militärviertel",
["The Nexus"] = "Der Nexus",
["The North Sea"] = "Das nördliche Meer",
["The Obsidian Sanctum"] = "Das Obsidiansanktum",
["The Oculus"] = "Das Oculus",
["The Plague Quarter"] = "Das Seuchenviertel",
["The Prison of Yogg-Saron"] = "Das Gefängnis von Yogg-Saron",
["Theramore Isle"] = "Insel Theramore",
["The Ring of Valor"] = "Der Ring der Ehre",
["The Ruby Sanctum"] = "Das Rubinsanktum",
["The Scarlet Enclave"] = "Die Scharlachrote Enklave",
["The Shattered Halls"] = "Die zerschmetterten Hallen",
["The Slave Pens"] = "Die Sklavenunterkünfte",
["The Spark of Imagination"] = "Der Funke der Imagination",
["The Steamvault"] = "Die Dampfkammer",
["The Stockade"] = "Das Verlies",
["The Storm Peaks"] = "Die Sturmgipfel",
["The Temple of Atal'Hakkar"] = "Der Tempel von Atal'Hakkar",
["The Underbog"] = "Der Tiefensumpf",
["The Veiled Sea"] = "Das verhüllte Meer",
["The Violet Hold"] = "Die Violette Festung",
["Thousand Needles"] = "Tausend Nadeln",
["Thunder Bluff"] = "Donnerfels",
Tirisfal = "Tirisfal",
["Tirisfal Glades"] = "Tirisfal",
["Trial of the Champion"] = "Prüfung des Champions",
["Trial of the Crusader"] = "Prüfung des Kreuzfahrers",
["Twisting Nether"] = "Wirbelnder Nether",
Uldaman = "Uldaman",
Ulduar = "Ulduar",
Undercity = "Unterstadt",
["Un'Goro Crater"] = "Krater von Un'Goro",
["Upper Blackrock Spire"] = "Obere Schwarzfelsspitze",
["Utgarde Keep"] = "Burg Utgarde",
["Utgarde Pinnacle"] = "Turm Utgarde",
["Vault of Archavon"] = "Archavons Kammer",
["Vortex Pinnacle"] = "Vortexgipfel",
["Wailing Caverns"] = "Die Höhlen des Wehklagens",
["Warsong Gulch"] = "Kriegshymnenschlucht",
["Western Plaguelands"] = "Westliche Pestländer",
Westfall = "Westfall",
Wetlands = "Sumpfland",
Wintergrasp = "Tausendwintersee",
Winterspring = "Winterquell",
["Wyrmrest Temple"] = "Wyrmruhtempel",
Zangarmarsh = "Zangarmarschen",
["Zul'Aman"] = "Zul'Aman",
["Zul'Drak"] = "Zul'Drak",
["Zul'Farrak"] = "Zul'Farrak",
["Zul'Gurub"] = "Zul'Gurub",
}
elseif GAME_LOCALE == "frFR" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ahn'kahet : l'Ancien royaume",
["Ahn'Qiraj"] = "Ahn'Qiraj",
["Alliance Base"] = "Base de l'Alliance",
["Alterac Mountains"] = "Montagnes d'Alterac",
["Alterac Valley"] = "Vallée d'Alterac",
["Amani Pass"] = "Passage des Amani",
["Arathi Basin"] = "Bassin d'Arathi",
["Arathi Highlands"] = "Hautes-terres d'Arathi",
Armory = "Armurerie",
Ashenvale = "Orneval",
Auberdine = "Auberdine",
["Auchenai Crypts"] = "Cryptes Auchenaï",
Auchindoun = "Auchindoun",
Azeroth = "Azeroth",
["Azjol-Nerub"] = "Azjol-Nérub",
Azshara = "Azshara",
["Azuremyst Isle"] = "Île de Brume-azur",
Badlands = "Terres ingrates",
["Bash'ir Landing"] = "Point d'ancrage de Bash'ir",
["Blackfathom Deeps"] = "Profondeurs de Brassenoire",
["Blackrock Depths"] = "Profondeurs de Rochenoire",
["Blackrock Mountain"] = "Mont Rochenoire",
["Blackrock Spire"] = "Pic Rochenoire",
["Black Temple"] = "Temple noir",
["Blackwind Lake"] = "Lac Noirvent",
["Blackwing Lair"] = "Repaire de l'Aile noire",
["Blade's Edge Arena"] = "Arène des Tranchantes",
["Blade's Edge Mountains"] = "Les Tranchantes",
["Blasted Lands"] = "Terres foudroyées",
["Bloodmyst Isle"] = "Île de Brume-sang",
["Booty Bay"] = "Baie-du-Butin",
["Borean Tundra"] = "Toundra Boréenne",
["Burning Steppes"] = "Steppes ardentes",
Cathedral = "Cathédrale",
["Caverns of Time"] = "Grottes du temps",
["Champions' Hall"] = "Hall des Champions",
["Coilfang Reservoir"] = "Réservoir de Glissecroc",
Coldarra = "Frimarra",
["Cosmic map"] = "Carte cosmique",
["Crystalsong Forest"] = "Forêt du Chant de cristal",
["Crystal Spine"] = "Éperon de cristal",
Dalaran = "Dalaran",
["Dalaran Arena"] = "Arène de Dalaran",
["Dalaran Sewers"] = "Égouts de Dalaran",
["Darkmoon Faire"] = "Foire de Sombrelune",
Darkshore = "Sombrivage",
Darnassus = "Darnassus",
["Deadwind Pass"] = "Défilé de Deuillevent",
["Deeprun Tram"] = "Tram des profondeurs",
Desolace = "Désolace",
["Dire Maul"] = "Hache-tripes",
["Dire Maul (East)"] = "Hache-tripes (Est)",
["Dire Maul (North)"] = "Hache-tripes (Nord)",
["Dire Maul (West)"] = "Hache-tripes (Ouest)",
Dragonblight = "Désolation des dragons",
["Drak'Tharon Keep"] = "Donjon de Drak'Tharon",
["Dun Morogh"] = "Dun Morogh",
Durotar = "Durotar",
Duskwood = "Bois de la Pénombre",
["Dustwallow Marsh"] = "Marécage d'Âprefange",
["Eastern Kingdoms"] = "Royaumes de l'est",
["Eastern Plaguelands"] = "Maleterres de l'est",
["Elwynn Forest"] = "Forêt d'Elwynn",
Everlook = "Long-guet",
["Eversong Woods"] = "Bois des Chants éternels",
["Eye of the Storm"] = "L'Œil du cyclone",
Felwood = "Gangrebois",
Feralas = "Féralas",
["Forge Camp: Terror"] = "Camp de forge : Terreur",
["Forge Camp: Wrath"] = "Camp de forge : Courroux",
["Frostwyrm Lair"] = "Repaire du wyrm de givre",
["Furywing's Perch"] = "Perchoir d'Aile-furie",
Gadgetzan = "Gadgetzan",
["Gates of Ahn'Qiraj"] = "Portes d'Ahn'Qiraj",
Ghostlands = "Les Terres fantômes",
Gnomeregan = "Gnomeregan",
Graveyard = "Cimetière",
["Grizzly Hills"] = "Les Grisonnes",
["Grom'gol Base Camp"] = "Campement Grom'gol",
["Gruul's Lair"] = "Repaire de Gruul",
Gundrak = "Gundrak",
["Hall of Champions"] = "Hall des Champions",
["Hall of Legends"] = "Hall des Légendes",
["Halls of Lightning"] = "Les salles de Foudre",
["Halls of Reflection"] = "Les salles des Reflets",
["Halls of Stone"] = "Les salles de Pierre",
["Hellfire Citadel"] = "Citadelle des Flammes infernales",
["Hellfire Peninsula"] = "Péninsule des Flammes infernales",
["Hellfire Ramparts"] = "Remparts des Flammes infernales",
["Hillsbrad Foothills"] = "Contreforts de Hautebrande",
["Horde Encampment"] = "Campement de la Horde",
["Howling Fjord"] = "Fjord Hurlant",
["Hrothgar's Landing"] = "Accostage de Hrothgar",
Hyjal = "Hyjal",
["Hyjal Summit"] = "Sommet d'Hyjal",
Icecrown = "La Couronne de glace",
["Icecrown Citadel"] = "Citadelle de la Couronne de glace",
["Insidion's Perch"] = "Perchoir d'Insidion",
Ironforge = "Forgefer",
["Isle of Conquest"] = "Île des Conquérants",
["Isle of Quel'Danas"] = "Île de Quel'Danas",
Kalimdor = "Kalimdor",
Karazhan = "Karazhan",
["Krasus' Landing"] = "Aire de Krasus",
Library = "Bibliothèque",
["Loch Modan"] = "Loch Modan",
["Lower Blackrock Spire"] = "Pic de Rochenoire inférieur",
["Magisters' Terrace"] = "Terrasse des Magistères",
["Magtheridon's Lair"] = "Le repaire de Magtheridon",
["Mana-Tombs"] = "Tombes-mana",
Maraudon = "Maraudon",
["Marshlight Lake"] = "Lac des furoles",
["Menethil Harbor"] = "Port de Menethil",
["Molten Core"] = "Cœur du Magma",
Moonglade = "Reflet-de-Lune",
Mulgore = "Mulgore",
Nagrand = "Nagrand",
["Nagrand Arena"] = "Arène de Nagrand",
Naxxramas = "Naxxramas",
Netherstorm = "Raz-de-Néant",
["Night Elf Village"] = "Village elfe de la nuit",
Northrend = "Norfendre",
["Obsidia's Perch"] = "Perchoir d'Obsidia",
["Ogri'la"] = "Ogri'la",
["Old Hillsbrad Foothills"] = "Contreforts de Hautebrande d'antan",
["Old Stratholme"] = "L'Épuration de Stratholme",
["Onyxia's Lair"] = "Repaire d'Onyxia",
Orgrimmar = "Orgrimmar",
Outland = "Outreterre",
["Pit of Saron"] = "Fosse de Saron",
["Plaguelands: The Scarlet Enclave"] = "Maleterres : l'enclave Écarlate",
Plaguewood = "Pestebois",
["Quel'thalas"] = "Quel'thalas",
["Ragefire Chasm"] = "Gouffre de Ragefeu",
Ratchet = "Cabestan",
["Razorfen Downs"] = "Souilles de Tranchebauge",
["Razorfen Kraul"] = "Kraal de Tranchebauge",
["Redridge Mountains"] = "Les Carmines",
["Ring of Observance"] = "Cercle d'observance",
["Rivendark's Perch"] = "Perchoir de Clivenuit",
["Ruins of Ahn'Qiraj"] = "Ruines d'Ahn'Qiraj",
["Ruins of Lordaeron"] = "Ruines de Lordaeron",
["Scalebeard's Cave"] = "Caverne de Barbe-d'écailles",
["Scarlet Monastery"] = "Monastère écarlate",
Scholomance = "Scholomance",
["Searing Gorge"] = "Gorge des Vents brûlants",
["Serpent Lake"] = "Lac des Serpents",
["Serpentshrine Cavern"] = "Caverne du sanctuaire du Serpent",
["Sethekk Halls"] = "Les salles des Sethekk",
["Shadowfang Keep"] = "Donjon d'Ombrecroc",
["Shadow Labyrinth"] = "Labyrinthe des ombres",
["Shadowmoon Valley"] = "Vallée d'Ombrelune",
["Shartuul's Transporter"] = "Transporteur de Shartuul",
Shattrath = "Shattrath",
["Shattrath City"] = "Shattrath",
["Sholazar Basin"] = "Bassin de Sholazar",
Silithus = "Silithus",
["Silvermoon City"] = "Lune-d'argent",
["Silverpine Forest"] = "Forêt des Pins argentés",
["Skyguard Outpost"] = "Avant-poste de la Garde-ciel",
["Skysong Lake"] = "Lac Chanteciel",
["Sporewind Lake"] = "Lac Ventespore",
Stonard = "Pierrêche",
["Stonetalon Mountains"] = "Les Serres-Rocheuses",
Stormwind = "Hurlevent",
["Stormwind City"] = "Hurlevent",
["Strand of the Ancients"] = "Rivage des anciens",
["Stranglethorn Vale"] = "Vallée de Strangleronce",
Stratholme = "Stratholme",
["Sunken Temple"] = "Temple englouti",
["Sunwell Plateau"] = "Plateau du Puits de soleil",
["Swamp of Sorrows"] = "Marais des Chagrins",
Tanaris = "Tanaris",
Teldrassil = "Teldrassil",
["Tempest Keep"] = "Donjon de la Tempête",
["Temple of Ahn'Qiraj"] = "Le temple d'Ahn'Qiraj",
["Terokkar Forest"] = "Forêt de Terokkar",
["Terokk's Rest"] = "Repos de Terokk",
["The Arachnid Quarter"] = "Le quartier des Arachnides",
["The Arcatraz"] = "L'Arcatraz",
["The Argent Coliseum"] = "Le colisée d'Argent",
["The Barrens"] = "Les Tarides",
["The Black Morass"] = "Le Noir Marécage",
["The Blood Furnace"] = "La Fournaise du sang",
["The Bone Wastes"] = "Le désert des Ossements",
["The Botanica"] = "La Botanica",
["The Construct Quarter"] = "Le quartier des Assemblages",
["The Culling of Stratholme"] = "L'Épuration de Stratholme",
["The Dark Portal"] = "La Porte des ténèbres",
["The Deadmines"] = "Les Mortemines",
["The Descent into Madness"] = "La Descente dans la folie",
["The Exodar"] = "L'Exodar",
["The Eye"] = "L'Œil",
["The Eye of Eternity"] = "L'Œil de l'éternité",
["The Forbidding Sea"] = "La Mer interdite",
["The Forge of Souls"] = "La Forge des âmes",
["The Frozen Halls"] = "Les salles Gelées",
["The Frozen Sea"] = "La mer Gelée",
["The Great Sea"] = "La Grande mer",
["The Halls of Winter"] = "Les salles de l'Hiver",
["The Hinterlands"] = "Les Hinterlands",
["The Mechanar"] = "Le Méchanar",
["The Military Quarter"] = "Le quartier Militaire",
["The Nexus"] = "Le Nexus",
["The North Sea"] = "La mer Boréale",
["The Obsidian Sanctum"] = "Le sanctum Obsidien",
["The Oculus"] = "L'Oculus",
["The Plague Quarter"] = "Le quartier de la Peste",
["The Prison of Yogg-Saron"] = "La prison de Yogg-Saron",
["Theramore Isle"] = "Île de Theramore",
["The Ring of Valor"] = "L'Arène des valeureux",
["The Ruby Sanctum"] = "Le sanctum Rubis",
["The Scarlet Enclave"] = "L'enclave Écarlate",
["The Shattered Halls"] = "Les Salles brisées",
["The Slave Pens"] = "Les enclos aux esclaves",
["The Spark of Imagination"] = "L'Étincelle d'imagination",
["The Steamvault"] = "Le Caveau de la vapeur",
["The Stockade"] = "La Prison",
["The Storm Peaks"] = "Les pics Foudroyés",
["The Temple of Atal'Hakkar"] = "Le temple d'Atal'Hakkar",
["The Underbog"] = "La Basse-tourbière",
["The Veiled Sea"] = "La Mer voilée",
["The Violet Hold"] = "Le fort Pourpre",
["Thousand Needles"] = "Mille pointes",
["Thunder Bluff"] = "Les Pitons du Tonnerre",
Tirisfal = "Tirisfal",
["Tirisfal Glades"] = "Clairières de Tirisfal",
["Trial of the Champion"] = "L'épreuve du champion",
["Trial of the Crusader"] = "L'épreuve du croisé",
["Twisting Nether"] = "Le Néant distordu",
Uldaman = "Uldaman",
Ulduar = "Ulduar",
Undercity = "Fossoyeuse",
["Un'Goro Crater"] = "Cratère d'Un'Goro",
["Upper Blackrock Spire"] = "Pic de Rochenoire supérieur",
["Utgarde Keep"] = "Donjon d'Utgarde",
["Utgarde Pinnacle"] = "Cime d'Utgarde",
["Vault of Archavon"] = "Caveau d'Archavon",
["Vortex Pinnacle"] = "Cime du vortex",
["Wailing Caverns"] = "Cavernes des lamentations",
["Warsong Gulch"] = "Goulet des Chanteguerres",
["Western Plaguelands"] = "Maleterres de l'ouest",
Westfall = "Marche de l'Ouest",
Wetlands = "Les Paluns",
Wintergrasp = "Joug-d'hiver",
Winterspring = "Berceau-de-l'Hiver",
["Wyrmrest Temple"] = "Temple du Repos du ver",
Zangarmarsh = "Marécage de Zangar",
["Zul'Aman"] = "Zul'Aman",
["Zul'Drak"] = "Zul'Drak",
["Zul'Farrak"] = "Zul'Farrak",
["Zul'Gurub"] = "Zul'Gurub",
}
elseif GAME_LOCALE == "koKR" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "안카헤트: 고대 왕국",
["Ahn'Qiraj"] = "안퀴라즈",
["Alliance Base"] = "얼라이언스 주둔지",
["Alterac Mountains"] = "알터랙 산맥",
["Alterac Valley"] = "알터랙 계곡",
["Amani Pass"] = "아마니 고개",
["Arathi Basin"] = "아라시 분지",
["Arathi Highlands"] = "아라시 고원",
Armory = "무기고",
Ashenvale = "잿빛 골짜기",
Auberdine = "아우버다인",
["Auchenai Crypts"] = "아키나이 납골당",
Auchindoun = "아킨둔",
Azeroth = "아제로스",
["Azjol-Nerub"] = "아졸네룹",
Azshara = "아즈샤라",
["Azuremyst Isle"] = "하늘안개 섬",
Badlands = "황야의 땅",
["Bash'ir Landing"] = "바쉬르 영지",
["Blackfathom Deeps"] = "검은심연의 나락",
["Blackrock Depths"] = "검은바위 나락",
["Blackrock Mountain"] = "검은바위 산",
["Blackrock Spire"] = "검은바위 첨탑",
["Black Temple"] = "검은 사원",
["Blackwind Lake"] = "검은바람 호수",
["Blackwing Lair"] = "검은날개 둥지",
["Blade's Edge Arena"] = "칼날 투기장",
["Blade's Edge Mountains"] = "칼날 산맥",
["Blasted Lands"] = "저주받은 땅",
["Bloodmyst Isle"] = "핏빛안개 섬",
["Booty Bay"] = "무법항",
["Borean Tundra"] = "북풍의 땅",
["Burning Steppes"] = "불타는 평원",
Cathedral = "대성당",
["Caverns of Time"] = "시간의 동굴",
["Champions' Hall"] = "용사의 전당",
["Coilfang Reservoir"] = "갈퀴송곳니 저수지",
Coldarra = "콜다라",
["Cosmic map"] = "세계 지도",
["Crystalsong Forest"] = "수정노래 숲",
["Crystal Spine"] = "수정 돌기",
Dalaran = "달라란",
["Dalaran Arena"] = "달라란 투기장",
["Dalaran Sewers"] = "달라란 하수도",
["Darkmoon Faire"] = "다크문 축제",
Darkshore = "어둠의 해안",
Darnassus = "다르나서스",
["Deadwind Pass"] = "죽음의 고개",
["Deeprun Tram"] = "깊은굴 지하철",
Desolace = "잊혀진 땅",
["Dire Maul"] = "혈투의 전장",
["Dire Maul (East)"] = "혈투의 전장 동부",
["Dire Maul (North)"] = "혈투의 전장 북부",
["Dire Maul (West)"] = "혈투의 전장 서부",
Dragonblight = "용의 안식처",
["Drak'Tharon Keep"] = "드락타론 성채",
["Dun Morogh"] = "던 모로",
Durotar = "듀로타",
Duskwood = "그늘숲",
["Dustwallow Marsh"] = "먼지진흙 습지대",
["Eastern Kingdoms"] = "동부 왕국",
["Eastern Plaguelands"] = "동부 역병지대",
["Elwynn Forest"] = "엘윈 숲",
Everlook = "눈망루 마을",
["Eversong Woods"] = "영원노래 숲",
["Eye of the Storm"] = "폭풍의 눈",
Felwood = "악령의 숲",
Feralas = "페랄라스",
["Forge Camp: Terror"] = "공포의 괴철로 기지",
["Forge Camp: Wrath"] = "격노의 괴철로 기지",
["Frostwyrm Lair"] = "서리고룡의 방",
["Furywing's Perch"] = "퓨리윙의 둥지",
Gadgetzan = "가젯잔",
["Gates of Ahn'Qiraj"] = "안퀴라즈 성문",
Ghostlands = "유령의 땅",
Gnomeregan = "놈리건",
Graveyard = "묘지",
["Grizzly Hills"] = "회색 구릉지",
["Grom'gol Base Camp"] = "그롬골 주둔지",
["Gruul's Lair"] = "그룰의 둥지",
Gundrak = "군드락",
["Hall of Champions"] = "용사의 전당",
["Hall of Legends"] = "전설의 전당",
["Halls of Lightning"] = "번개의 전당",
["Halls of Reflection"] = "투영의 전당",
["Halls of Stone"] = "돌의 전당",
["Hellfire Citadel"] = "지옥불 성채",
["Hellfire Peninsula"] = "지옥불 반도",
["Hellfire Ramparts"] = "지옥불 성루",
["Hillsbrad Foothills"] = "힐스브래드 구릉지",
["Horde Encampment"] = "호드 야영지",
["Howling Fjord"] = "울부짖는 협만",
["Hrothgar's Landing"] = "흐로스가르 상륙지",
Hyjal = "하이잘",
["Hyjal Summit"] = "하이잘 정상",
Icecrown = "얼음왕관",
["Icecrown Citadel"] = "얼음왕관 성채",
["Insidion's Perch"] = "인시디온의 둥지",
Ironforge = "아이언포지",
["Isle of Conquest"] = "정복의 섬",
["Isle of Quel'Danas"] = "쿠엘다나스 섬",
Kalimdor = "칼림도어",
Karazhan = "카라잔",
["Krasus' Landing"] = "크라서스 착륙장",
Library = "도서관",
["Loch Modan"] = "모단 호수",
["Lower Blackrock Spire"] = "검은바위 첨탑 하층",
["Magisters' Terrace"] = "마법학자의 정원",
["Magtheridon's Lair"] = "마그테리돈의 둥지",
["Mana-Tombs"] = "마나 무덤",
Maraudon = "마라우돈",
["Marshlight Lake"] = "수렁등불 호수",
["Menethil Harbor"] = "메네실 항구",
["Molten Core"] = "화산 심장부",
Moonglade = "달의 숲",
Mulgore = "멀고어",
Nagrand = "나그란드",
["Nagrand Arena"] = "나그란드 투기장",
Naxxramas = "낙스라마스",
Netherstorm = "황천의 폭풍",
["Night Elf Village"] = "나이트 엘프 마을",
Northrend = "노스렌드",
["Obsidia's Perch"] = "옵시디아의 둥지",
["Ogri'la"] = "오그릴라",
["Old Hillsbrad Foothills"] = "옛 힐스브래드 구릉지",
["Old Stratholme"] = "옛 스트라솔름",
["Onyxia's Lair"] = "오닉시아의 둥지",
Orgrimmar = "오그리마",
Outland = "아웃랜드",
["Pit of Saron"] = "사론의 구덩이",
["Plaguelands: The Scarlet Enclave"] = "동부 역병지대: 붉은십자군 초소",
Plaguewood = "역병의 숲",
["Quel'thalas"] = "쿠엘탈라스",
["Ragefire Chasm"] = "성난불길 협곡",
Ratchet = "톱니항",
["Razorfen Downs"] = "가시덩굴 구릉",
["Razorfen Kraul"] = "가시덩굴 우리",
["Redridge Mountains"] = "붉은마루 산맥",
["Ring of Observance"] = "규율의 광장",
["Rivendark's Perch"] = "리븐다크의 둥지",
["Ruins of Ahn'Qiraj"] = "안퀴라즈 폐허",
["Ruins of Lordaeron"] = "로데론의 폐허",
["Scalebeard's Cave"] = "비늘수염 동굴",
["Scarlet Monastery"] = "붉은십자군 수도원",
Scholomance = "스칼로맨스",
["Searing Gorge"] = "이글거리는 협곡",
["Serpent Lake"] = "물갈퀴 호수",
["Serpentshrine Cavern"] = "불뱀 제단",
["Sethekk Halls"] = "세데크 전당",
["Shadowfang Keep"] = "그림자송곳니 성채",
["Shadow Labyrinth"] = "어둠의 미궁",
["Shadowmoon Valley"] = "어둠달 골짜기",
["Shartuul's Transporter"] = "샤툴의 순간이동기",
Shattrath = "샤트라스",
["Shattrath City"] = "샤트라스",
["Sholazar Basin"] = "숄라자르 분지",
Silithus = "실리더스",
["Silvermoon City"] = "실버문",
["Silverpine Forest"] = "은빛소나무 숲",
["Skyguard Outpost"] = "하늘경비대 전초기지",
["Skysong Lake"] = "하늘노래 호수",
["Sporewind Lake"] = "포자바람 호수",
Stonard = "스토나드",
["Stonetalon Mountains"] = "돌발톱 산맥",
Stormwind = "스톰윈드",
["Stormwind City"] = "스톰윈드",
["Strand of the Ancients"] = "고대의 해안",
["Stranglethorn Vale"] = "가시덤불 골짜기",
Stratholme = "스트라솔름",
["Sunken Temple"] = "가라앉은 사원",
["Sunwell Plateau"] = "태양샘 고원",
["Swamp of Sorrows"] = "슬픔의 늪",
Tanaris = "타나리스",
Teldrassil = "텔드랏실",
["Tempest Keep"] = "폭풍우 요새",
["Temple of Ahn'Qiraj"] = "안퀴라즈 사원",
["Terokkar Forest"] = "테로카르 숲",
["Terokk's Rest"] = "테로크의 안식처",
["The Arachnid Quarter"] = "거미 지구",
["The Arcatraz"] = "알카트라즈",
["The Argent Coliseum"] = "십자군 원형경기장",
["The Barrens"] = "불모의 땅",
["The Black Morass"] = "검은늪",
["The Blood Furnace"] = "피의 용광로",
["The Bone Wastes"] = "해골 무덤",
["The Botanica"] = "신록의 정원",
["The Construct Quarter"] = "피조물 지구",
["The Culling of Stratholme"] = "옛 스트라솔름",
["The Dark Portal"] = "어둠의 문",
["The Deadmines"] = "죽음의 폐광",
["The Descent into Madness"] = "광기의 내리막길",
["The Exodar"] = "엑소다르",
["The Eye"] = "눈",
["The Eye of Eternity"] = "영원의 눈",
["The Forbidding Sea"] = "성난폭풍 해안",
["The Forge of Souls"] = "영혼의 제련소",
["The Frozen Halls"] = "얼어붙은 전당",
["The Frozen Sea"] = "얼어붙은 바다",
["The Great Sea"] = "대해",
["The Halls of Winter"] = "겨울의 전당",
["The Hinterlands"] = "동부 내륙지",
["The Mechanar"] = "메카나르",
["The Military Quarter"] = "군사 지구",
["The Nexus"] = "마력의 탑",
["The North Sea"] = "북해",
["The Obsidian Sanctum"] = "흑요석 성소",
["The Oculus"] = "마력의 눈",
["The Plague Quarter"] = "역병 지구",
["The Prison of Yogg-Saron"] = "요그사론의 감옥",
["Theramore Isle"] = "테라모어 섬",
["The Ring of Valor"] = "용맹의 투기장",
["The Ruby Sanctum"] = "루비 성소", -- Needs review
["The Scarlet Enclave"] = "진홍빛 전당",
["The Shattered Halls"] = "으스러진 손의 전당",
["The Slave Pens"] = "강제 노역소",
["The Spark of Imagination"] = "상상의 흔적",
["The Steamvault"] = "증기 저장고",
["The Stockade"] = "스톰윈드 지하감옥",
["The Storm Peaks"] = "폭풍우 봉우리",
["The Temple of Atal'Hakkar"] = "아탈학카르 신전",
["The Underbog"] = "지하수렁",
["The Veiled Sea"] = "장막의 바다",
["The Violet Hold"] = "보랏빛 요새",
["Thousand Needles"] = "버섯구름 봉우리",
["Thunder Bluff"] = "썬더 블러프",
Tirisfal = "티리스팔",
["Tirisfal Glades"] = "티리스팔 숲",
["Trial of the Champion"] = "용사의 시험장",
["Trial of the Crusader"] = "십자군의 시험장",
["Twisting Nether"] = "뒤틀린 황천",
Uldaman = "울다만",
Ulduar = "울두아르",
Undercity = "언더시티",
["Un'Goro Crater"] = "운고로 분화구",
["Upper Blackrock Spire"] = "검은바위 첨탑 상층",
["Utgarde Keep"] = "우트가드 성채",
["Utgarde Pinnacle"] = "우트가드 첨탑",
["Vault of Archavon"] = "아카본 석실",
["Vortex Pinnacle"] = "소용돌이 고원",
["Wailing Caverns"] = "통곡의 동굴",
["Warsong Gulch"] = "전쟁노래 협곡",
["Western Plaguelands"] = "서부 역병지대",
Westfall = "서부 몰락지대",
Wetlands = "저습지",
Wintergrasp = "겨울손아귀 호수",
Winterspring = "여명의 설원",
["Wyrmrest Temple"] = "고룡쉼터 사원",
Zangarmarsh = "장가르 습지대",
["Zul'Aman"] = "줄아만",
["Zul'Drak"] = "줄드락",
["Zul'Farrak"] = "줄파락",
["Zul'Gurub"] = "줄구룹",
}
elseif GAME_LOCALE == "esES" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ahn'kahet: El Antiguo Reino",
["Ahn'Qiraj"] = "Ahn'Qiraj",
["Alliance Base"] = "Base de la Alianza",
["Alterac Mountains"] = "Montañas de Alterac",
["Alterac Valley"] = "Valle de Alterac",
["Amani Pass"] = "Paso de Amani",
["Arathi Basin"] = "Cuenca de Arathi",
["Arathi Highlands"] = "Tierras Altas de Arathi",
Armory = "Armería",
Ashenvale = "Vallefresno",
Auberdine = "Auberdine",
["Auchenai Crypts"] = "Criptas Auchenai",
Auchindoun = "Auchindoun",
Azeroth = "Azeroth",
["Azjol-Nerub"] = "Azjol-Nerub",
Azshara = "Azshara",
["Azuremyst Isle"] = "Isla Bruma Azur",
Badlands = "Tierras Inhóspitas",
["Bash'ir Landing"] = "Zona de aterrizaje Bash'ir",
["Blackfathom Deeps"] = "Cavernas de Brazanegra",
["Blackrock Depths"] = "Profundidades de Roca Negra",
["Blackrock Mountain"] = "Montaña Roca Negra",
["Blackrock Spire"] = "Cumbre de Roca Negra",
["Black Temple"] = "El Templo Oscuro",
["Blackwind Lake"] = "Lago Vientonegro",
["Blackwing Lair"] = "Guarida Alanegra",
["Blade's Edge Arena"] = "Arena Filospada",
["Blade's Edge Mountains"] = "Montañas Filospada",
["Blasted Lands"] = "Las Tierras Devastadas",
["Bloodmyst Isle"] = "Isla Bruma de Sangre",
["Booty Bay"] = "Bahía del Botín",
["Borean Tundra"] = "Tundra Boreal",
["Burning Steppes"] = "Las Estepas Ardientes",
Cathedral = "Catedral",
["Caverns of Time"] = "Cavernas del Tiempo",
["Champions' Hall"] = "Sala de los Campeones",
["Coilfang Reservoir"] = "Reserva Colmillo Torcido",
Coldarra = "Gelidar",
["Cosmic map"] = "Mapa cósmico",
["Crystalsong Forest"] = "Bosque Canto de Cristal",
["Crystal Spine"] = "Espina de Cristal",
Dalaran = "Dalaran",
["Dalaran Arena"] = "Arena de Dalaran",
["Dalaran Sewers"] = "Cloacas de Dalaran",
["Darkmoon Faire"] = "Feria de la Luna Negra",
Darkshore = "Costa Oscura",
Darnassus = "Darnassus",
["Deadwind Pass"] = "Paso de la Muerte",
["Deeprun Tram"] = "Tranvía Subterráneo",
Desolace = "Desolace",
["Dire Maul"] = "La Masacre",
["Dire Maul (East)"] = "La Masacre (Este)",
["Dire Maul (North)"] = "La Masacre (Norte)",
["Dire Maul (West)"] = "La Masacre (Oeste)",
Dragonblight = "Cementerio de Dragones",
["Drak'Tharon Keep"] = "Fortaleza de Drak'Tharon",
["Dun Morogh"] = "Dun Morogh",
Durotar = "Durotar",
Duskwood = "Bosque del Ocaso",
["Dustwallow Marsh"] = "Marjal Revolcafango",
["Eastern Kingdoms"] = "Reinos del Este",
["Eastern Plaguelands"] = "Tierras de la Peste del Este",
["Elwynn Forest"] = "Bosque de Elwynn",
Everlook = "Vista Eterna",
["Eversong Woods"] = "Bosque Canción Eterna",
["Eye of the Storm"] = "Ojo de la Tormenta",
Felwood = "Frondavil",
Feralas = "Feralas",
["Forge Camp: Terror"] = "Campamento forja: Terror",
["Forge Camp: Wrath"] = "Campamento forja: Cólera",
["Frostwyrm Lair"] = "Guarida de Vermis de Escarcha",
["Furywing's Perch"] = "Nido de Alafuria",
Gadgetzan = "Gadgetzan",
["Gates of Ahn'Qiraj"] = "Puertas de Ahn'Qiraj",
Ghostlands = "Tierras Fantasma",
Gnomeregan = "Gnomeregan",
Graveyard = "Cementerio",
["Grizzly Hills"] = "Colinas Pardas",
["Grom'gol Base Camp"] = "Campamento Grom'gol",
["Gruul's Lair"] = "Guarida de Gruul",
Gundrak = "Gundrak",
["Hall of Champions"] = "Sala de los Campeones",
["Hall of Legends"] = "Sala de las Leyendas",
["Halls of Lightning"] = "Cámaras de Relámpagos",
["Halls of Reflection"] = "Cámaras de Reflexión",
["Halls of Stone"] = "Cámaras de Piedra",
["Hellfire Citadel"] = "Ciudadela del Fuego Infernal",
["Hellfire Peninsula"] = "Península del Fuego Infernal",
["Hellfire Ramparts"] = "Murallas del Fuego Infernal",
["Hillsbrad Foothills"] = "Laderas de Trabalomas",
["Horde Encampment"] = "Campamento Horda",
["Howling Fjord"] = "Fiordo Aquilonal",
["Hrothgar's Landing"] = "Desembarco de Hrothgar",
Hyjal = "Hyjal",
["Hyjal Summit"] = "Cima Hyjal",
Icecrown = "Corona de Hielo",
["Icecrown Citadel"] = "Ciudadela de la Corona de Hielo",
["Insidion's Perch"] = "Nido de Insidion",
Ironforge = "Forjaz",
["Isle of Conquest"] = "Isla de la Conquista",
["Isle of Quel'Danas"] = "Isla de Quel'Danas",
Kalimdor = "Kalimdor",
Karazhan = "Karazhan",
["Krasus' Landing"] = "Krasus' Landing",
Library = "Biblioteca",
["Loch Modan"] = "Loch Modan",
["Lower Blackrock Spire"] = "Cumbre inferior de Roca Negra",
["Magisters' Terrace"] = "Bancal Del Magister",
["Magtheridon's Lair"] = "Guarida de Magtheridon",
["Mana-Tombs"] = "Tumbas de Maná",
Maraudon = "Maraudon",
["Marshlight Lake"] = "Lago Luz Pantanosa",
["Menethil Harbor"] = "Puerto de Menethil",
["Molten Core"] = "Núcleo de Magma",
Moonglade = "Claro de la Luna",
Mulgore = "Mulgore",
Nagrand = "Nagrand",
["Nagrand Arena"] = "Arena de Nagrand",
Naxxramas = "Naxxramas",
Netherstorm = "Tormenta Abisal",
["Night Elf Village"] = "Poblado Elfo de la Noche",
Northrend = "Rasganorte",
["Obsidia's Perch"] = "Nido de Obsidia",
["Ogri'la"] = "Ogri'la",
["Old Hillsbrad Foothills"] = "Antiguas Laderas de Trabalomas",
["Old Stratholme"] = "Stratholme en el pasado",
["Onyxia's Lair"] = "Guarida de Onyxia",
Orgrimmar = "Orgrimmar",
Outland = "Terrallende",
["Pit of Saron"] = "Foso de Saron",
["Plaguelands: The Scarlet Enclave"] = "Tierras de la Peste del Este: El Enclave Escarlata",
Plaguewood = "Bosque de la Plaga",
["Quel'thalas"] = "Quel'thalas",
["Ragefire Chasm"] = "Sima ígnea",
Ratchet = "Trinquete",
["Razorfen Downs"] = "Zahúrda Rajacieno",
["Razorfen Kraul"] = "Horado Rajacieno",
["Redridge Mountains"] = "Montañas Crestagrana",
["Ring of Observance"] = "Círculo de la Observancia",
["Rivendark's Perch"] = "Nido de Desgarro Oscuro",
["Ruins of Ahn'Qiraj"] = "Ruinas de Ahn'Qiraj",
["Ruins of Lordaeron"] = "Ruinas de Lordaeron",
["Scalebeard's Cave"] = "Cueva de Barbascamas",
["Scarlet Monastery"] = "Monasterio Escarlata",
Scholomance = "Scholomance",
["Searing Gorge"] = "La Garganta de Fuego",
["Serpent Lake"] = "Lago Serpiente",
["Serpentshrine Cavern"] = "Caverna Santuario Serpiente",
["Sethekk Halls"] = "Salas Sethekk",
["Shadowfang Keep"] = "Castillo de Colmillo Oscuro",
["Shadow Labyrinth"] = "Laberinto de las Sombras",
["Shadowmoon Valley"] = "Valle Sombraluna",
["Shartuul's Transporter"] = "Transportador de Shartuul",
Shattrath = "Shattrath",
["Shattrath City"] = "Ciudad de Shattrath",
["Sholazar Basin"] = "Cuenca de Sholazar",
Silithus = "Silithus",
["Silvermoon City"] = "Ciudad de Lunargenta",
["Silverpine Forest"] = "Bosque de Argénteos",
["Skyguard Outpost"] = "Puesto de la guardia de cielo",
["Skysong Lake"] = "Lago Sol Celeste",
["Sporewind Lake"] = "Lago Espora Volante",
Stonard = "Rocal",
["Stonetalon Mountains"] = "Sierra Espolón",
Stormwind = "Ventormenta",
["Stormwind City"] = "Ciudad de Ventormenta",
["Strand of the Ancients"] = "Playa de los Ancestros",
["Stranglethorn Vale"] = "Vega de Tuercespina",
Stratholme = "Stratholme",
["Sunken Temple"] = "El Templo Sumergido",
["Sunwell Plateau"] = "Meseta de la Fuente del Sol",
["Swamp of Sorrows"] = "Pantano de las Penas",
Tanaris = "Tanaris",
Teldrassil = "Teldrassil",
["Tempest Keep"] = "El Castillo de la Tempestad",
["Temple of Ahn'Qiraj"] = "El Templo de Ahn'Qiraj",
["Terokkar Forest"] = "Bosque de Terokkar",
["Terokk's Rest"] = "Sosiego de Terokk",
["The Arachnid Quarter"] = "Ala Arácnida",
["The Arcatraz"] = "El Alcatraz",
["The Argent Coliseum"] = "El Coliseo Argenta",
["The Barrens"] = "Los Baldíos",
["The Black Morass"] = "La Ciénaga Negra",
["The Blood Furnace"] = "El Horno de Sangre",
["The Bone Wastes"] = "El Vertedero de Huesos",
["The Botanica"] = "El Invernáculo",
["The Construct Quarter"] = "Ala de Abominación",
["The Culling of Stratholme"] = "La Matanza de Stratholme",
["The Dark Portal"] = "El Portal Oscuro",
["The Deadmines"] = "Las Minas de la Muerte",
["The Descent into Madness"] = "Descenso a la Locura",
["The Exodar"] = "El Exodar",
["The Eye"] = "El Ojo",
["The Eye of Eternity"] = "El Ojo de la Eternidad",
["The Forbidding Sea"] = "Mar Adusto",
["The Forge of Souls"] = "La Forja de Almas",
["The Frozen Halls"] = "Las Cámaras Heladas",
["The Frozen Sea"] = "El Mar Gélido",
["The Great Sea"] = "Mare Magnum",
["The Halls of Winter"] = "Las Cámaras del Invierno",
["The Hinterlands"] = "Tierras del Interior",
["The Mechanar"] = "El Mechanar",
["The Military Quarter"] = "Ala Militar",
["The Nexus"] = "El Nexo",
["The North Sea"] = "El Mar Norte",
["The Obsidian Sanctum"] = "El Sagrario Obsidiana",
["The Oculus"] = "El Oculus",
["The Plague Quarter"] = "Ala de la Plaga",
["The Prison of Yogg-Saron"] = "La Prisión de Yogg-Saron",
["Theramore Isle"] = "Isla Theramore",
["The Ring of Valor"] = "El Anillo del Valor",
-- ["The Ruby Sanctum"] = "",
["The Scarlet Enclave"] = "Tierras de la Peste: El Enclave Escarlata",
["The Shattered Halls"] = "Las Salas Arrasadas",
["The Slave Pens"] = "Recinto de los Esclavos",
["The Spark of Imagination"] = "Cámaras de la Invención",
["The Steamvault"] = "La Cámara de Vapor",
["The Stockade"] = "Las Mazmorras",
["The Storm Peaks"] = "Las Cumbres Tormentosas",
["The Temple of Atal'Hakkar"] = "El Templo de Atal'Hakkar",
["The Underbog"] = "La Sotiénaga",
["The Veiled Sea"] = "Mar de la Bruma",
["The Violet Hold"] = "El Bastión Violeta",
["Thousand Needles"] = "Las Mil Agujas",
["Thunder Bluff"] = "Cima del Trueno",
Tirisfal = "Tirisfal",
["Tirisfal Glades"] = "Claros de Tirisfal",
["Trial of the Champion"] = "Prueba del Cruzado",
["Trial of the Crusader"] = "Prueba del Cruzado",
["Twisting Nether"] = "El Vacío Abisal",
Uldaman = "Uldaman",
Ulduar = "Ulduar",
Undercity = "Entrañas",
["Un'Goro Crater"] = "Cráter de Un'Goro",
["Upper Blackrock Spire"] = "Cumbre de Roca Negra",
["Utgarde Keep"] = "Fortaleza de Utgarde",
["Utgarde Pinnacle"] = "Pináculo de Utgarde",
["Vault of Archavon"] = "La Cámara de Archavon",
["Vortex Pinnacle"] = "Cumbre del Vórtice",
["Wailing Caverns"] = "Cuevas de los Lamentos",
["Warsong Gulch"] = "Garganta Grito de Guerra",
["Western Plaguelands"] = "Tierras de la Peste del Oeste",
Westfall = "Páramos de Poniente",
Wetlands = "Los Humedales",
Wintergrasp = "Conquista del Invierno",
Winterspring = "Cuna del Invierno",
["Wyrmrest Temple"] = "Templo del Reposo del Dragón",
Zangarmarsh = "Marisma de Zangar",
["Zul'Aman"] = "Zul'Aman",
["Zul'Drak"] = "Zul'Drak",
["Zul'Farrak"] = "Zul'Farrak",
["Zul'Gurub"] = "Zul'Gurub",
}
elseif GAME_LOCALE == "esMX" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ahn'kahet: El Antiguo Reino",
["Ahn'Qiraj"] = "Ahn'Qiraj",
["Alliance Base"] = "Base de la Alianza",
["Alterac Mountains"] = "Montañas de Alterac",
["Alterac Valley"] = "Valle de Alterac",
["Amani Pass"] = "Paso de Amani",
["Arathi Basin"] = "Cuenca de Arathi",
["Arathi Highlands"] = "Tierras Altas de Arathi",
Armory = "Armería",
Ashenvale = "Vallefresno",
Auberdine = "Auberdine",
["Auchenai Crypts"] = "Criptas Auchenai",
Auchindoun = "Auchindoun",
Azeroth = "Azeroth",
["Azjol-Nerub"] = "Azjol-Nerub",
Azshara = "Azshara",
["Azuremyst Isle"] = "Isla Bruma Azur",
Badlands = "Tierras Inhóspitas",
["Bash'ir Landing"] = "Zona de aterrizaje Bash'ir",
["Blackfathom Deeps"] = "Cavernas de Brazanegra",
["Blackrock Depths"] = "Profundidades de Roca Negra",
["Blackrock Mountain"] = "Montaña Roca Negra",
["Blackrock Spire"] = "Cumbre de Roca Negra",
["Black Temple"] = "El Templo Oscuro",
["Blackwind Lake"] = "Lago Vientonegro",
["Blackwing Lair"] = "Guarida Alanegra",
["Blade's Edge Arena"] = "Arena Filospada",
["Blade's Edge Mountains"] = "Montañas Filospada",
["Blasted Lands"] = "Las Tierras Devastadas",
["Bloodmyst Isle"] = "Isla Bruma de Sangre",
["Booty Bay"] = "Bahía del Botín",
["Borean Tundra"] = "Tundra Boreal",
["Burning Steppes"] = "Las Estepas Ardientes",
Cathedral = "Catedral",
["Caverns of Time"] = "Cavernas del Tiempo",
["Champions' Hall"] = "Sala de los Campeones",
["Coilfang Reservoir"] = "Reserva Colmillo Torcido",
Coldarra = "Gelidar",
["Cosmic map"] = "Mapa cósmico",
["Crystalsong Forest"] = "Bosque Canto de Cristal",
["Crystal Spine"] = "Espina de Cristal",
Dalaran = "Dalaran",
["Dalaran Arena"] = "Arena de Dalaran",
["Dalaran Sewers"] = "Cloacas de Dalaran",
["Darkmoon Faire"] = "Feria de la Luna Negra",
Darkshore = "Costa Oscura",
Darnassus = "Darnassus",
["Deadwind Pass"] = "Paso de la Muerte",
["Deeprun Tram"] = "Tranvía Subterráneo",
Desolace = "Desolace",
["Dire Maul"] = "La Masacre",
["Dire Maul (East)"] = "La Masacre (Este)",
["Dire Maul (North)"] = "La Masacre (Norte)",
["Dire Maul (West)"] = "La Masacre (Oeste)",
Dragonblight = "Cementerio de Dragones",
["Drak'Tharon Keep"] = "Fortaleza de Drak'Tharon",
["Dun Morogh"] = "Dun Morogh",
Durotar = "Durotar",
Duskwood = "Bosque del Ocaso",
["Dustwallow Marsh"] = "Marjal Revolcafango",
["Eastern Kingdoms"] = "Reinos del Este",
["Eastern Plaguelands"] = "Tierras de la Peste del Este",
["Elwynn Forest"] = "Bosque de Elwynn",
Everlook = "Vista Eterna",
["Eversong Woods"] = "Bosque Canción Eterna",
["Eye of the Storm"] = "Ojo de la Tormenta",
Felwood = "Frondavil",
Feralas = "Feralas",
["Forge Camp: Terror"] = "Campamento forja: Terror",
["Forge Camp: Wrath"] = "Campamento forja: Cólera",
["Frostwyrm Lair"] = "Guarida de Vermis de Escarcha",
["Furywing's Perch"] = "Nido de Alafuria",
Gadgetzan = "Gadgetzan",
["Gates of Ahn'Qiraj"] = "Puertas de Ahn'Qiraj",
Ghostlands = "Tierras Fantasma",
Gnomeregan = "Gnomeregan",
Graveyard = "Cementerio",
["Grizzly Hills"] = "Colinas Pardas",
["Grom'gol Base Camp"] = "Campamento Grom'gol",
["Gruul's Lair"] = "Guarida de Gruul",
Gundrak = "Gundrak",
["Hall of Champions"] = "Sala de los Campeones",
["Hall of Legends"] = "Sala de las Leyendas",
["Halls of Lightning"] = "Cámaras de Relámpagos",
["Halls of Reflection"] = "Camáras de Reflexión",
["Halls of Stone"] = "Cámaras de Piedra",
["Hellfire Citadel"] = "Ciudadela del Fuego Infernal",
["Hellfire Peninsula"] = "Península del Fuego Infernal",
["Hellfire Ramparts"] = "Murallas del Fuego Infernal",
["Hillsbrad Foothills"] = "Laderas de Trabalomas",
["Horde Encampment"] = "Campamento Horda",
["Howling Fjord"] = "Fiordo Aquilonal",
["Hrothgar's Landing"] = "Desembarco de Hrothgar",
Hyjal = "Hyjal",
["Hyjal Summit"] = "Cima Hyjal",
Icecrown = "Corona de Hielo",
["Icecrown Citadel"] = "Ciudadela de la Corona de Hielo",
["Insidion's Perch"] = "Nido de Insidion",
Ironforge = "Forjaz",
["Isle of Conquest"] = "Isla de la Conquista",
["Isle of Quel'Danas"] = "Isla de Quel'Danas",
Kalimdor = "Kalimdor",
Karazhan = "Karazhan",
["Krasus' Landing"] = "Krasus' Landing",
Library = "Biblioteca",
["Loch Modan"] = "Loch Modan",
["Lower Blackrock Spire"] = "Cumbre inferior de Roca Negra",
["Magisters' Terrace"] = "Bancal Del Magister",
["Magtheridon's Lair"] = "Guarida de Magtheridon",
["Mana-Tombs"] = "Tumbas de Maná",
Maraudon = "Maraudon",
["Marshlight Lake"] = "Lago Luz Pantanosa",
["Menethil Harbor"] = "Puerto de Menethil",
["Molten Core"] = "Núcleo de Magma",
Moonglade = "Claro de la Luna",
Mulgore = "Mulgore",
Nagrand = "Nagrand",
["Nagrand Arena"] = "Arena de Nagrand",
Naxxramas = "Naxxramas",
Netherstorm = "Tormenta Abisal",
["Night Elf Village"] = "Poblado Elfo de la Noche",
Northrend = "Rasganorte",
["Obsidia's Perch"] = "Nido de Obsidia",
["Ogri'la"] = "Ogri'la",
["Old Hillsbrad Foothills"] = "Antiguas Laderas de Trabalomas",
["Old Stratholme"] = "Stratholme en el pasado",
["Onyxia's Lair"] = "Guarida de Onyxia",
Orgrimmar = "Orgrimmar",
Outland = "Terrallende",
["Pit of Saron"] = "Foso de Saron",
["Plaguelands: The Scarlet Enclave"] = "Tierras de la Peste del Este: El Enclave Escarlata",
Plaguewood = "Bosque de la Plaga",
["Quel'thalas"] = "Quel'thalas",
["Ragefire Chasm"] = "Sima ígnea",
Ratchet = "Trinquete",
["Razorfen Downs"] = "Zahúrda Rajacieno",
["Razorfen Kraul"] = "Horado Rajacieno",
["Redridge Mountains"] = "Montañas Crestagrana",
["Ring of Observance"] = "Círculo de la Observancia",
["Rivendark's Perch"] = "Nido de Desgarro Oscuro",
["Ruins of Ahn'Qiraj"] = "Ruinas de Ahn'Qiraj",
["Ruins of Lordaeron"] = "Ruinas de Lordaeron",
["Scalebeard's Cave"] = "Cueva de Barbaescamas",
["Scarlet Monastery"] = "Monasterio Escarlata",
Scholomance = "Scholomance",
["Searing Gorge"] = "La Garganta de Fuego",
["Serpent Lake"] = "Lago Serpiente",
["Serpentshrine Cavern"] = "Caverna Santuario Serpiente",
["Sethekk Halls"] = "Salas Sethekk",
["Shadowfang Keep"] = "Castillo de Colmillo Oscuro",
["Shadow Labyrinth"] = "Laberinto de las Sombras",
["Shadowmoon Valley"] = "Valle Sombraluna",
["Shartuul's Transporter"] = "Transportador de Shartuul",
Shattrath = "Shattrath",
["Shattrath City"] = "Ciudad de Shattrath",
["Sholazar Basin"] = "Cuenca de Sholazar",
Silithus = "Silithus",
["Silvermoon City"] = "Ciudad de Lunargenta",
["Silverpine Forest"] = "Bosque de Argénteos",
["Skyguard Outpost"] = "Puesto de la guardia de cielo",
["Skysong Lake"] = "Lago Son Celeste",
["Sporewind Lake"] = "Lago Espora Volante",
Stonard = "Rocal",
["Stonetalon Mountains"] = "Sierra Espolón",
Stormwind = "Ventormenta",
["Stormwind City"] = "Ciudad de Ventormenta",
["Strand of the Ancients"] = "Playa de los Ancestros",
["Stranglethorn Vale"] = "Vega de Tuercespina",
Stratholme = "Stratholme",
["Sunken Temple"] = "El Templo Sumergido",
["Sunwell Plateau"] = "Meseta de la Fuente del Sol",
["Swamp of Sorrows"] = "Pantano de las Penas",
Tanaris = "Tanaris",
Teldrassil = "Teldrassil",
["Tempest Keep"] = "El Castillo de la Tempestad",
["Temple of Ahn'Qiraj"] = "El Templo de Ahn'Qiraj",
["Terokkar Forest"] = "Bosque de Terokkar",
["Terokk's Rest"] = "Sosiego de Terokk",
["The Arachnid Quarter"] = "Ala Arácnida",
["The Arcatraz"] = "El Alcatraz",
["The Argent Coliseum"] = "El Coliseo Argenta",
["The Barrens"] = "Los Baldíos",
["The Black Morass"] = "La Ciénaga Negra",
["The Blood Furnace"] = "El Horno de Sangre",
["The Bone Wastes"] = "El Vertedero de Huesos",
["The Botanica"] = "El Invernáculo",
["The Construct Quarter"] = "Ala de Abominación",
["The Culling of Stratholme"] = "La Matanza de Stratholme",
["The Dark Portal"] = "El Portal Oscuro",
["The Deadmines"] = "Las Minas de la Muerte",
["The Descent into Madness"] = "Descenso a la Locura",
["The Exodar"] = "El Exodar",
["The Eye"] = "El Ojo",
["The Eye of Eternity"] = "El Ojo de la Eternidad",
["The Forbidding Sea"] = "Mar Adusto",
["The Forge of Souls"] = "La Forja de Almas",
["The Frozen Halls"] = "Las Salas Gélidas",
["The Frozen Sea"] = "El Mar Gélido",
["The Great Sea"] = "Mare Magnum",
["The Halls of Winter"] = "Las Cámaras del Invierno",
["The Hinterlands"] = "Tierras del Interior",
["The Mechanar"] = "El Mechanar",
["The Military Quarter"] = "Ala Militar",
["The Nexus"] = "El Nexo",
["The North Sea"] = "El Mar Norte",
["The Obsidian Sanctum"] = "El Sagrario Obsidiana",
["The Oculus"] = "El Oculus",
["The Plague Quarter"] = "Ala de la Plaga",
["The Prison of Yogg-Saron"] = "La Prisión de Yogg-Saron",
["Theramore Isle"] = "Isla Theramore",
["The Ring of Valor"] = "El Anillo del Valor",
-- ["The Ruby Sanctum"] = "",
["The Scarlet Enclave"] = "El Enclave Escarlata",
["The Shattered Halls"] = "Las Salas Arrasadas",
["The Slave Pens"] = "Recinto de los Esclavos",
["The Spark of Imagination"] = "Cámaras de la Invención",
["The Steamvault"] = "La Cámara de Vapor",
["The Stockade"] = "Las Mazmorras",
["The Storm Peaks"] = "Las Cumbres Tormentosas",
["The Temple of Atal'Hakkar"] = "El Templo de Atal'Hakkar",
["The Underbog"] = "La Sotiénaga",
["The Veiled Sea"] = "Mar de la Bruma",
["The Violet Hold"] = "El Bastión Violeta",
["Thousand Needles"] = "Las Mil Agujas",
["Thunder Bluff"] = "Cima del Trueno",
Tirisfal = "Tirisfal",
["Tirisfal Glades"] = "Claros de Tirisfal",
["Trial of the Champion"] = "Pueba del Campeon",
["Trial of the Crusader"] = "Prueba del Cruzado",
["Twisting Nether"] = "El Vacío Abisal",
Uldaman = "Uldaman",
Ulduar = "Ulduar",
Undercity = "Entrañas",
["Un'Goro Crater"] = "Cráter de Un'Goro",
["Upper Blackrock Spire"] = "Cumbre de Roca Negra",
["Utgarde Keep"] = "Fortaleza de Utgarde",
["Utgarde Pinnacle"] = "Pináculo de Utgarde",
["Vault of Archavon"] = "La Cámara de Archavon",
["Vortex Pinnacle"] = "Cumbre del Vórtice",
["Wailing Caverns"] = "Cuevas de los Lamentos",
["Warsong Gulch"] = "Garganta Grito de Guerra",
["Western Plaguelands"] = "Tierras de la Peste del Oeste",
Westfall = "Páramos de Poniente",
Wetlands = "Los Humedales",
Wintergrasp = "Conquista del Invierno",
Winterspring = "Cuna del Invierno",
["Wyrmrest Temple"] = "Templo del Reposo del Dragón",
Zangarmarsh = "Marisma de Zangar",
["Zul'Aman"] = "Zul'Aman",
["Zul'Drak"] = "Zul'Drak",
["Zul'Farrak"] = "Zul'Farrak",
["Zul'Gurub"] = "Zul'Gurub",
}
elseif GAME_LOCALE == "ruRU" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "Ан'кахет: Старое Королевство",
["Ahn'Qiraj"] = "Ан'Кираж",
["Alliance Base"] = "База Альянса",
["Alterac Mountains"] = "Альтеракские горы",
["Alterac Valley"] = "Альтеракская долина",
["Amani Pass"] = "Перевал Амани",
["Arathi Basin"] = "Низина Арати",
["Arathi Highlands"] = "Нагорье Арати",
Armory = "Оружейная",
Ashenvale = "Ясеневый лес",
Auberdine = "Аубердин",
["Auchenai Crypts"] = "Аукенайские гробницы",
Auchindoun = "Аукиндон",
Azeroth = "Азерот",
["Azjol-Nerub"] = "Азжол-Неруб",
Azshara = "Азшара",
["Azuremyst Isle"] = "Остров Лазурной Дымки",
Badlands = "Бесплодные земли",
["Bash'ir Landing"] = "Лагерь Баш'ира",
["Blackfathom Deeps"] = "Непроглядная Пучина",
["Blackrock Depths"] = "Глубины Черной горы",
["Blackrock Mountain"] = "Черная гора",
["Blackrock Spire"] = "Пик Черной горы",
["Black Temple"] = "Черный храм",
["Blackwind Lake"] = "Озеро Черного Ветра",
["Blackwing Lair"] = "Логово Крыла Тьмы",
["Blade's Edge Arena"] = "Арена Острогорья",
["Blade's Edge Mountains"] = "Острогорье",
["Blasted Lands"] = "Выжженные земли",
["Bloodmyst Isle"] = "Остров Кровавой Дымки",
["Booty Bay"] = "Пиратская Бухта",
["Borean Tundra"] = "Борейская тундра",
["Burning Steppes"] = "Пылающие степи",
Cathedral = "Собор",
["Caverns of Time"] = "Пещеры Времени",
["Champions' Hall"] = "Зал Защитника",
["Coilfang Reservoir"] = "Резервуар Кривого Клыка",
Coldarra = "Хладарра",
["Cosmic map"] = "Карта Вселенной",
["Crystalsong Forest"] = "Лес Хрустальной Песни",
["Crystal Spine"] = "Хрустальное поле",
Dalaran = "Даларан",
["Dalaran Arena"] = "Арена Даларана",
["Dalaran Sewers"] = "Арена Даларана",
["Darkmoon Faire"] = "Ярмарка Новолуния",
Darkshore = "Темные берега",
Darnassus = "Дарнас",
["Deadwind Pass"] = "Перевал Мертвого Ветра",
["Deeprun Tram"] = "Подземный поезд",
Desolace = "Пустоши",
["Dire Maul"] = "Забытый Город",
["Dire Maul (East)"] = "Забытый Город: Восток",
["Dire Maul (North)"] = "Забытый Город: Север",
["Dire Maul (West)"] = "Забытый Город: Запад",
Dragonblight = "Драконий Погост",
["Drak'Tharon Keep"] = "Крепость Драк'Тарон",
["Dun Morogh"] = "Дун Морог",
Durotar = "Дуротар",
Duskwood = "Сумеречный лес",
["Dustwallow Marsh"] = "Пылевые топи",
["Eastern Kingdoms"] = "Восточные королевства",
["Eastern Plaguelands"] = "Восточные Чумные земли",
["Elwynn Forest"] = "Элвиннский лес",
Everlook = "Круговзор",
["Eversong Woods"] = "Леса Вечной Песни",
["Eye of the Storm"] = "Око Бури",
Felwood = "Оскверненный лес",
Feralas = "Фералас",
["Forge Camp: Terror"] = "Лагерь Легиона: Ужас",
["Forge Camp: Wrath"] = "Лагерь Легиона: Гнев",
["Frostwyrm Lair"] = "Логово Ледяного змея",
["Furywing's Perch"] = "Гнездовье Ярокрыла",
Gadgetzan = "Прибамбасск",
["Gates of Ahn'Qiraj"] = "Врата Ан'Киража",
Ghostlands = "Призрачные земли",
Gnomeregan = "Гномреган",
Graveyard = "Кладбище",
["Grizzly Hills"] = "Седые холмы",
["Grom'gol Base Camp"] = "Лагерь Гром'гол",
["Gruul's Lair"] = "Логово Груула",
Gundrak = "Гундрак",
["Hall of Champions"] = "Чертог Защитников",
["Hall of Legends"] = "Зал Легенд",
["Halls of Lightning"] = "Чертоги Молний",
["Halls of Reflection"] = "Залы Отражений",
["Halls of Stone"] = "Чертоги Камня",
["Hellfire Citadel"] = "Цитадель Адского Пламени",
["Hellfire Peninsula"] = "Полуостров Адского Пламени",
["Hellfire Ramparts"] = "Бастионы Адского Пламени",
["Hillsbrad Foothills"] = "Предгорья Хилсбрада",
["Horde Encampment"] = "Стоянка Орды",
["Howling Fjord"] = "Ревущий фьорд",
["Hrothgar's Landing"] = "Лагерь Хротгара",
Hyjal = "Хиджал",
["Hyjal Summit"] = "Вершина Хиджала",
Icecrown = "Ледяная Корона",
["Icecrown Citadel"] = "Цитадель Ледяной Короны",
["Insidion's Perch"] = "Гнездо Инсидиона",
Ironforge = "Стальгорн",
["Isle of Conquest"] = "Остров Завоеваний",
["Isle of Quel'Danas"] = "Остров Кель'Данас",
Kalimdor = "Калимдор",
Karazhan = "Каражан",
["Krasus' Landing"] = "Площадка Краса",
Library = "Библиотека",
["Loch Modan"] = "Лок Модан",
["Lower Blackrock Spire"] = "Нижний ярус Черной горы",
["Magisters' Terrace"] = "Терраса Магистров",
["Magtheridon's Lair"] = "Логово Магтеридона",
["Mana-Tombs"] = "Гробницы Маны",
Maraudon = "Мародон",
["Marshlight Lake"] = "Озеро Болотных Огоньков",
["Menethil Harbor"] = "Гавань Менетилов",
["Molten Core"] = "Огненные Недра",
Moonglade = "Лунная поляна",
Mulgore = "Мулгор",
Nagrand = "Награнд",
["Nagrand Arena"] = "Арена Награнда",
Naxxramas = "Наксрамас",
Netherstorm = "Пустоверть",
["Night Elf Village"] = "Деревня ночных эльфов",
Northrend = "Нордскол",
["Obsidia's Perch"] = "Гнездо Обсидии",
["Ogri'la"] = "Огри'ла",
["Old Hillsbrad Foothills"] = "Старые предгорья Хилсбрада",
["Old Stratholme"] = "Старый Стратхольм",
["Onyxia's Lair"] = "Логово Ониксии",
Orgrimmar = "Оргриммар",
Outland = "Запределье",
["Pit of Saron"] = "Яма Сарона",
["Plaguelands: The Scarlet Enclave"] = "Чумные земли: Анклав Алого ордена",
Plaguewood = "Проклятый лес",
["Quel'thalas"] = "Кель'Талас",
["Ragefire Chasm"] = "Огненная пропасть",
Ratchet = "Кабестан",
["Razorfen Downs"] = "Курганы Иглошкурых",
["Razorfen Kraul"] = "Лабиринты Иглошкурых",
["Redridge Mountains"] = "Красногорье",
["Ring of Observance"] = "Ритуальный Круг",
["Rivendark's Perch"] = "Гнездо Чернокрыла",
["Ruins of Ahn'Qiraj"] = "Руины Ан'Киража",
["Ruins of Lordaeron"] = "Руины Лордерона",
["Scalebeard's Cave"] = "Пещера Чешуеборода",
["Scarlet Monastery"] = "Монастырь Алого ордена",
Scholomance = "Некроситет",
["Searing Gorge"] = "Тлеющее ущелье",
["Serpent Lake"] = "Змеиное озеро",
["Serpentshrine Cavern"] = "Змеиное святилище",
["Sethekk Halls"] = "Сетеккские залы",
["Shadowfang Keep"] = "Крепость Темного Клыка",
["Shadow Labyrinth"] = "Темный лабиринт",
["Shadowmoon Valley"] = "Долина Призрачной Луны",
["Shartuul's Transporter"] = "Транспортер Шартуула",
Shattrath = "Шаттрат",
["Shattrath City"] = "Шаттрат",
["Sholazar Basin"] = "Низина Шолазар",
Silithus = "Силитус",
["Silvermoon City"] = "Луносвет",
["Silverpine Forest"] = "Серебряный бор",
["Skyguard Outpost"] = "Застава Стражи Небес",
["Skysong Lake"] = "Озеро Небесной Песни",
["Sporewind Lake"] = "Озеро Спороветра",
Stonard = "Каменор",
["Stonetalon Mountains"] = "Когтистые горы",
Stormwind = "Штормград",
["Stormwind City"] = "Штормград",
["Strand of the Ancients"] = "Берег Древних",
["Stranglethorn Vale"] = "Тернистая долина",
Stratholme = "Стратхольм",
["Sunken Temple"] = "Затонувший храм",
["Sunwell Plateau"] = "Плато Солнечного Колодца",
["Swamp of Sorrows"] = "Болото Печали",
Tanaris = "Танарис",
Teldrassil = "Тельдрассил",
["Tempest Keep"] = "Крепость Бурь",
["Temple of Ahn'Qiraj"] = "Храм Ан'Кираж",
["Terokkar Forest"] = "Лес Тероккар",
["Terokk's Rest"] = "Покой Терокка",
["The Arachnid Quarter"] = "Паучий квартал",
["The Arcatraz"] = "Аркатрац",
["The Argent Coliseum"] = "Испытание крестоносца",
["The Barrens"] = "Степи",
["The Black Morass"] = "Черные топи",
["The Blood Furnace"] = "Кузня Крови",
["The Bone Wastes"] = "Костяные пустоши",
["The Botanica"] = "Ботаника",
["The Construct Quarter"] = "Квартал Мерзости",
["The Culling of Stratholme"] = "Очищение Стратхольма",
["The Dark Portal"] = "Темный портал",
["The Deadmines"] = "Мертвые копи",
["The Descent into Madness"] = "Провал Безумия",
["The Exodar"] = "Экзодар",
["The Eye"] = "Око",
["The Eye of Eternity"] = "Око Вечности",
["The Forbidding Sea"] = "Зловещее море",
["The Forge of Souls"] = "Кузня Душ",
["The Frozen Halls"] = "Ледяные залы", -- Needs review
["The Frozen Sea"] = "Ледяное море",
["The Great Sea"] = "Великое море",
["The Halls of Winter"] = "Залы Зимы", -- Needs review
["The Hinterlands"] = "Внутренние земли",
["The Mechanar"] = "Механар",
["The Military Quarter"] = "Военный квартал",
["The Nexus"] = "Нексус",
["The North Sea"] = "Северное море",
["The Obsidian Sanctum"] = "Обсидиановое святилище",
["The Oculus"] = "Окулус",
["The Plague Quarter"] = "Чумной квартал",
["The Prison of Yogg-Saron"] = "Темница Йогг-Сарона", -- Needs review
["Theramore Isle"] = "Остров Терамор",
["The Ring of Valor"] = "Круг Доблести",
["The Ruby Sanctum"] = "Рубиновое святилище",
["The Scarlet Enclave"] = "Анклав Алого ордена", -- Needs review
["The Shattered Halls"] = "Разрушенные залы",
["The Slave Pens"] = "Узилище",
["The Spark of Imagination"] = "Искра Воображения",
["The Steamvault"] = "Паровое подземелье",
["The Stockade"] = "Тюрьма",
["The Storm Peaks"] = "Грозовая Гряда",
["The Temple of Atal'Hakkar"] = "Храм Атал'Хаккара",
["The Underbog"] = "Нижетопь",
["The Veiled Sea"] = "Сокрытое Море",
["The Violet Hold"] = "Аметистовая крепость",
["Thousand Needles"] = "Тысяча Игл",
["Thunder Bluff"] = "Громовой Утес",
Tirisfal = "Тирисфальские леса",
["Tirisfal Glades"] = "Тирисфальские леса",
["Trial of the Champion"] = "Испытание чемпиона",
["Trial of the Crusader"] = "Испытание крестоносца",
["Twisting Nether"] = "Круговерть Пустоты",
Uldaman = "Ульдаман",
Ulduar = "Ульдуар",
Undercity = "Подгород",
["Un'Goro Crater"] = "Кратер Ун'Горо",
["Upper Blackrock Spire"] = "Верхний ярус Черной горы",
["Utgarde Keep"] = "Крепость Утгард",
["Utgarde Pinnacle"] = "Вершина Утгард",
["Vault of Archavon"] = "Склеп Аркавона",
["Vortex Pinnacle"] = "Нагорье Смерчей",
["Wailing Caverns"] = "Пещеры Стенаний",
["Warsong Gulch"] = "Ущелье Песни Войны",
["Western Plaguelands"] = "Западные Чумные земли",
Westfall = "Западный Край",
Wetlands = "Болотина",
Wintergrasp = "Озеро Ледяных Оков",
Winterspring = "Зимние Ключи",
["Wyrmrest Temple"] = "Храм Драконьего Покоя",
Zangarmarsh = "Зангартопь",
["Zul'Aman"] = "Зул'Аман",
["Zul'Drak"] = "Зул'Драк",
["Zul'Farrak"] = "Зул'Фаррак",
["Zul'Gurub"] = "Зул'Гуруб",
}
elseif GAME_LOCALE == "zhCN" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "安卡雷:古代王国",
["Ahn'Qiraj"] = "安其拉",
["Alliance Base"] = "联盟基地",
["Alterac Mountains"] = "奥特兰克山脉",
["Alterac Valley"] = "奥特兰克山谷",
["Amani Pass"] = "阿曼尼小径",
["Arathi Basin"] = "阿拉希盆地",
["Arathi Highlands"] = "阿拉希高地",
Armory = "军械库",
Ashenvale = "灰谷",
Auberdine = "奥伯丁",
["Auchenai Crypts"] = "奥金尼地穴",
Auchindoun = "奥金顿",
Azeroth = "艾泽拉斯",
["Azjol-Nerub"] = "艾卓-尼鲁布",
Azshara = "艾萨拉",
["Azuremyst Isle"] = "秘蓝岛",
Badlands = "荒芜之地",
["Bash'ir Landing"] = "巴什伊尔码头",
["Blackfathom Deeps"] = "黑暗深渊",
["Blackrock Depths"] = "黑石深渊",
["Blackrock Mountain"] = "黑石山",
["Blackrock Spire"] = "黑石塔",
["Black Temple"] = "黑暗神殿",
["Blackwind Lake"] = "黑风湖",
["Blackwing Lair"] = "黑翼之巢",
["Blade's Edge Arena"] = "刀锋山竞技场",
["Blade's Edge Mountains"] = "刀锋山",
["Blasted Lands"] = "诅咒之地",
["Bloodmyst Isle"] = "秘血岛",
["Booty Bay"] = "藏宝海湾",
["Borean Tundra"] = "北风苔原",
["Burning Steppes"] = "燃烧平原",
Cathedral = "教堂",
["Caverns of Time"] = "时光之穴",
["Champions' Hall"] = "勇士大厅",
["Coilfang Reservoir"] = "盘牙水库",
Coldarra = "考达拉",
["Cosmic map"] = "全部地图",
["Crystalsong Forest"] = "晶歌森林",
["Crystal Spine"] = "水晶之脊",
Dalaran = "达拉然",
["Dalaran Arena"] = "达拉然竞技场",
["Dalaran Sewers"] = "达拉然下水道",
["Darkmoon Faire"] = "暗月马戏团",
Darkshore = "黑海岸",
Darnassus = "达纳苏斯",
["Deadwind Pass"] = "逆风小径",
["Deeprun Tram"] = "矿道地铁",
Desolace = "凄凉之地",
["Dire Maul"] = "厄运之槌",
["Dire Maul (East)"] = "厄运之槌(东)",
["Dire Maul (North)"] = "厄运之槌(北)",
["Dire Maul (West)"] = "厄运之槌(西)",
Dragonblight = "龙骨荒野",
["Drak'Tharon Keep"] = "达克萨隆要塞",
["Dun Morogh"] = "丹莫罗",
Durotar = "杜隆塔尔",
Duskwood = "暮色森林",
["Dustwallow Marsh"] = "尘泥沼泽",
["Eastern Kingdoms"] = "东部王国",
["Eastern Plaguelands"] = "东瘟疫之地",
["Elwynn Forest"] = "艾尔文森林",
Everlook = "永望镇",
["Eversong Woods"] = "永歌森林",
["Eye of the Storm"] = "风暴之眼",
Felwood = "费伍德森林",
Feralas = "菲拉斯",
["Forge Camp: Terror"] = "铸魔营地:恐怖",
["Forge Camp: Wrath"] = "铸魔营地:天罚",
["Frostwyrm Lair"] = "冰霜巨龙的巢穴",
["Furywing's Perch"] = "弗雷文栖木",
Gadgetzan = "加基森",
["Gates of Ahn'Qiraj"] = "安其拉之门",
Ghostlands = "幽魂之地",
Gnomeregan = "诺莫瑞根",
Graveyard = "墓地",
["Grizzly Hills"] = "灰熊丘陵",
["Grom'gol Base Camp"] = "格罗姆高营地",
["Gruul's Lair"] = "格鲁尔的巢穴",
Gundrak = "古达克",
["Hall of Champions"] = "勇士大厅",
["Hall of Legends"] = "传说大厅",
["Halls of Lightning"] = "闪电大厅",
["Halls of Reflection"] = "映像大厅",
["Halls of Stone"] = "岩石大厅",
["Hellfire Citadel"] = "地狱火堡垒",
["Hellfire Peninsula"] = "地狱火半岛",
["Hellfire Ramparts"] = "地狱火城墙",
["Hillsbrad Foothills"] = "希尔斯布莱德丘陵",
["Horde Encampment"] = "部落营地",
["Howling Fjord"] = "嚎风峡湾",
["Hrothgar's Landing"] = "洛斯加尔登陆点",
Hyjal = "海加尔山",
["Hyjal Summit"] = "海加尔峰",
Icecrown = "冰冠冰川",
["Icecrown Citadel"] = "冰冠堡垒",
["Insidion's Perch"] = "因斯迪安栖木",
Ironforge = "铁炉堡",
["Isle of Conquest"] = "征服之岛",
["Isle of Quel'Danas"] = "奎尔丹纳斯岛",
Kalimdor = "卡利姆多",
Karazhan = "卡拉赞",
["Krasus' Landing"] = "克拉苏斯平台",
Library = "图书馆",
["Loch Modan"] = "洛克莫丹",
["Lower Blackrock Spire"] = "下层黑石塔",
["Magisters' Terrace"] = "魔导师平台",
["Magtheridon's Lair"] = "玛瑟里顿的巢穴",
["Mana-Tombs"] = "法力陵墓",
Maraudon = "玛拉顿",
["Marshlight Lake"] = "沼光湖",
["Menethil Harbor"] = "米奈希尔港",
["Molten Core"] = "熔火之心",
Moonglade = "月光林地",
Mulgore = "莫高雷",
Nagrand = "纳格兰",
["Nagrand Arena"] = "纳格兰竞技场",
Naxxramas = "纳克萨玛斯",
Netherstorm = "虚空风暴",
["Night Elf Village"] = "暗夜精灵村庄",
Northrend = "诺森德",
["Obsidia's Perch"] = "欧比斯迪栖木",
["Ogri'la"] = "奥格瑞拉",
["Old Hillsbrad Foothills"] = "旧希尔斯布莱德丘陵",
["Old Stratholme"] = "旧斯坦索姆",
["Onyxia's Lair"] = "奥妮克希亚的巢穴",
Orgrimmar = "奥格瑞玛",
Outland = "外域",
["Pit of Saron"] = "萨隆矿坑",
["Plaguelands: The Scarlet Enclave"] = "东瘟疫之地:血色领地",
Plaguewood = "病木林",
["Quel'thalas"] = "奎尔萨拉斯",
["Ragefire Chasm"] = "怒焰裂谷",
Ratchet = "棘齿城",
["Razorfen Downs"] = "剃刀高地",
["Razorfen Kraul"] = "剃刀沼泽",
["Redridge Mountains"] = "赤脊山",
["Ring of Observance"] = "仪式广场",
["Rivendark's Perch"] = "雷文达克栖木",
["Ruins of Ahn'Qiraj"] = "安其拉废墟",
["Ruins of Lordaeron"] = "洛丹伦废墟",
["Scalebeard's Cave"] = "鳞须海龟洞穴",
["Scarlet Monastery"] = "血色修道院",
Scholomance = "通灵学院",
["Searing Gorge"] = "灼热峡谷",
["Serpent Lake"] = "毒蛇湖",
["Serpentshrine Cavern"] = "毒蛇神殿",
["Sethekk Halls"] = "塞泰克大厅",
["Shadowfang Keep"] = "影牙城堡",
["Shadow Labyrinth"] = "暗影迷宫",
["Shadowmoon Valley"] = "影月谷",
["Shartuul's Transporter"] = "沙图尔的传送器",
Shattrath = "沙塔斯",
["Shattrath City"] = "沙塔斯城",
["Sholazar Basin"] = "索拉查盆地",
Silithus = "希利苏斯",
["Silvermoon City"] = "银月城",
["Silverpine Forest"] = "银松森林",
["Skyguard Outpost"] = "天空卫队哨站",
["Skysong Lake"] = "天歌湖",
["Sporewind Lake"] = "孢子湖",
Stonard = "斯通纳德",
["Stonetalon Mountains"] = "石爪山脉",
Stormwind = "暴风城",
["Stormwind City"] = "暴风城",
["Strand of the Ancients"] = "远古海滩",
["Stranglethorn Vale"] = "荆棘谷",
Stratholme = "斯坦索姆",
["Sunken Temple"] = "沉没的神庙",
["Sunwell Plateau"] = "太阳之井高地",
["Swamp of Sorrows"] = "悲伤沼泽",
Tanaris = "塔纳利斯",
Teldrassil = "泰达希尔",
["Tempest Keep"] = "风暴要塞",
["Temple of Ahn'Qiraj"] = "安其拉神殿",
["Terokkar Forest"] = "泰罗卡森林",
["Terokk's Rest"] = "泰罗克之墓",
["The Arachnid Quarter"] = "蜘蛛区",
["The Arcatraz"] = "禁魔监狱",
["The Argent Coliseum"] = "银色试炼场", -- Needs review
["The Barrens"] = "贫瘠之地",
["The Black Morass"] = "黑色沼泽",
["The Blood Furnace"] = "鲜血熔炉",
["The Bone Wastes"] = "白骨荒野",
["The Botanica"] = "生态船",
["The Construct Quarter"] = "构造区",
["The Culling of Stratholme"] = "净化斯坦索姆",
["The Dark Portal"] = "黑暗之门",
["The Deadmines"] = "死亡矿井",
["The Descent into Madness"] = "疯狂阶梯",
["The Exodar"] = "埃索达",
["The Eye"] = "风暴要塞",
["The Eye of Eternity"] = "永恒之眼",
["The Forbidding Sea"] = "禁忌之海",
["The Forge of Souls"] = "灵魂洪炉",
["The Frozen Halls"] = "The Frozen Halls", -- Needs review
["The Frozen Sea"] = "冰冻之海",
["The Great Sea"] = "无尽之海",
["The Halls of Winter"] = "寒冬之厅",
["The Hinterlands"] = "辛特兰",
["The Mechanar"] = "能源舰",
["The Military Quarter"] = "军事区",
["The Nexus"] = "魔枢",
["The North Sea"] = "北海",
["The Obsidian Sanctum"] = "黑曜石圣殿",
["The Oculus"] = "魔环",
["The Plague Quarter"] = "瘟疫区",
["The Prison of Yogg-Saron"] = "尤格-萨隆的监狱",
["Theramore Isle"] = "塞拉摩岛",
["The Ring of Valor"] = "勇气竞技场",
["The Ruby Sanctum"] = "The Ruby Sanctum", -- Needs review
["The Scarlet Enclave"] = "血色领地",
["The Shattered Halls"] = "破碎大厅",
["The Slave Pens"] = "奴隶围栏",
["The Spark of Imagination"] = "思想火花",
["The Steamvault"] = "蒸汽地窟",
["The Stockade"] = "监狱",
["The Storm Peaks"] = "风暴峭壁",
["The Temple of Atal'Hakkar"] = "阿塔哈卡神庙",
["The Underbog"] = "幽暗沼泽",
["The Veiled Sea"] = "迷雾之海",
["The Violet Hold"] = "紫罗兰监狱",
["Thousand Needles"] = "千针石林",
["Thunder Bluff"] = "雷霆崖",
Tirisfal = "提里斯法林地",
["Tirisfal Glades"] = "提瑞斯法林地",
["Trial of the Champion"] = "冠军的试炼",
["Trial of the Crusader"] = "十字军的试炼",
["Twisting Nether"] = "扭曲虚空",
Uldaman = "奥达曼",
Ulduar = "奥杜尔",
Undercity = "幽暗城",
["Un'Goro Crater"] = "安戈洛环形山",
["Upper Blackrock Spire"] = "上层黑石塔",
["Utgarde Keep"] = "乌特加德城堡",
["Utgarde Pinnacle"] = "乌特加德之巅",
["Vault of Archavon"] = "阿尔卡冯的宝库",
["Vortex Pinnacle"] = "漩涡峰",
["Wailing Caverns"] = "哀嚎洞穴",
["Warsong Gulch"] = "战歌峡谷",
["Western Plaguelands"] = "西瘟疫之地",
Westfall = "西部荒野",
Wetlands = "湿地",
Wintergrasp = "冬拥湖",
Winterspring = "冬泉谷",
["Wyrmrest Temple"] = "龙眠神殿",
Zangarmarsh = "赞加沼泽",
["Zul'Aman"] = "祖阿曼",
["Zul'Drak"] = "祖达克",
["Zul'Farrak"] = "祖尔法拉克",
["Zul'Gurub"] = "祖尔格拉布",
}
elseif GAME_LOCALE == "zhTW" then
lib:SetCurrentTranslations {
["Ahn'kahet: The Old Kingdom"] = "安卡罕特:古王國",
["Ahn'Qiraj"] = "安其拉",
["Alliance Base"] = "聯盟營地",
["Alterac Mountains"] = "奧特蘭克山脈",
["Alterac Valley"] = "奧特蘭克山谷",
["Amani Pass"] = "阿曼尼小俓",
["Arathi Basin"] = "阿拉希盆地",
["Arathi Highlands"] = "阿拉希高地",
Armory = "軍械庫",
Ashenvale = "梣谷",
Auberdine = "奧伯丁",
["Auchenai Crypts"] = "奧奇奈地穴",
Auchindoun = "奧齊頓",
Azeroth = "艾澤拉斯",
["Azjol-Nerub"] = "阿茲歐-奈幽",
Azshara = "艾薩拉",
["Azuremyst Isle"] = "藍謎島",
Badlands = "荒蕪之地",
["Bash'ir Landing"] = "貝許爾平臺",
["Blackfathom Deeps"] = "黑暗深淵",
["Blackrock Depths"] = "黑石深淵",
["Blackrock Mountain"] = "黑石山",
["Blackrock Spire"] = "黑石塔",
["Black Temple"] = "黑暗神廟",
["Blackwind Lake"] = "黑風湖",
["Blackwing Lair"] = "黑翼之巢",
["Blade's Edge Arena"] = "劍刃競技場",
["Blade's Edge Mountains"] = "劍刃山脈",
["Blasted Lands"] = "詛咒之地",
["Bloodmyst Isle"] = "血謎島",
["Booty Bay"] = "藏寶海灣",
["Borean Tundra"] = "北風凍原",
["Burning Steppes"] = "燃燒平原",
Cathedral = "教堂",
["Caverns of Time"] = "時光之穴",
["Champions' Hall"] = "勇士大廳",
["Coilfang Reservoir"] = "盤牙洞穴",
Coldarra = "凜懼島",
["Cosmic map"] = "宇宙地圖",
["Crystalsong Forest"] = "水晶之歌森林",
["Crystal Spine"] = "水晶背脊",
Dalaran = "達拉然",
["Dalaran Arena"] = "達拉然競技場",
["Dalaran Sewers"] = "達拉然下水道",
["Darkmoon Faire"] = "暗月馬戲團",
Darkshore = "黑海岸",
Darnassus = "達納蘇斯",
["Deadwind Pass"] = "逆風小徑",
["Deeprun Tram"] = "礦道地鐵",
Desolace = "淒涼之地",
["Dire Maul"] = "厄運之槌",
["Dire Maul (East)"] = "厄運之槌 - 東",
["Dire Maul (North)"] = "厄運之槌 - 北",
["Dire Maul (West)"] = "厄運之槌 - 西",
Dragonblight = "龍骨荒野",
["Drak'Tharon Keep"] = "德拉克薩隆要塞",
["Dun Morogh"] = "丹莫洛",
Durotar = "杜洛塔",
Duskwood = "暮色森林",
["Dustwallow Marsh"] = "塵泥沼澤",
["Eastern Kingdoms"] = "東部王國",
["Eastern Plaguelands"] = "東瘟疫之地",
["Elwynn Forest"] = "艾爾文森林",
Everlook = "永望鎮",
["Eversong Woods"] = "永歌森林",
["Eye of the Storm"] = "暴風之眼",
Felwood = "費伍德森林",
Feralas = "菲拉斯",
["Forge Camp: Terror"] = "煉冶場:驚駭",
["Forge Camp: Wrath"] = "煉冶場:憤怒",
["Frostwyrm Lair"] = "冰霜巨龍的巢穴",
["Furywing's Perch"] = "狂怒之翼棲所",
Gadgetzan = "加基森",
["Gates of Ahn'Qiraj"] = "安其拉之門",
Ghostlands = "鬼魂之地",
Gnomeregan = "諾姆瑞根",
Graveyard = "墓地",
["Grizzly Hills"] = "灰白之丘",
["Grom'gol Base Camp"] = "格羅姆高營地",
["Gruul's Lair"] = "戈魯爾之巢",
Gundrak = "剛德拉克",
["Hall of Champions"] = "勇士大廳",
["Hall of Legends"] = "傳說大廳",
["Halls of Lightning"] = "雷光大廳",
["Halls of Reflection"] = "倒影大廳",
["Halls of Stone"] = "石之大廳",
["Hellfire Citadel"] = "地獄火堡壘",
["Hellfire Peninsula"] = "地獄火半島",
["Hellfire Ramparts"] = "地獄火壁壘",
["Hillsbrad Foothills"] = "希爾斯布萊德丘陵",
["Horde Encampment"] = "部落營地",
["Howling Fjord"] = "凜風峽灣",
["Hrothgar's Landing"] = "赫魯斯加臺地",
Hyjal = "海加爾山",
["Hyjal Summit"] = "海加爾山",
Icecrown = "寒冰皇冠",
["Icecrown Citadel"] = "冰冠城塞",
["Insidion's Perch"] = "印希迪恩棲所",
Ironforge = "鐵爐堡",
["Isle of Conquest"] = "征服之島",
["Isle of Quel'Danas"] = "奎爾達納斯之島",
Kalimdor = "卡林多",
Karazhan = "卡拉贊",
["Krasus' Landing"] = "卡薩斯平臺",
Library = "圖書館",
["Loch Modan"] = "洛克莫丹",
["Lower Blackrock Spire"] = "黑石塔",
["Magisters' Terrace"] = "博學者殿堂",
["Magtheridon's Lair"] = "瑪瑟里頓的巢穴",
["Mana-Tombs"] = "法力墓地",
Maraudon = "瑪拉頓",
["Marshlight Lake"] = "沼澤光之湖",
["Menethil Harbor"] = "米奈希爾港",
["Molten Core"] = "熔火之心",
Moonglade = "月光林地",
Mulgore = "莫高雷",
Nagrand = "納葛蘭",
["Nagrand Arena"] = "納葛蘭競技場",
Naxxramas = "納克薩瑪斯",
Netherstorm = "虛空風暴",
["Night Elf Village"] = "夜精靈村",
Northrend = "北裂境",
["Obsidia's Perch"] = "歐比希迪亞棲所",
["Ogri'la"] = "歐格利拉",
["Old Hillsbrad Foothills"] = "希爾斯布萊德丘陵舊址",
["Old Stratholme"] = "舊斯坦索姆",
["Onyxia's Lair"] = "奧妮克希亞的巢穴",
Orgrimmar = "奧格瑪",
Outland = "外域",
["Pit of Saron"] = "薩倫之淵",
["Plaguelands: The Scarlet Enclave"] = "東瘟疫之地: 血色領區",
Plaguewood = "病木林",
["Quel'thalas"] = "奎爾薩拉斯",
["Ragefire Chasm"] = "怒焰裂谷",
Ratchet = "棘齒城",
["Razorfen Downs"] = "剃刀高地",
["Razorfen Kraul"] = "剃刀沼澤",
["Redridge Mountains"] = "赤脊山",
["Ring of Observance"] = "儀式競技場",
["Rivendark's Perch"] = "瑞文達科棲所",
["Ruins of Ahn'Qiraj"] = "安其拉廢墟",
["Ruins of Lordaeron"] = "羅德隆廢墟",
["Scalebeard's Cave"] = "鱗鬚洞穴",
["Scarlet Monastery"] = "血色修道院",
Scholomance = "通靈學院",
["Searing Gorge"] = "灼熱峽谷",
["Serpent Lake"] = "毒蛇之湖",
["Serpentshrine Cavern"] = "毒蛇神殿洞穴",
["Sethekk Halls"] = "塞司克大廳",
["Shadowfang Keep"] = "影牙城堡",
["Shadow Labyrinth"] = "暗影迷宮",
["Shadowmoon Valley"] = "影月谷",
["Shartuul's Transporter"] = "夏圖歐的傳送門",
Shattrath = "撒塔斯城",
["Shattrath City"] = "撒塔斯城",
["Sholazar Basin"] = "休拉薩盆地",
Silithus = "希利蘇斯",
["Silvermoon City"] = "銀月城",
["Silverpine Forest"] = "銀松森林",
["Skyguard Outpost"] = "禦天者崗哨",
["Skysong Lake"] = "天歌湖",
["Sporewind Lake"] = "孢子風之湖",
Stonard = "斯通納德",
["Stonetalon Mountains"] = "石爪山脈",
Stormwind = "暴風城",
["Stormwind City"] = "暴風城",
["Strand of the Ancients"] = "遠祖灘頭",
["Stranglethorn Vale"] = "荊棘谷",
Stratholme = "斯坦索姆",
["Sunken Temple"] = "沉沒的神廟",
["Sunwell Plateau"] = "太陽之井高地",
["Swamp of Sorrows"] = "悲傷沼澤",
Tanaris = "塔納利斯",
Teldrassil = "泰達希爾",
["Tempest Keep"] = "風暴要塞",
["Temple of Ahn'Qiraj"] = "安其拉神廟",
["Terokkar Forest"] = "泰洛卡森林",
["Terokk's Rest"] = "泰洛克之墓",
["The Arachnid Quarter"] = "蜘蛛區",
["The Arcatraz"] = "亞克崔茲",
["The Argent Coliseum"] = "銀白大競技場",
["The Barrens"] = "貧瘠之地",
["The Black Morass"] = "黑色沼澤",
["The Blood Furnace"] = "血熔爐",
["The Bone Wastes"] = "白骨荒野",
["The Botanica"] = "波塔尼卡",
["The Construct Quarter"] = "傀儡區",
["The Culling of Stratholme"] = "斯坦索姆的抉擇",
["The Dark Portal"] = "黑暗之門",
["The Deadmines"] = "死亡礦坑",
["The Descent into Madness"] = "驟狂斜廊",
["The Exodar"] = "艾克索達",
["The Eye"] = "風暴要塞",
["The Eye of Eternity"] = "永恆之眼",
["The Forbidding Sea"] = "禁忌之海",
["The Forge of Souls"] = "眾魂熔爐",
["The Frozen Halls"] = "冰封大廳",
["The Frozen Sea"] = "冰凍之海",
["The Great Sea"] = "無盡之海",
["The Halls of Winter"] = "凜冬之廳",
["The Hinterlands"] = "辛特蘭",
["The Mechanar"] = "麥克納爾",
["The Military Quarter"] = "軍事區",
["The Nexus"] = "奧核之心",
["The North Sea"] = "北海",
["The Obsidian Sanctum"] = "黑曜聖所",
["The Oculus"] = "奧核之眼",
["The Plague Quarter"] = "瘟疫區",
["The Prison of Yogg-Saron"] = "尤格薩倫之獄",
["Theramore Isle"] = "塞拉摩島",
["The Ring of Valor"] = "勇武之環",
["The Ruby Sanctum"] = "晶紅聖所",
["The Scarlet Enclave"] = "血色領區",
["The Shattered Halls"] = "破碎大廳",
["The Slave Pens"] = "奴隸監獄",
["The Spark of Imagination"] = "創思之廳",
["The Steamvault"] = "蒸汽洞窟",
["The Stockade"] = "監獄",
["The Storm Peaks"] = "風暴群山",
["The Temple of Atal'Hakkar"] = "阿塔哈卡神廟",
["The Underbog"] = "深幽泥沼",
["The Veiled Sea"] = "迷霧之海",
["The Violet Hold"] = "紫羅蘭堡",
["Thousand Needles"] = "千針石林",
["Thunder Bluff"] = "雷霆崖",
Tirisfal = "提里斯法林地",
["Tirisfal Glades"] = "提里斯法林地",
["Trial of the Champion"] = "勇士試煉",
["Trial of the Crusader"] = "十字軍試煉",
["Twisting Nether"] = "扭曲虛空",
Uldaman = "奧達曼",
Ulduar = "奧杜亞",
Undercity = "幽暗城",
["Un'Goro Crater"] = "安戈洛環形山",
["Upper Blackrock Spire"] = "黑石塔上層",
["Utgarde Keep"] = "俄特加德要塞",
["Utgarde Pinnacle"] = "俄特加德之巔",
["Vault of Archavon"] = "亞夏梵穹殿",
["Vortex Pinnacle"] = "漩渦尖塔",
["Wailing Caverns"] = "哀嚎洞穴",
["Warsong Gulch"] = "戰歌峽谷",
["Western Plaguelands"] = "西瘟疫之地",
Westfall = "西部荒野",
Wetlands = "濕地",
Wintergrasp = "冬握湖",
Winterspring = "冬泉谷",
["Wyrmrest Temple"] = "龍眠神殿",
Zangarmarsh = "贊格沼澤",
["Zul'Aman"] = "祖阿曼",
["Zul'Drak"] = "祖爾德拉克",
["Zul'Farrak"] = "祖爾法拉克",
["Zul'Gurub"] = "祖爾格拉布",
}
 
else
error(("%s: Locale %q not supported"):format(MAJOR_VERSION, GAME_LOCALE))
end
trunk/Libs/LibBabble-Zone-3.0/lib.xml New file
0,0 → 1,5
<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="LibBabble-3.0.lua" />
<Script file="LibBabble-Zone-3.0.lua" />
</Ui>
\ No newline at end of file
trunk/Libs/AceLocale-3.0/AceLocale-3.0.xml New file
0,0 → 1,4
<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="AceLocale-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceLocale-3.0/AceLocale-3.0.lua New file
0,0 → 1,136
--- **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 895 2009-12-06 16:28:55Z nevcairiel $
local MAJOR,MINOR = "AceLocale-3.0", 2
 
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 setmetatable, rawset, rawget = 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. Can only be set on the default locale.
-- @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)
 
if silent and not isDefault then
error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
end
 
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
-- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
-- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
-- opinion to remove this.
local gameLocale = GAME_LOCALE or gameLocale
 
if locale ~= gameLocale and not isDefault then
return -- nop, we don't need these translations
end
 
local app = AceLocale.apps[application]
 
if not app then
app = setmetatable({}, silent and readmetasilent or readmeta)
AceLocale.apps[application] = app
AceLocale.appnames[app] = application
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
trunk/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml New file
0,0 → 1,4
<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="CallbackHandler-1.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,240
--[[ $Id: CallbackHandler-1.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 5
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 next, xpcall, eh = ...
 
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 = ...
repeat
xpcall(call, eh)
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 = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("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, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
 
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[select('#', ...) + 1](events[eventname], eventname, ...)
 
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 select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId"
if type(self)~="table" and type(self)~="string" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
end
 
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(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 select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
 
 
for i=1,select("#",...) do
local self = select(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.
 
trunk/Libs/AceConsole-3.0/AceConsole-3.0.xml New file
0,0 → 1,4
<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="AceConsole-3.0.lua"/>
</Ui>
\ No newline at end of file
trunk/Libs/AceConsole-3.0/AceConsole-3.0.lua New file
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 878 2009-11-02 18:51:58Z 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 = _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: 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, select("#", ...) do
n=n+1
tmp[n] = tostring(select(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 = ...
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, select(2,...))
else
return Print(self, DEFAULT_CHAT_FRAME, ...)
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 = ...
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, format(select(2,...)))
else
return Print(self, DEFAULT_CHAT_FRAME, format(...))
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_"..command:upper()
 
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"] = "/"..command:lower()
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, ...)
elseif n==1 then
return nil, ...
else
return ...
end
end
 
 
--- Retreive one or more space-separated arguments from a string.
-- Treats quoted strings and itemlinks as non-spaced.
-- @param string 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
trunk/Libs/LibGroupTalents-1.0/LibGroupTalents-1.0.lua New file
0,0 → 1,1716
--[[
Name: LibGroupTalents-1.0
Revision: $Rev: 53 $
Author: Zek
Documentation: http://wowace.com/wiki/LibGroupTalents-1.0
SVN: svn://svn.wowace.com/wow/libgrouptalents-1-0/mainline/trunk
Description: Talent Library abstraction layer to provide easy interface to the lower level system
Dependancies: LibStub, CallbackHandler-1.0, LibTalentQuery-1.0
License: GPL v3
 
Purpose:
LibGroupTalents-1.0 is intended to do the following basic functions usually handled at the mod level.
 
- Maintain a raid wide table of talents, automatically updated on roster changes, notifying you on talent receipts.
- Provide easy access to talent queries (spec weight, spec name, specific talent presence)
- Monitor talent changes in players, and notify of changes (respec, talent swap, update after out of sight, level up)
- Monitor player roles, and notify of changes (melee, tank, healer, caster)
- Communicate directly with itself to other users to update talents via addon channel when possible
 
Notes:
The LibTalentQuery-1.0 dependancy must be included before LibGroupTalents-1.0 in any lib.xml or mod side TOC declarations.
 
Functions:
UnitHasTalent(unit, talentName[, group])-- Returns: Points spent in talent or nil
GUIDHasTalent(guid, talentName[, group])-- As UnitHasTalent
GetUnitTalentSpec(unitid[, group]) -- Returns: Dominant Tree, spent1, spent2, spent3
GetGUIDTalentSpec(guid[, group]) -- As GetUnitTalentSpec
GetUnitTalents(unit, refresh) -- Returns: Raw talent information in form of table of 3 strings of points spent. The refresh arg will force a re-query of the unit's talents
GetGUIDTalents(guid, refresh) -- As GetUnitTalents
GetUnitRole(unit) -- Returns one of: "melee", "caster", "healer", "tank"
GetGUIDRole(guid) -- As GetUnitRole
RefreshTalentsByUnit(unit) -- Force a refresh of talents for the specific unit
RefreshTalentsByGUID(guid) -- Force a refresh of talents for the specific player GUID
GetTreeNames(class) -- Returns: The three talent tree names for that class (Note: These return values are only valid after a player of that class has been inspected)
GetTreeIcons(class) -- Returns: The three talent tree icons for that class (Note: As above)
GetTalentCount() -- Returns: Talent info got, Talent info missing
GetTalentMissingNames() -- Returns: Comma delimited list of player names we're missing talents for
GetClassTalentInfo(class, talentName) -- Returns: Max Rank, Icon, Tab, Tier, Column, Tree Index
GetUnitStorageString(unit) -- Returns: An encoded data string containing talent information for the player which can be stored by mods to set in later sessions using SetStorageString()
GetGUIDStorageString(guid) -- As GetUnitStorageString
SetStorageString(talentString) -- Returns: true on success (applicable). Any second return value indicates the data was invalid and should not be kept
GetUnitGlyphs(unit[, group]) -- Returns: Up to 6 spell IDs for the currently assigned Glyphs (Note: For the moment, we can only see the glyphs of players running LibGroupTalents-1.0)
GetGUIDGlyphs(guid[, group]) -- As GetUnitGlyphs
UnitHasGlyph(unit, glyph [, group]) -- Returns: true if the player has the glyph associated with spellID or spellName (Note: For the moment, we can only see the glyphs of players running LibGroupTalents-1.0)
GUIDHasGlyph(unit, glyph [, group]) -- As UnitHasGlyph
PurgeAndRescanTalents() -- Wipe current roster of all talents and rescan from start
 
Convenience Functions (Similar to Blizzard API functions, but callable with a unit ID):
GetActiveTalentGroup(unit) -- Returns: Active talent group for unit
GetNumTalentGroups(unit) -- Returns: Number of talent groups for unit
GetNumTalentTabs(unit) -- Returns: Number of talent tabs. Here's a clue; it's going to be 3...
GetTalentTabInfo(unit, tab[, group]) -- Returns: Tree Name, Tree Icon, Points Spent, Tree Background
GetNumTalents(unit, tab) -- Returns: Number of talents for specified tree
GetTalentInfo(unit, tab, index[, group])-- Returns: Talent Name, Icon, Tier, Column, Points Spent, Max Rank (Note that preview return values are not given unless called with "player")
GetUnspentTalentPoints(unit[, group]) -- Returns: Number of un-spent talent points for the unit
 
Events:
LibGroupTalents_Update(guid, unit, newSpec, n1, n2, n3 [, oldSpec, o1, o2, o3]) -- Received updated talents. If it's a respec, or old set is know, it passes the old info also (this is not sent if new talent scan is same as previous)
LibGroupTalents_UpdateComplete(guid1, guid2[, ...]) -- Sent when there are no more pending talent reads due (passes all GUIDs that were updated since last time this event was fired)
LibGroupTalents_Add(guid, unit, name, realm) -- Unit added to talent roster (Talents not necessarily available yet, but this is the mod's chance to feed talents using SetStorageString)
LibGroupTalents_Remove(guid, name, realm) -- Unit removed from talent roster (This is your last chance to store talents if required using GetUnitStorageString)
LibGroupTalents_RoleChange(guid, unit, newrole, oldrole) -- Roles are: "melee", "caster", "healer", "tank"
LibGroupTalents_GlyphUpdate(guid, unit) -- Fired when a player's glyphs change (Note: For the moment, we can only see the glyphs of players running LibGroupTalents-1.0)
 
]]
 
local TalentQuery = LibStub("LibTalentQuery-1.0")
 
local MAJOR, MINOR = "LibGroupTalents-1.0", tonumber(("$Rev: 53 $"):match("(%d+)"))
local lib = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end
 
local ChatThrottleLib = _G.ChatThrottleLib
 
lib.roster = lib.roster or {}
lib.classTalentData = lib.classTalentData or {}
lib.batch = lib.batch or {}
lib.pendingStorageStrings = lib.pendingStorageStrings or {}
 
local function UnitFullName(unit)
local name, realm = UnitName(unit)
local namerealm = realm and realm ~= "" and name .. "-" .. realm or name
return namerealm
end
 
local specChangers = {}
for index,spellid in ipairs(_G.TALENT_ACTIVATION_SPELLS) do
specChangers[GetSpellInfo(spellid)] = index
end
 
local frame = lib.frame
if (not frame) then
frame = CreateFrame("Frame", "LibGroupTalents_Frame")
lib.frame = frame
end
frame:UnregisterAllEvents()
frame:RegisterEvent("RAID_ROSTER_UPDATE")
frame:RegisterEvent("PARTY_MEMBERS_CHANGED")
frame:RegisterEvent("UNIT_NAME_UPDATE")
frame:RegisterEvent("PLAYER_TALENT_UPDATE")
frame:RegisterEvent("UNIT_LEVEL")
frame:RegisterEvent("UNIT_AURA") -- Always get a UNIT_AURA when a unit's UnitIsVisible() changes
frame:RegisterEvent("CHAT_MSG_ADDON")
frame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
frame:RegisterEvent("PLAYER_LOGIN")
frame:RegisterEvent("GLYPH_ADDED")
frame:RegisterEvent("GLYPH_REMOVED")
frame:RegisterEvent("GLYPH_UPDATED")
 
frame:SetScript("OnEvent", function(self, event, ...)
return lib[event](lib, ...)
end)
 
if not lib.events then
lib.events = LibStub("CallbackHandler-1.0"):New(lib)
end
 
local next, select, pairs, type = next, select, pairs, type
local new, del, deepDel
do
local list = setmetatable({},{__mode='k'})
function new(...)
local t = next(list)
if t then
list[t] = nil
for i = 1, select('#', ...) do
t[i] = select(i, ...)
end
return t
else
return {...}
end
end
function del(t)
if (t) then
wipe(t)
t[''] = true
t[''] = nil
list[t] = true
end
end
function deepDel(t)
if (t) then
for k,v in pairs(t) do
if type(v) == "table" then
deepDel(v)
end
t[k] = nil
end
t[''] = true
t[''] = nil
list[t] = true
end
end
end
 
do
local delay = 0
frame:SetScript("OnUpdate", function(self, elapsed)
if (lib.raidRosterUpdate) then
lib.raidRosterUpdate = nil
lib:OnRaidRosterUpdate()
end
 
if (lib.refreshCheckTimer) then
lib.refreshCheckTimer = lib.refreshCheckTimer - elapsed
if (lib.refreshCheckTimer < 0) then
lib.refreshCheckTimer = nil
lib:CheckForMissingTalents()
end
end
 
if (lib.talentTimers) then
delay = delay + elapsed
if (delay > 1) then
delay = 0
local now = GetTime()
local triggers
for guid,when in pairs(lib.talentTimers) do
if (now > when) then
-- Pass to second table to process, because RefreshTimers can affect this talentTimers table
-- So it's important we're not still iterating it at the time
if (not triggers) then
triggers = new()
end
triggers[guid] = true
lib.talentTimers[guid] = nil
if (not next(lib.talentTimers)) then
lib.talentTimers = del(lib.talentTimers)
break
end
end
end
 
if (triggers) then
for guid in pairs(triggers) do
lib:RefreshTalentsByGUID(guid)
end
del(triggers)
end
end
end
 
if (not lib.talentTimers and not lib.refreshCheckTimer) then
self:Hide()
end
end)
end
frame:Show()
lib.raidRosterUpdate = true
 
-- GetGUIDTalentsRaw
local function GetGUIDTalentsRaw(guid, group)
local r = guid and lib.roster[guid]
return r and r.talents and r.talents[group or r.active], r
end
 
-- PLAYER_LOGIN
function lib:PLAYER_LOGIN()
ChatThrottleLib = _G.ChatThrottleLib
lib.PLAYER_LOGIN = nil
end
 
-- RAID_ROSTER_UPDATE
function lib:RAID_ROSTER_UPDATE()
self.raidRosterUpdate = true
frame:Show()
end
lib.PARTY_MEMBERS_CHANGED = lib.RAID_ROSTER_UPDATE
 
-- UNIT_NAME_UPDATE
function lib:UNIT_NAME_UPDATE(unit)
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
if (r) then
local needsAdd = r.name == UNKNOWN
r.name, r.realm = UnitName(unit)
if (r.realm == "") then
r.realm = nil
end
r.class = select(2, UnitClass(unit))
r.level = UnitLevel(unit)
if (not r.talents) then
if (needsAdd) then
self.events:Fire("LibGroupTalents_Add", guid, unit, r.name, r.realm)
end
 
self:CheckForMissingTalents()
end
end
end
 
-- AnyPending
local function AnyPending()
local checkUpdate
for guid,info in pairs(lib.roster) do
if (UnitIsConnected(info.name)) then
if (lib.wasOffline) then
lib.wasOffline[guid] = nil
end
if (not info.talents or info.refresh) then
return true
end
else
if (not lib.wasOffline) then
lib.wasOffline = new()
end
lib.wasOffline[guid] = true
end
end
if (lib.wasOffline and not next(lib.wasOffline)) then
lib.wasOffline = del(lib.wasOffline)
end
end
 
-- CheckForUpdateComplete
local function CheckForUpdateComplete()
-- When all pending updates are complete, send an event to notify nothing else is due
if (next(lib.batch)) then
if (not AnyPending()) then
lib.events:Fire("LibGroupTalents_UpdateComplete", unpack(lib.batch))
wipe(lib.batch)
end
end
end
 
-- UNIT_LEVEL
function lib:UNIT_LEVEL(unit)
if (UnitInParty(unit) or UnitInRaid(unit)) then
local guid = UnitGUID(unit)
local r = guid and self.roster[guid]
if (r) then
r.level = UnitLevel(unit)
self:RefreshTalentsByUnit(unit)
end
end
end
 
-- UNIT_AURA
function lib:UNIT_AURA(unit)
local guid = UnitGUID(unit)
if (not UnitIsVisible(unit) or (self.wasOffline and self.wasOffline[guid])) then
if (not self.outOfSight) then
self.outOfSight = {}
end
self.outOfSight[guid] = true
self:RefreshTalentsByGUID(guid)
end
end
 
-- OnRaidRosterUpdate
function lib:OnRaidRosterUpdate()
local instanceType = select(2, IsInInstance())
if (instanceType == "pvp" or instanceType == "arena") then
self.distribution = "BATTLEGROUND"
else
if (GetNumRaidMembers() > 0) then
self.distribution = "RAID"
elseif (GetNumPartyMembers() > 0) then
self.distribution = "PARTY"
else
self.distribution = nil
end
end
if (self.distribution) then
if (self.sentHello ~= self.distribution) then
self.sentHello = self.distribution
self:SendCommMessage("HELLO "..MINOR, nil, self.distribution)
end
else
self.sentHello = nil
self.talentThrottle = del(self.talentThrottle)
self.wasOffline = del(self.wasOffline)
self.outOfSight = del(self.outOfSight)
wipe(self.pendingStorageStrings)
end
 
-- Now check for roster changes
local subtractions = new()
local additions = new()
local changes = new()
 
if (self.roster) then
for guid,info in pairs(self.roster) do
subtractions[guid] = info.level or 0
end
end
 
for unit in self:IterateRoster() do
local guid = UnitGUID(unit)
if (guid) then
local n = self.roster[guid]
if (not n) then
n = new()
self.roster[guid] = n
end
 
n.name, n.realm = UnitName(unit)
if (n.realm == "") then
n.realm = nil -- Fix this already..
end
n.level = UnitLevel(unit)
n.class = select(2, UnitClass(unit))
n.unit = unit
 
if (subtractions[guid]) then
if (subtractions[guid] ~= n.level) then
changes[guid] = unit -- Level changed, needs a rescan
end
 
subtractions[guid] = nil
else
if (n.name ~= UNKNOWN) then
self.events:Fire("LibGroupTalents_Add", guid, unit, n.name, n.realm)
end
additions[guid] = unit
end
end
end
 
if (next(additions)) then
for guid,unit in pairs(additions) do
self:GetUnitTalents(unit)
end
end
 
if (next(changes)) then
for guid,unit in pairs(changes) do
self:GetUnitTalents(unit)
end
end
 
if (next(subtractions)) then
for guid in pairs(subtractions) do
local r = self.roster[guid]
if (r) then
self.events:Fire("LibGroupTalents_Remove", guid, r.name, r.realm)
self.roster[guid] = deepDel(r)
 
local classStorageStrings = self.pendingStorageStrings[r.class]
if (classStorageStrings) then
classStorageStrings[guid] = del(classStorageStrings[guid])
if (not next(classStorageStrings)) then
self.pendingStorageStrings[r.class] = del(self.pendingStorageStrings[r.class])
end
end
end
end
 
CheckForUpdateComplete()
end
 
del(additions)
del(subtractions)
del(changes)
 
self:CheckForMissingTalents()
end
 
-- ValidateUnit
local function ValidateUnit(r, guid)
local unit = r.unit
if (UnitGUID(unit) ~= guid) then
local name = r.name .. (r.realm and "-" or "") .. (r.realm or "")
local index = UnitInRaid(name)
if (index) then
r.unit = "raid"..index
return true
else
if (UnitGUID("player") == guid) then
r.unit = "player"
return true
 
elseif (UnitInParty(name)) then
for i = 1,4 do
if (UnitGUID("party"..i) == guid) then
r.unit = "party"..i
return true
end
end
end
end
return
end
 
return true
end
 
-- CountTree
local function CountTree(branch)
local count = 0
for i = 1,#branch do
count = count + branch:byte(i) - 48
end
return count
end
 
-- TalentWeight
local function TalentWeight(talents, class)
if (talents and #talents == 3 and class) then
local c1, c2, c3 = CountTree(talents[1]), CountTree(talents[2]), CountTree(talents[3])
 
local weight = 1
if (c2 > c1 and c2 > c3) then
weight = 2
elseif (c3 > c1 and c3 > c2) then
weight = 3
end
 
local data = lib.classTalentData[class]
if (data and data[weight]) then
return data[weight].name, c1, c2, c3
end
 
return weight, c1, c2, c3
end
return nil, 0, 0, 0
end
 
do
-- First segment: Player ID (from GUID), Name, level, class, activePage, TalentString
-- Subsequent: spec number, talentString()
 
-- crc
local function crc32(str)
local val = tonumber((select(2, GetBuildInfo()))) -- Use WoW build as CRC base
for i = 1,#str do
val = bit.band(val * 2 + str:byte(i), 0xFFFF)
end
return val
end
 
-- GetUnitStorageString
function lib:GetUnitStorageString(unit)
return self:GetGUIDStorageString(UnitGUID(unit))
end
 
-- GetGUIDStorageString
-- Make a storage string for mods to store talents.
-- Rules: 1) Your own realm only 2) Their talents are complete (nothing unspent)
function lib:GetGUIDStorageString(guid)
local r = self.roster[guid]
if (r) then
local id
local playerGUID = UnitGUID("player")
if (playerGUID:sub(1, 6) == guid:sub(1, 6)) then
-- Same realm code, so just trim it off. This is likely always true from what I've seen
id = format("%X", tonumber(guid:sub(7), 16))
else
id = guid:sub(4)
end
 
if (r.talents and r.active and not r.realm and (not r.unspent or not r.unspent[r.active])) then
if (r.level < 1) then
r.level = UnitLevel(r.name) or 0
end
local str = format("%s,%d,%s,%d,%d", id, r.level, r.class, r.active, r.numActive)
for i = 1,r.numActive do
local t = r.talents[i]
if (t) then
str = format("%s;%d,%s", str, i, table.concat(t, "-"))
end
end
return format("%s;%d", str, crc32(str))
end
end
end
 
-- SetStorageString
function lib:SetStorageString(str, comms)
local ret, retInfo
if (str) then
local parts = new(strsplit(";", str))
if (#parts >= 2) then
local strCRC = tonumber(parts[#parts])
local temp = table.concat(parts, ";", 1, #parts - 1)
if (crc32(temp) == strCRC) then
local part1 = new(strsplit(",", parts[1]))
 
while true do
local guid
local id = part1[1]
if (id:len() < 12) then
-- Trimmed GUID, we'll prefix it with our own GUID's realm code
guid = format("%s%012X", UnitGUID("player"):sub(1, 6), tonumber(id, 16))
else
guid = format("0x0%015s", id)
end
 
local r = self.roster[guid]
if (not r) then
retInfo = format("Unexpected SetStorageString for ID %s", guid)
ret = true -- Still return true, we just didn't want this string yet
break
elseif (r.name == UNKNOWN) then
retInfo = format("Premature SetStorageString for ID %s", guid)
ret = true -- Still return true, we just didn't want this string yet
break
end
if (r.talents) then
-- We've already received talents for this player
ret = true -- Still return true, we just didn't want this string because we have their talents
break
end
 
if (not self.classTalentData[r.class]) then
-- Received a storage string for a class that we've not yet been able to scan
-- the talent trees for. We store this until we have that data
local classStorageStrings = self.pendingStorageStrings[r.class]
if (not classStorageStrings) then
classStorageStrings = new()
self.pendingStorageStrings[r.class] = classStorageStrings
end
classStorageStrings[guid] = str
ret = true
break
end
 
local level = tonumber(part1[2])
local class = part1[3]
local active = tonumber(part1[4])
local numActive = tonumber(part1[5])
 
if (r.level < 1) then
r.level = UnitLevel(r.name) or 0
end
if (level ~= r.level and r.level > 1) then
-- Won't accept talents for mismatched levels (but ignore errors reading the UnitLevel early)
retInfo = "Wrong level"
break
end
if (not r.class and class) then
-- If we don't have the class, but the storage string does, we'll take it
r.class = class
end
if (class ~= r.class) then
-- Class doesn't match, probably a char delete/remake or xrealm
retInfo = format("Wrong class: expected %q, got %q", tostring(r.class), tostring(class))
break
end
 
-- Now the talent trees
local talents = new()
for i = 2,#parts - 1 do
local partN = new(strsplit(",", parts[i]))
if (#partN == 2) then
local specNumber = tonumber(partN[1])
local specTalents = new(strsplit("-", partN[2]))
 
if (specNumber and #specTalents >= 3) then
talents[specNumber] = specTalents
else
del(specTalents)
talents = del(talents)
retInfo = "Invalid talent specs in tree "..i
break
end
end
end
 
if (talents) then
r.talents = talents
r.active = active
r.numActive = numActive
if (comms ~= r.name) then
-- If comms part sends player name along with packet, then we'll skip the refresh later
-- which we'd normally do when Storage is set via app startup
r.refresh = true
else
r.refresh = nil
end
 
ValidateUnit(r, guid)
local newSpec, n1, n2, n3 = TalentWeight(r.talents[r.active], r.class)
self.events:Fire("LibGroupTalents_Update", guid, r.unit, newSpec, n1, n2, n3)
self:GetGUIDRole(guid, true)
ret = true
end
break
end
 
del(part1)
else
retInfo = "Invalid string"
end
end
del(parts)
end
 
return ret, retInfo
end
end
 
-- GetClassTalentData
-- Builds an internal table for talent name -> tree/index lookups.
function GetClassTalentData(unit)
local _, class = UnitClass(unit)
if (class) then
local data = lib.classTalentData[class]
if (not data) then
local isnotplayer = not UnitIsUnit("player", unit)
if (GetNumTalentTabs(isnotplayer) > 0) then
data = new()
 
for tab = 1, GetNumTalentTabs(isnotplayer) do
local tree = new()
local _
tree.name, tree.icon, _, tree.background = GetTalentTabInfo(tab, isnotplayer)
tinsert(data, tree)
 
tree.list = new()
for i = 1,GetNumTalents(tab, isnotplayer) do
local name, icon, tier, column, currentRank, maxRank = GetTalentInfo(tab, i, isnotplayer)
if (name) then
local entry = new()
entry.name = name
entry.icon = icon
entry.tier = tier
entry.column = column
entry.maxRank = maxRank
entry.index = i
entry.treeIndex = tab
tinsert(tree.list, entry)
if (not data.list) then
data.list = new()
end
data.list[name] = entry
end
end
end
 
if (next(data)) then
lib.classTalentData[class] = data
 
--for guid,r in pairs(lib.roster) do
-- if (r.class == class and r.talents) then
-- -- We picked up class talent data for a class after receiving talents for them via comms
-- -- So, we fire an Update event for any members of the class we already have so that
-- -- talents can now be interpreted correctly.
-- local spec, n1, n2, n3 = TalentWeight(r.talents[r.active], class)
-- lib.events:Fire("LibGroupTalents_Update", guid, unit, spec, n1, n2, n3)
-- end
--end
 
local classStorageStrings = lib.pendingStorageStrings[class]
if (classStorageStrings) then
local unitGUID = UnitGUID(unit)
for guid, str in pairs(classStorageStrings) do
if (guid ~= unitGUID) then
lib:SetStorageString(str)
end
end
lib.pendingStorageStrings[class] = del(lib.pendingStorageStrings[class])
end
else
deepDel(data)
end
end
end
end
end
 
-- GetTreeNames
function lib:GetTreeNames(class)
local info = self.classTalentData[class]
if (info) then
return info[1].name, info[2].name, info[3].name
end
end
 
-- GetTreeIcons
function lib:GetTreeIcons(class)
local info = self.classTalentData[class]
if (info) then
return info[1].icon, info[2].icon, info[3].icon
end
end
 
-- ReadTalentGroup
local function ReadTalentGroup(isnotplayer, group, class)
local numTabs = GetNumTalentTabs(isnotplayer)
if (numTabs and numTabs >= 3 and GetNumTalents(1, isnotplayer) > 0) then
local ctd = lib.classTalentData[class]
--[===[@debug@
assert(ctd and ctd[1] and ctd[2] and ctd[3])
assert(ctd[1].list and ctd[2].list and ctd[3].list)
--@end-debug@]===]
 
local n = new()
for tab = 1, numTabs do
local branchLength = GetNumTalents(tab, isnotplayer, nil, group)
if (branchLength ~= #ctd[tab].list) then
-- Tab tree size is not what we expected for this class
del(n)
return
end
 
local t = new()
local trim
for i = 1,branchLength do
local name, icon, tier, column, currentRank, maxRank = GetTalentInfo(tab, i, isnotplayer, nil, group)
tinsert(t, currentRank)
if (currentRank > 0) then
trim = i -- We strip off trailing zeros from talent strings to save storage space
end
end
 
tinsert(n, table.concat(t, nil, 1, trim or 0))
del(t)
end
 
return n
end
end
 
-- TalentQuery_Ready
function lib:TalentQuery_Ready_Outsider(e, name, realm, unit)
self:TalentQuery_Ready(e, name, realm, unit)
end
 
-- TalentQuery_Ready
function lib:TalentQuery_Ready(e, name, realm, unit)
GetClassTalentData(unit)
 
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
if (r) then
local namerealm = realm and realm ~= "" and name .. "-" .. realm or name
local isnotplayer = not UnitIsUnit(unit, "player")
 
if (GetTalentTabInfo(1, isnotplayer)) then
local active = GetActiveTalentGroup(isnotplayer)
local numActive = GetNumTalentGroups(isnotplayer)
local listUnspent, invalid
local talents = new()
 
for group = 1,numActive do
local n = ReadTalentGroup(isnotplayer, group, r.class)
if (n and #n >= 3) then
talents[group] = n
else
invalid = true
break
end
 
local unspent = GetUnspentTalentPoints(isnotplayer, nil, group)
if (unspent and unspent > 0) then
if (not listUnspent) then
listUnspent = new()
end
listUnspent[group] = unspent
end
end
 
if (isnotplayer and (invalid or (listUnspent and listUnspent[active] or 0) > 0)) then
-- Unit didn't have all their points spent in active group, so we'll have another look in 10 seconds
-- Don't need to check when it's "player" because we get PLAYER_TALENT_UPDATE event on changes
self:TriggerRefreshTalents(guid, 10)
end
 
if (not invalid) then
if (active > numActive) then
-- May be better to discard instead? We'll see
active = 1
end
self:OnReceiveTalents(guid, unit, talents, active, numActive, listUnspent)
end
end
end
end
TalentQuery.RegisterCallback(lib, "TalentQuery_Ready")
TalentQuery.RegisterCallback(lib, "TalentQuery_Ready_Outsider")
 
-- GetUnitTalentSpec
function lib:GetUnitTalentSpec(unit, group)
return self:GetGUIDTalentSpec(UnitGUID(unit), group)
end
 
-- GetGUIDTalentSpec
function lib:GetGUIDTalentSpec(guid, group)
local talents, r = GetGUIDTalentsRaw(guid, group)
if (talents) then
return TalentWeight(talents, r.class)
end
end
 
-- CompareTalents
local function CompareTalents(tree1, tree2)
if ((tree1 ~= nil) ~= (tree2 ~= nil)) then
return
end
if (tree1 and tree2 and #tree1 == #tree2) then
for i = 1,#tree1 do
if (tree1[i] ~= tree2[i]) then
return
end
end
return true
end
end
 
-- OnReceiveTalents
function lib:OnReceiveTalents(guid, unit, talents, active, numActive, listUnspent)
local r = self.roster[guid]
if (r) then
if (active ~= r.active or numActive ~= r.numActive or not CompareTalents(talents and talents[active], r.talents and r.talents[r.active])) then
local oldTalents
if (r.talents) then
oldTalents = r.talents[r.active]
end
del(r.unspent)
 
r.talents = talents
r.active = active
r.numActive = numActive
r.unspent = listUnspent
 
local newSpec, n1, n2, n3 = TalentWeight(r.talents[active], r.class)
 
local fired
if (oldTalents) then
-- For those cases when we didn't have the alternate talents for a player for whatever reason.
-- Maybe they just picked up dual talent spec, or gated to trainer to respec.
local oldSpec, o1, o2, o3 = TalentWeight(oldTalents, r.class)
 
if (o1 ~= n1 or o2 ~= n2 or o3 ~= n3) then
self.events:Fire("LibGroupTalents_Update", guid, unit, newSpec, n1, n2, n3, oldSpec, o1, o2, o3)
fired = true
end
end
 
if (not fired) then
self.events:Fire("LibGroupTalents_Update", guid, unit, newSpec, n1, n2, n3)
end
self:GetGUIDRole(guid, true)
 
tinsert(self.batch, guid)
CheckForUpdateComplete()
 
oldTalents = del(oldTalents)
return
end
end
del(talents)
end
 
-- OnReceiveGlyphs
function lib:OnReceiveGlyphs(guid, sender, glyphs)
local r = self.roster[guid]
if (r) then
if (ValidateUnit(r, guid)) then
local oldGlyphs
if (r.glyphs) then
oldGlyphs = r.glyphs[r.active]
r.glyphs = del(r.glyphs)
end
 
r.glyphs = glyphs
 
local newGlyphs = r.glyphs and r.glyphs[r.active]
if (newGlyphs ~= oldGlyphs) then
self.events:Fire("LibGroupTalents_GlyphUpdate", guid, r.unit)
end
return
end
end
 
del(glyphs)
end
 
-- GetUnitGlyphs
function lib:GetUnitGlyphs(unit, group)
return self:GetGUIDGlyphs(UnitGUID(unit), group)
end
 
-- GetGUIDGlyphs
function lib:GetGUIDGlyphs(guid, group)
local r = self.roster[guid]
if (r) then
local g = r.glyphs and r.glyphs[group or r.active]
if (g) then
local temp = new(strsplit(",", g))
for i,str in ipairs(temp) do
temp[i] = tonumber(str)
end
local a, b, c, d, e, f = unpack(temp)
del(temp)
return a, b, c, d, e, f
end
end
end
 
-- UnitHasGlyph
function lib:UnitHasGlyph(unit, glyphID, group)
return lib:GUIDHasGlyph(UnitGUID(unit), glyphID, group)
end
 
-- GUIDHasGlyph
function lib:GUIDHasGlyph(guid, glyphID, group)
local ret
local r = self.roster[guid]
if (r) then
local g = r.glyphs and r.glyphs[group or r.active]
if (g) then
local temp = new(strsplit(",", g))
for i,str in ipairs(temp) do
local id = tonumber(str)
if (type(glyphID) == "number") then
if (glyphID == id) then
ret = true
break
end
else
if (glyphID == GetSpellInfo(id)) then
ret = true
break
end
end
end
del(temp)
end
end
return ret
end
 
-- GLYPH_ADDED
function lib:GLYPH_ADDED(index, a, b, c)
self:RefreshPlayerGlyphs()
end
 
-- GLYPH_REMOVED
function lib:GLYPH_REMOVED(index, a, b, c)
self:RefreshPlayerGlyphs()
end
 
-- GLYPH_UPDATED
function lib:GLYPH_UPDATED(index, a, b, c)
self:RefreshPlayerGlyphs()
end
 
-- RefreshPlayerGlyphs
function lib:RefreshPlayerGlyphs()
local guid = UnitGUID("player")
local r = self.roster[guid]
if (not r) then
return
end
 
local glyphs = new()
local any
for talentGroup = 1,GetNumTalentGroups() do
local list = new()
for i = 1,GetNumGlyphSockets() do
local enabled, glyphType, glyphSpell, icon = GetGlyphSocketInfo(i, talentGroup)
if (enabled and glyphType and glyphSpell) then
tinsert(list, glyphSpell)
any = true
end
end
glyphs[talentGroup] = table.concat(list, ",")
del(list)
end
 
local oldGlyphs = r.glyphs
if (any) then
r.glyphs = glyphs
else
del(glyphs)
end
 
local change = (oldGlyphs and oldGlyphs[r.active]) ~= (r.glyphs and r.glyphs[r.active])
if (change) then
self:SendMyGlyphs()
self.events:Fire("LibGroupTalents_GlyphUpdate", guid, "player")
end
 
del(oldGlyphs)
end
 
-- PLAYER_TALENT_UPDATE
function lib:PLAYER_TALENT_UPDATE()
self:TriggerRefreshTalents(UnitGUID("player"), 2)
end
 
-- UNIT_SPELLCAST_SUCCEEDED
function lib:UNIT_SPELLCAST_SUCCEEDED(unit, spell)
local newActiveGroup = specChangers[spell]
if (newActiveGroup) then
local guid = UnitGUID(unit)
local r = guid and self.roster[guid]
if (r) then
if (newActiveGroup == r.active) then
-- We obviously didn't see them switch from this set
self:GetGUIDRole(guid, true)
return
end
 
if (r.talents) then
local oldSet = r.talents[r.active]
local newSet = r.talents[newActiveGroup]
if (oldSet and newSet) then
-- We have the other talent set, so no need to refresh anything. Just compare and notify
r.active = newActiveGroup
 
local oldSpec, o1, o2, o3 = TalentWeight(oldSet, r.class)
local newSpec, n1, n2, n3 = TalentWeight(newSet, r.class)
 
if (o1 ~= n1 or o2 ~= n2 or o3 ~= n3) then
self.events:Fire("LibGroupTalents_Update", guid, unit, newSpec, n1, n2, n3, oldSpec, o1, o2, o3)
else
self.events:Fire("LibGroupTalents_Update", guid, unit, newSpec, n1, n2, n3)
end
self:GetGUIDRole(guid, true)
return
end
end
 
-- If we get this far, then someone probably gated to respec
self:RefreshTalentsByGUID(guid)
end
end
end
 
-- TriggerRefreshTalents
function lib:TriggerRefreshTalents(guid, delay)
if (not self.talentTimers) then
self.talentTimers = new()
end
if (guid) then
self.talentTimers[guid] = GetTime() + delay
frame:Show()
end
end
 
-- RefreshTalentsByUnit
function lib:RefreshTalentsByUnit(unit)
local guid = UnitGUID(unit)
if (guid) then
self:RefreshTalentsByGUID(guid)
end
end
 
-- RefreshTalentsByGUID
function lib:RefreshTalentsByGUID(guid)
local r = self.roster[guid]
if (not r) then
return
end
if (not ValidateUnit(r, guid)) then
return
end
 
if (self.talentTimers) then
self.talentTimers[guid] = nil
end
 
if (not self.talentThrottle) then
self.talentThrottle = {}
end
for guidThrottle,when in pairs(self.talentThrottle) do
if (when < GetTime() - 5) then
self.talentThrottle[guidThrottle] = nil
elseif (guid == guidThrottle) then
return
end
end
self.talentThrottle[guid] = GetTime()
 
if (self.commQueried) then
self.commQueried[guid] = nil
if (not next(self.commQueried)) then
self.commQueried = del(self.commQueried)
end
end
 
r.refresh = true
self:CheckForMissingTalents()
 
if (UnitGUID("player") == guid) then
self:SendMyTalents()
end
end
 
-- CheckForMissingTalents
function lib:CheckForMissingTalents()
local any
for guid,info in pairs(self.roster) do
if (not info.talents or (not UnitIsVisible(info.name) and UnitExists(info.name)) or info.refresh) then
any = true
info.refresh = nil
self:GetUnitTalents(info.unit, true)
end
end
 
if (any) then
lib.refreshCheckTimer = 15
frame:Show()
end
end
 
do
local survivalOfTheFittest = GetSpellInfo(33853) -- Survival of the Fittest
local protectorOfThePack = GetSpellInfo(57873) -- Protector of the Pack
local dkBladeBarrier = GetSpellInfo(49182) -- Blade Barrier
local dkToughness = GetSpellInfo(49042) -- Toughness
local dkAnticipation = GetSpellInfo(55129) -- Anticipation
 
-- GetUnitRole
function lib:GetUnitRole(unit, reset)
local guid = UnitGUID(unit)
if (guid) then
return self:GetGUIDRole(guid, reset)
end
end
 
-- GetGUIDRole
function lib:GetGUIDRole(guid, reset)
local r = guid and self.roster[guid]
if (not r) then
return
end
if (r.role and not reset) then
return r.role
end
if (not ValidateUnit(r, guid)) then
return
end
 
local class = r.class
local role
 
local unit = r.unit
if (class == "ROGUE" or class == "HUNTER") then
role = "melee"
elseif (class == "MAGE" or class == "WARLOCK") then
role = "caster"
elseif (r.talents and r.talents[r.active]) then
if (class == "DEATHKNIGHT") then
local score = self:GUIDHasTalent(guid, dkBladeBarrier) and 1 or 0
score = score + (self:GUIDHasTalent(guid, dkToughness) and 1 or 0)
score = score + (self:GUIDHasTalent(guid, dkAnticipation) and 1 or 0)
role = score >= 2 and "tank" or "melee" -- Has 2 of the 3 tanking talents at least
 
else
local specName, t1, t2, t3 = TalentWeight(r.talents[r.active], class)
 
if (class == "PRIEST") then
role = ((t1 + t2) > t3) and "healer" or "caster"
elseif (class == "WARRIOR") then
role = ((t1 + t2) > t3) and "melee" or "tank"
else
local heavy = (t1 > t2 and t1 > t3 and 1) or (t2 > t1 and t2 > t3 and 2) or (t3 > t1 and t3 > t2 and 3) or 0
if (class == "PALADIN") then
role = heavy == 1 and "healer" or heavy == 2 and "tank" or heavy == 3 and "melee"
 
elseif (class == "DRUID") then
if (heavy == 2) then
if (self:GUIDHasTalent(guid, survivalOfTheFittest) and self:GUIDHasTalent(guid, protectorOfThePack)) then
role = "tank"
else
role = "melee"
end
else
role = heavy == 1 and "caster" or "healer"
end
 
elseif (class == "SHAMAN") then
role = heavy == 1 and "caster" or heavy == 2 and "melee" or heavy == 3 and "healer"
end
end
end
end
 
local oldrole = r.role
r.role = role
 
if (role and role ~= oldrole) then
self.events:Fire("LibGroupTalents_RoleChange", guid, unit, role, oldrole)
end
return role
end
end
 
-- GetUnitTalents
function lib:GetUnitTalents(unit, refetch)
local guid = UnitGUID(unit)
if (not guid) then
return
end
return self:GetGUIDTalents(guid, refetch)
end
 
-- CanCommQuery
local function CanCommQuery(guid)
if (not lib.commQueried or not lib.commQueried[guid]) then
if (not lib.commQueried) then
lib.commQueried = new()
end
lib.commQueried[guid] = true
return true
end
end
 
-- GetGUIDTalents
function lib:GetGUIDTalents(guid, refetch)
local r = self.roster[guid]
if (not r) then
return
end
if (not ValidateUnit(r, guid)) then
return
end
 
local unit = r.unit
local name, realm = UnitName(unit)
local activeTalents = r.talents and r.talents[r.active]
 
if (activeTalents) then
-- If someone is out of sight, we won't catch their talent swap spell cast, so we'll invalidate them here and recheck talents
if ((not UnitIsVisible(unit) and UnitIsConnected(unit)) or (self.outOfSight and self.outOfSight[guid])) then
if (not r.version) then
refetch = true
end
end
end
 
if (not activeTalents or refetch) then
if (UnitIsUnit("player", unit)) then
self:RefreshPlayerGlyphs()
self:TalentQuery_Ready(nil, name, nil, unit)
 
elseif ((UnitInRaid(unit) or UnitInParty(unit)) and UnitIsConnected(unit)) then
TalentQuery:Query(unit)
 
local namerealm = UnitFullName(unit)
if (not r.talents and not r.requested) then
-- Don't need to query on a 'refetch' because they'll send changes anyway via comms
local skipGlyphs
if (not UnitIsVisible(unit) or not CanInspect(unit)) then
if (r.version) then
if (CanCommQuery(guid)) then
-- We request talents via comms for anyone that may be out of inspect range
self:SendCommMessage("REQUESTTALENTS", namerealm)
r.requested = true
skipGlyphs = true
end
end
end
end
 
if (not r.glyphs and not skipGlyphs) then
if (r.version and r.version >= 15) then
if (CanCommQuery(guid)) then
-- They're in range to inspect, but we'll still want to ask for their glyphs
self:SendCommMessage("REQUESTGLYPHS", namerealm)
end
end
end
end
 
if (self.outOfSight) then
self.outOfSight[guid] = nil
end
end
 
return activeTalents
end
 
-- SendCommMessage
function lib:SendCommMessage(msg, target, channel)
if (msg) then
if (ChatThrottleLib) then
ChatThrottleLib:SendAddonMessage("NORMAL", MAJOR, msg, channel or "WHISPER", target)
else
SendAddonMessage(MAJOR, msg, channel or "WHISPER", target)
end
end
end
 
-- Throttle - Purposely local to here
-- Abuse prevention. Yes, who would abuse addon comms? Noone would make a macro to crash a mod user would they. Right?
-- Well, this one time, at band camp. Someone thought it was super funny to make a macro that DCd PallyPower users
local throttle
local function Throttle(sender, key)
if (not throttle) then
throttle = {}
end
local s = throttle[sender]
if (not s) then
s = {}
throttle[sender] = s
end
 
if ((s[key] or 0) < GetTime() - 4.5) then
-- Same message key only allowable once every 4.5 secs from 1 person (Respec cast time is 5 seconds)
s[key] = GetTime()
return true
end
end
 
-- CHAT_MSG_ADDON
function lib:CHAT_MSG_ADDON(prefix, msg, channel, sender)
if (prefix == MAJOR) then
if (sender == UnitName("player")) then
return
elseif (not UnitInRaid(sender) and not UnitInParty(sender)) then
return
end
 
local guid = UnitGUID(sender)
if (not guid) then
return
end
local r = self.roster[guid]
if (not r) then
return
end
 
local cmd, str = msg:match("^(%a+) *(.*)$")
if (not cmd) then
return
end
 
if (cmd == "TALENTS") then
-- Talents come in form of:
local t = r.talents
r.talents = nil -- SetStorageString won't overwrite talents usually, but we want it to here, without providing a means to do it easily with an arg from a mod
if (not self:SetStorageString(str, sender)) then
r.talents = t
else
deepDel(t)
end
 
elseif (cmd == "GLYPHS") then
local invalid
local pages = new(strsplit(";", str))
local glyphs = new()
for page,info in ipairs(pages) do
local list = new(strsplit(",", info))
local tab = tonumber(tremove(list, 1))
if (tab) then
glyphs[tab] = table.concat(list, ",")
del(list)
else
invalid = true
del(glyphs)
del(list)
break
end
end
if (not invalid) then
self:OnReceiveGlyphs(guid, sender, glyphs)
end
del(pages)
 
elseif (cmd == "REQUESTTALENTS") then
if (Throttle(sender, "REQUESTTALENTS")) then
if ((r.version or 0) < 39) then
if (lib.sentToOld and lib.sentToOld[guid]) then
return
end
if (not lib.sentToOld) then
lib.sentToOld = new()
end
lib.sentToOld[guid] = time()
end
 
self:SendMyTalents(sender)
self:SendMyGlyphs(sender)
end
 
elseif (cmd == "REQUESTGLYPHS") then
if (Throttle(sender, "REQUESTGLYPHS")) then
self:SendMyGlyphs(sender)
end
 
elseif (cmd == "HELLO") then
r.version = tonumber(str)
if (channel ~= "WHISPER") then
if (lib.sentToOld) then
lib.sentToOld[guid] = nil
end
if (UnitIsConnected(sender) and Throttle(sender, "HELLO")) then
self:SendCommMessage("HELLO "..MINOR, sender)
self:SendMyGlyphs(sender)
end
end
end
end
end
 
-- SendMy
local function SendMy(sender, str)
if (sender) then
if (UnitIsConnected(sender)) then
lib:SendCommMessage(str, sender)
end
else
for guid,info in pairs(lib.roster) do
if (info.version and UnitIsConnected(info.name)) then
lib:SendCommMessage(str, info.name)
end
end
end
end
 
-- SendMyTalents
function lib:SendMyTalents(sender)
if (sender or self:UserCount() > 0) then
local str = self:GetGUIDStorageString(UnitGUID("player"))
if (str) then
SendMy(sender, "TALENTS "..str)
end
end
end
 
-- SendMyGlyphs
function lib:SendMyGlyphs(sender)
if (sender or self:UserCount() > 0) then
local r = self.roster[UnitGUID("player")]
if (r and r.glyphs) then
local str = "GLYPHS "
local i = 1
for tab,g in pairs(r.glyphs) do
local temp = format("%d,%s", tab, g)
str = str .. (i > 1 and ";" or "") .. temp
i = i + 1
end
SendMy(sender, str)
end
end
end
 
-- UserCount
function lib:UserCount()
local count = 0
for guid,info in pairs(self.roster) do
if (info.version and not UnitIsUnit("player", info.name)) then
count = count + 1
end
end
return count
end
 
-- UnitHasTalent
-- eg: lib:UnitHasTalent("player", GetSpellInfo(talentSpellID))
-- Returns: nil, or number of points spent into talent
-- If the talent group is not specified, then the active talent group is used
function lib:UnitHasTalent(unit, talentName, group)
return unit and self:GUIDHasTalent(UnitGUID(unit), talentName, group)
end
 
-- GUIDHasTalent
-- Returns: nil, or number of points spent into talent
function lib:GUIDHasTalent(guid, talentName, group)
local talents, r = GetGUIDTalentsRaw(guid, group)
if (talents and r.class) then
local data = self.classTalentData[r.class]
if (data) then
local info = data.list and data.list[talentName]
if (info) then
local str = talents[info.treeIndex]
if (str) then
local amount = (str:byte(info.index) or 48) - 48
return (amount or 0) > 0 and amount or nil
end
end
end
end
end
 
-- GetClassTalentInfo
function lib:GetClassTalentInfo(class, talentName)
-- Returns: Max Rank, Icon, Tab, Tier, Column, Tree Index
local data = self.classTalentData[class]
if (data) then
local info = data.list and data.list[talentName]
if (info) then
return info.maxRank, info.icon, info.treeIndex, info.column, info.tier, info.index
end
end
end
 
-- GetActiveTalentGroup
function lib:GetActiveTalentGroup(unit)
if (UnitIsUnit(unit, "player")) then
return GetActiveTalentGroup()
else
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
return r and r.active or nil
end
end
 
-- GetNumTalentGroups
function lib:GetNumTalentGroups(unit)
if (UnitIsUnit(unit, "player")) then
return GetNumTalentGroups()
else
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
return r and r.numActive or nil
end
end
 
-- GetTalentTabInfo
function lib:GetTalentTabInfo(unit, tab, group)
if (UnitIsUnit(unit, "player")) then
return GetTalentTabInfo(tab, nil, nil, group or GetActiveTalentGroup())
else
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
if (r and r.class) then
local ctd = self.classTalentData[r.class]
if (ctd and tab >= 1 and tab <= #ctd) then
local spec, c1, c2, c3 = self:GetGUIDTalentSpec(guid, group)
return ctd[tab].name, ctd[tab].icon, tab == 1 and c1 or tab == 2 and c2 or c3, ctd[tab].background, 0
end
end
end
end
 
-- GetNumTalents
function lib:GetNumTalents(unit, tab)
if (UnitIsUnit(unit, "player")) then
return GetNumTalents(tab)
else
local _, class = UnitClass(unit)
if (class) then
local ctd = self.classTalentData[class]
if (ctd and tab >= 1 and tab <= #ctd) then
return #ctd[tab].list
end
end
end
end
 
-- GetTalentInfo
function lib:GetTalentInfo(unit, tab, index, group)
if (UnitIsUnit(unit, "player")) then
return GetTalentInfo(tab, index, nil, nil, group or GetActiveTalentGroup())
else
local _, class = UnitClass(unit)
if (class) then
local ctd = self.classTalentData[class]
if (ctd and tab >= 1 and tab <= #ctd) then
local info = ctd[tab].list[index]
if (info) then
local spent = self:UnitHasTalent(unit, info.name, group)
return info.name, info.icon, info.tier, info.column, spent or 0, info.maxRank
end
end
end
end
end
 
-- GetNumTalentTabs
function lib:GetNumTalentTabs()
return GetNumTalentTabs()
end
 
-- GetNumTalentTabs
function lib:GetUnspentTalentPoints(unit, group)
if (UnitIsUnit(unit, "player")) then
return GetUnspentTalentPoints(nil, nil, group)
else
local guid = unit and UnitGUID(unit)
local r = guid and self.roster[guid]
if (r) then
return r.unspent and r.unspent[group or r.active or 1]
end
end
end
 
-- GetTalentCount
function lib:GetTalentCount()
local count, missing = 0, 0
for guid,info in pairs(self.roster) do
if (info.talents) then
count = count + 1
else
missing = missing + 1
end
end
return count, missing
end
 
-- GetTalentMissingNames
function lib:GetTalentMissingNames()
local list = new()
for unit in self:IterateRoster() do
local guid = UnitGUID(unit)
local r = guid and self.roster[guid]
if (not r or not r.talents) then
tinsert(list, UnitFullName(unit))
end
end
local ret
if (next(list)) then
ret = table.concat(list, ",")
end
del(list)
return ret
end
 
-- PurgeAndRescanTalents
function lib:PurgeAndRescanTalents()
if (self.roster) then
wipe(self.pendingStorageStrings)
for guid,info in pairs(self.roster) do
info.talents = del(info.talents)
info.active = nil
info.numActive = nil
info.requested = nil
end
end
self:CheckForMissingTalents()
end
 
-- Roster iterator
do
local function iter(t)
local key = t.id
local ret
if (t.mode == "raid") then
if (key > t.r) then
del(t)
return nil
end
ret = "raid"..key
else
if (key > t.p) then
del(t)
return nil
end
ret = key == 0 and "player" or "party"..key
end
t.id = key + 1
return ret
end
 
-- IterateRoster
function lib:IterateRoster()
local t = new()
if (GetNumRaidMembers() > 0) then
t.mode = "raid"
t.id = 1
t.r = GetNumRaidMembers()
else
t.mode = "party"
t.id = 0
t.p = GetNumPartyMembers()
end
return iter, t
end
end
trunk/Libs/LibGroupTalents-1.0/LibGroupTalents-1.0.toc New file
0,0 → 1,17
## Interface: 30300
## LoadOnDemand: 1
## Title: Lib: GroupTalents-1.0
## Notes: Library to help with querying unit talents.
## Author: Zek
## Version: $Rev: 51 $
## OptionalDeps: Ace3, LibTalentQuery-1.0
## X-Category: Library
## X-ReleaseDate: $Date$
## X-Website: http://wowace.com/wiki/LibGroupTalents-1.0
## X-License: MIT
## X-Curse-Packaged-Version: r53
## X-Curse-Project-Name: LibGroupTalents-1.0
## X-Curse-Project-ID: libgrouptalents-1-0
## X-Curse-Repository-ID: wow/libgrouptalents-1-0/mainline
 
lib.xml
trunk/Libs/LibGroupTalents-1.0/lib.xml New file
0,0 → 1,3
<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="LibGroupTalents-1.0.lua"/>
</Ui>