From 6ac1945b6459024bca4148f9111d3fb4a0cc293b Mon Sep 17 00:00:00 2001 From: Hosq Date: Sun, 4 Jun 2017 23:07:23 +0300 Subject: [PATCH] fix shield bash and aoe taunts --- Libs/AceAddon-2.0/AceAddon-2.0.lua | 1012 +++ Libs/AceConsole-2.0/AceConsole-2.0.lua | 1898 +++++ Libs/AceDB-2.0/AceDB-2.0.lua | 1497 ++++ Libs/AceDebug-2.0/AceDebug-2.0.lua | 239 + Libs/AceEvent-2.0/AceEvent-2.0.lua | 973 +++ Libs/AceHook-2.1/AceHook-2.1.lua | 569 ++ Libs/AceLibrary/AceLibrary.lua | 757 ++ Libs/AceLocale-2.2/AceLocale-2.2.lua | 538 ++ Libs/AceOO-2.0/AceOO-2.0.lua | 1004 +++ Libs/Babble-Spell-2.2/Babble-Spell-2.2.lua | 7839 ++++++++++++++++++++ Libs/Deformat-2.0/Deformat-2.0.lua | 343 + Libs/Gratuity-2.0/Gratuity-2.0.lua | 220 + Libs/SpellCache-1.0/SpellCache-1.0.lua | 304 + Libs/SpellStatus-1.0/SpellStatus-1.0.lua | 1011 +++ TankBuddyEnh.lua | 28 +- TankBuddyEnh.toc | 22 +- TankBuddyEnh.xml | 2 +- localization.lua | 8 +- 18 files changed, 18256 insertions(+), 8 deletions(-) create mode 100644 Libs/AceAddon-2.0/AceAddon-2.0.lua create mode 100644 Libs/AceConsole-2.0/AceConsole-2.0.lua create mode 100644 Libs/AceDB-2.0/AceDB-2.0.lua create mode 100644 Libs/AceDebug-2.0/AceDebug-2.0.lua create mode 100644 Libs/AceEvent-2.0/AceEvent-2.0.lua create mode 100644 Libs/AceHook-2.1/AceHook-2.1.lua create mode 100644 Libs/AceLibrary/AceLibrary.lua create mode 100644 Libs/AceLocale-2.2/AceLocale-2.2.lua create mode 100644 Libs/AceOO-2.0/AceOO-2.0.lua create mode 100644 Libs/Babble-Spell-2.2/Babble-Spell-2.2.lua create mode 100644 Libs/Deformat-2.0/Deformat-2.0.lua create mode 100644 Libs/Gratuity-2.0/Gratuity-2.0.lua create mode 100644 Libs/SpellCache-1.0/SpellCache-1.0.lua create mode 100644 Libs/SpellStatus-1.0/SpellStatus-1.0.lua diff --git a/Libs/AceAddon-2.0/AceAddon-2.0.lua b/Libs/AceAddon-2.0/AceAddon-2.0.lua new file mode 100644 index 0000000..c7f9337 --- /dev/null +++ b/Libs/AceAddon-2.0/AceAddon-2.0.lua @@ -0,0 +1,1012 @@ +--[[ +Name: AceAddon-2.0 +Revision: $Rev: 17957 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceAddon-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceAddon-2.0 +Description: Base for all Ace addons to inherit from. +Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) AceConsole-2.0 +]] + +local MAJOR_VERSION = "AceAddon-2.0" +local MINOR_VERSION = "$Revision: 17957 $" + +-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end + +local function safecall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + local success, err = pcall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + if not success then geterrorhandler()(err) end +end + +-- Localization +local STANDBY, TITLE, NOTES, VERSION, AUTHOR, DATE, CATEGORY, EMAIL, CREDITS, WEBSITE, CATEGORIES, ABOUT, PRINT_ADDON_INFO +if GetLocale() == "deDE" then + STANDBY = "|cffff5050(Standby)|r" -- capitalized + + TITLE = "Titel" + NOTES = "Anmerkung" + VERSION = "Version" + AUTHOR = "Autor" + DATE = "Datum" + CATEGORY = "Kategorie" + EMAIL = "E-mail" + WEBSITE = "Webseite" + CREDITS = "Credits" -- fix + + ABOUT = "\195\188ber" + PRINT_ADDON_INFO = "Gibt Addondaten aus" + + CATEGORIES = { + ["Action Bars"] = "Aktionsleisten", + ["Auction"] = "Auktion", + ["Audio"] = "Audio", + ["Battlegrounds/PvP"] = "Schlachtfeld/PvP", + ["Buffs"] = "Buffs", + ["Chat/Communication"] = "Chat/Kommunikation", + ["Druid"] = "Druide", + ["Hunter"] = "Jไger", + ["Mage"] = "Magier", + ["Paladin"] = "Paladin", + ["Priest"] = "Priester", + ["Rogue"] = "Schurke", + ["Shaman"] = "Schamane", + ["Warlock"] = "Hexenmeister", + ["Warrior"] = "Krieger", + ["Healer"] = "Heiler", + ["Tank"] = "Tank", -- noone use "Brecher"... + ["Caster"] = "Caster", + ["Combat"] = "Kampf", + ["Compilations"] = "Compilations", -- whats that o_O + ["Data Export"] = "Datenexport", + ["Development Tools"] = "Entwicklungs Tools", + ["Guild"] = "Gilde", + ["Frame Modification"] = "Frame Modifikation", + ["Interface Enhancements"] = "Interface Verbesserungen", + ["Inventory"] = "Inventar", + ["Library"] = "Library", + ["Map"] = "Map", + ["Mail"] = "Mail", + ["Miscellaneous"] = "Diverses", + ["Quest"] = "Quest", + ["Raid"] = "Schlachtzug", + ["Tradeskill"] = "Handelsf\195\164higkeit", + ["UnitFrame"] = "UnitFrame", + } +elseif GetLocale() == "frFR" then + STANDBY = "|cffff5050(attente)|r" + + TITLE = "Titre" + NOTES = "Notes" + VERSION = "Version" + AUTHOR = "Auteur" + DATE = "Date" + CATEGORY = "Cat\195\169gorie" + EMAIL = "E-mail" + WEBSITE = "Site web" + CREDITS = "Credits" -- fix + + ABOUT = "A propos" + PRINT_ADDON_INFO = "Afficher les informations sur l'addon" + + CATEGORIES = { + ["Action Bars"] = "Barres d'action", + ["Auction"] = "H\195\180tel des ventes", + ["Audio"] = "Audio", + ["Battlegrounds/PvP"] = "Champs de bataille/JcJ", + ["Buffs"] = "Buffs", + ["Chat/Communication"] = "Chat/Communication", + ["Druid"] = "Druide", + ["Hunter"] = "Chasseur", + ["Mage"] = "Mage", + ["Paladin"] = "Paladin", + ["Priest"] = "Pr\195\170tre", + ["Rogue"] = "Voleur", + ["Shaman"] = "Chaman", + ["Warlock"] = "D\195\169moniste", + ["Warrior"] = "Guerrier", + ["Healer"] = "Soigneur", + ["Tank"] = "Tank", + ["Caster"] = "Casteur", + ["Combat"] = "Combat", + ["Compilations"] = "Compilations", + ["Data Export"] = "Exportation de donn\195\169es", + ["Development Tools"] = "Outils de d\195\169veloppement", + ["Guild"] = "Guilde", + ["Frame Modification"] = "Modification des fen\195\170tres", + ["Interface Enhancements"] = "Am\195\169liorations de l'interface", + ["Inventory"] = "Inventaire", + ["Library"] = "Biblioth\195\168ques", + ["Map"] = "Carte", + ["Mail"] = "Courrier", + ["Miscellaneous"] = "Divers", + ["Quest"] = "Qu\195\170tes", + ["Raid"] = "Raid", + ["Tradeskill"] = "M\195\169tiers", + ["UnitFrame"] = "Fen\195\170tres d'unit\195\169", + } +elseif GetLocale() == "koKR" then + STANDBY = "|cffff5050(์‚ฌ์šฉ๊ฐ€๋Šฅ)|r" + + TITLE = "์ œ๋ชฉ" + NOTES = "๋…ธํŠธ" + VERSION = "๋ฒ„์ „" + AUTHOR = "์ €์ž‘์ž" + DATE = "๋‚ ์งœ" + CATEGORY = "๋ถ„๋ฅ˜" + EMAIL = "E-mail" + WEBSITE = "์›น์‚ฌ์ดํŠธ" + CREDITS = "Credits" -- fix + + ABOUT = "์ •๋ณด" + PRINT_ADDON_INFO = "์• ๋“œ์˜จ ์ •๋ณด ์ถœ๋ ฅ" + + CATEGORIES = { + ["Action Bars"] = "์•ก์…˜๋ฐ”", + ["Auction"] = "๊ฒฝ๋งค", + ["Audio"] = "์Œํ–ฅ", + ["Battlegrounds/PvP"] = "์ „์žฅ/PvP", + ["Buffs"] = "๋ฒ„ํ”„", + ["Chat/Communication"] = "๋Œ€ํ™”/์˜์‚ฌ์†Œํ†ต", + ["Druid"] = "๋“œ๋ฃจ์ด๋“œ", + ["Hunter"] = "์‚ฌ๋ƒฅ๊พผ", + ["Mage"] = "๋งˆ๋ฒ•์‚ฌ", + ["Paladin"] = "์„ฑ๊ธฐ์‚ฌ", + ["Priest"] = "์‚ฌ์ œ", + ["Rogue"] = "๋„์ ", + ["Shaman"] = "์ฃผ์ˆ ์‚ฌ", + ["Warlock"] = "ํ‘๋งˆ๋ฒ•์‚ฌ", + ["Warrior"] = "์ „์‚ฌ", + ["Healer"] = "ํž๋Ÿฌ", + ["Tank"] = "ํƒฑ์ปค", + ["Caster"] = "์บ์Šคํ„ฐ", + ["Combat"] = "์ „ํˆฌ", + ["Compilations"] = "๋ณตํ•ฉ", + ["Data Export"] = "์ž๋ฃŒ ์ถœ๋ ฅ", + ["Development Tools"] = "๊ฐœ๋ฐœ ๋„๊ตฌ", + ["Guild"] = "๊ธธ๋“œ", + ["Frame Modification"] = "๊ตฌ์กฐ ๋ณ€๊ฒฝ", + ["Interface Enhancements"] = "์ธํ„ฐํŽ˜์ด์Šค ๊ฐ•ํ™”", + ["Inventory"] = "์ธ๋ฒคํ† ๋ฆฌ", + ["Library"] = "๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ", + ["Map"] = "์ง€๋„", + ["Mail"] = "์šฐํŽธ", + ["Miscellaneous"] = "๊ธฐํƒ€", + ["Quest"] = "ํ€˜์ŠคํŠธ", + ["Raid"] = "๊ณต๊ฒฉ๋Œ€", + ["Tradeskill"] = "์ „๋ฌธ๊ธฐ์ˆ ", + ["UnitFrame"] = "์œ ๋‹› ํ”„๋ ˆ์ž„", + } +elseif GetLocale() == "zhTW" then + STANDBY = "|cffff5050(ๅพ…ๅ‘ฝ)|r" + + TITLE = "ๆจ™้กŒ" + NOTES = "่จป่จ˜" + VERSION = "็‰ˆๆœฌ" + AUTHOR = "ไฝœ่€…" + DATE = "ๆ—ฅๆœŸ" + CATEGORY = "้กžๅˆฅ" + EMAIL = "E-mail" + WEBSITE = "็ถฒ็ซ™" + CREDITS = "Credits" -- fix + + ABOUT = "้—œๆ–ผ" + PRINT_ADDON_INFO = "้กฏ็คบๆ’ไปถ่ณ‡่จŠ" + + CATEGORIES = { + ["Action Bars"] = "ๅ‹•ไฝœๅˆ—", + ["Auction"] = "ๆ‹่ณฃ", + ["Audio"] = "้Ÿณๆจ‚", + ["Battlegrounds/PvP"] = "ๆˆฐๅ ด/PvP", + ["Buffs"] = "ๅขž็›Š", + ["Chat/Communication"] = "่Šๅคฉ/้€š่จŠ", + ["Druid"] = "ๅพท้ญฏไผŠ", + ["Hunter"] = "็ตไบบ", + ["Mage"] = "ๆณ•ๅธซ", + ["Paladin"] = "่–้จŽๅฃซ", + ["Priest"] = "็‰งๅธซ", + ["Rogue"] = "็›œ่ณŠ", + ["Shaman"] = "่–ฉๆปฟ", + ["Warlock"] = "่ก“ๅฃซ", + ["Warrior"] = "ๆˆฐๅฃซ", + ["Healer"] = "ๆฒป็™‚่€…", + ["Tank"] = "ๅฆๅ…‹", + ["Caster"] = "ๆ–ฝๆณ•่€…", + ["Combat"] = "ๆˆฐ้ฌฅ", + ["Compilations"] = "็ทจ่ผฏ", + ["Data Export"] = "่ณ‡ๆ–™ๅŒฏๅ‡บ", + ["Development Tools"] = "้–‹็™ผๅทฅๅ…ท", + ["Guild"] = "ๅ…ฌๆœƒ", + ["Frame Modification"] = "ๆก†ๆžถไฟฎๆ”น", + ["Interface Enhancements"] = "ไป‹้ขๅขžๅผท", + ["Inventory"] = "่ƒŒๅŒ…", + ["Library"] = "่ณ‡ๆ–™ๅบซ", + ["Map"] = "ๅœฐๅœ–", + ["Mail"] = "้ƒตไปถ", + ["Miscellaneous"] = "็ถœๅˆ", + ["Quest"] = "ไปปๅ‹™", + ["Raid"] = "ๅœ˜้šŠ", + ["Tradeskill"] = "ๅ•†ๆฅญๆŠ€่ƒฝ", + ["UnitFrame"] = "ๅ–ฎไฝๆก†ๆžถ", + } +elseif GetLocale() == "zhCN" then + STANDBY = "|cffff5050(\230\154\130\230\140\130)|r" + + TITLE = "\230\160\135\233\162\152" + NOTES = "\233\153\132\230\179\168" + VERSION = "\231\137\136\230\156\172" + AUTHOR = "\228\189\156\232\128\133" + DATE = "\230\151\165\230\156\159" + CATEGORY = "\229\136\134\231\177\187" + EMAIL = "\231\148\181\229\173\144\233\130\174\228\187\182" + WEBSITE = "\231\189\145\231\171\153" + CREDITS = "Credits" -- fix + + ABOUT = "\229\133\179\228\186\142" + PRINT_ADDON_INFO = "\229\141\176\229\136\151\229\135\186\230\143\146\228\187\182\228\191\161\230\129\175" + + CATEGORIES = { + ["Action Bars"] = "\229\138\168\228\189\156\230\157\161", + ["Auction"] = "\230\139\141\229\141\150", + ["Audio"] = "\233\159\179\233\162\145", + ["Battlegrounds/PvP"] = "\230\136\152\229\156\186/PvP", + ["Buffs"] = "\229\162\158\231\155\138\233\173\148\230\179\149", + ["Chat/Communication"] = "\232\129\138\229\164\169/\228\186\164\230\181\129", + ["Druid"] = "\229\190\183\233\178\129\228\188\138", + ["Hunter"] = "\231\140\142\228\186\186", + ["Mage"] = "\230\179\149\229\184\136", + ["Paladin"] = "\229\156\163\233\170\145\229\163\171", + ["Priest"] = "\231\137\167\229\184\136", + ["Rogue"] = "\231\155\151\232\180\188", + ["Shaman"] = "\232\144\168\230\187\161\231\165\173\229\143\184", + ["Warlock"] = "\230\156\175\229\163\171", + ["Warrior"] = "\230\136\152\229\163\171", +-- ["Healer"] = "\230\178\187\231\150\151\228\191\157\233\154\156", +-- ["Tank"] = "\232\191\145\230\136\152\230\142\167\229\136\182", +-- ["Caster"] = "\232\191\156\231\168\139\232\190\147\229\135\186", + ["Combat"] = "\230\136\152\230\150\151", + ["Compilations"] = "\231\188\150\232\175\145", + ["Data Export"] = "\230\149\176\230\141\174\229\175\188\229\135\186", + ["Development Tools"] = "\229\188\128\229\143\145\229\183\165\229\133\183", + ["Guild"] = "\229\133\172\228\188\154", + ["Frame Modification"] = "\230\161\134\230\158\182\228\191\174\230\148\185", + ["Interface Enhancements"] = "\231\149\140\233\157\162\229\162\158\229\188\186", + ["Inventory"] = "\232\131\140\229\140\133", + ["Library"] = "\229\186\147", + ["Map"] = "\229\156\176\229\155\190", + ["Mail"] = "\233\130\174\228\187\182", + ["Miscellaneous"] = "\230\157\130\233\161\185", + ["Quest"] = "\228\187\187\229\138\161", + ["Raid"] = "\229\155\162\233\152\159", + ["Tradeskill"] = "\229\149\134\228\184\154\230\138\128\232\131\189", + ["UnitFrame"] = "\229\164\180\229\131\143\230\161\134\230\158\182", + } +else -- enUS + STANDBY = "|cffff5050(standby)|r" + + TITLE = "Title" + NOTES = "Notes" + VERSION = "Version" + AUTHOR = "Author" + DATE = "Date" + CATEGORY = "Category" + EMAIL = "E-mail" + WEBSITE = "Website" + CREDITS = "Credits" + + ABOUT = "About" + PRINT_ADDON_INFO = "Print out addon info" + + CATEGORIES = { + ["Action Bars"] = "Action Bars", + ["Auction"] = "Auction", + ["Audio"] = "Audio", + ["Battlegrounds/PvP"] = "Battlegrounds/PvP", + ["Buffs"] = "Buffs", + ["Chat/Communication"] = "Chat/Communication", + ["Druid"] = "Druid", + ["Hunter"] = "Hunter", + ["Mage"] = "Mage", + ["Paladin"] = "Paladin", + ["Priest"] = "Priest", + ["Rogue"] = "Rogue", + ["Shaman"] = "Shaman", + ["Warlock"] = "Warlock", + ["Warrior"] = "Warrior", + ["Healer"] = "Healer", + ["Tank"] = "Tank", + ["Caster"] = "Caster", + ["Combat"] = "Combat", + ["Compilations"] = "Compilations", + ["Data Export"] = "Data Export", + ["Development Tools"] = "Development Tools", + ["Guild"] = "Guild", + ["Frame Modification"] = "Frame Modification", + ["Interface Enhancements"] = "Interface Enhancements", + ["Inventory"] = "Inventory", + ["Library"] = "Library", + ["Map"] = "Map", + ["Mail"] = "Mail", + ["Miscellaneous"] = "Miscellaneous", + ["Quest"] = "Quest", + ["Raid"] = "Raid", + ["Tradeskill"] = "Tradeskill", + ["UnitFrame"] = "UnitFrame", + } +end + +setmetatable(CATEGORIES, { __index = function(self, key) -- case-insensitive + local lowerKey = string.lower(key) + for k,v in pairs(CATEGORIES) do + if string.lower(k) == lowerKey then + return v + end + end +end }) + +-- Create the library object + +local AceOO = AceLibrary("AceOO-2.0") +local AceAddon = AceOO.Class() +local AceEvent +local AceConsole +local AceModuleCore + +function AceAddon:ToString() + return "AceAddon" +end + +local function print(text) + DEFAULT_CHAT_FRAME:AddMessage(text) +end + +function AceAddon:ADDON_LOADED(name) + while table.getn(self.nextAddon) > 0 do + local addon = table.remove(self.nextAddon, 1) + table.insert(self.addons, addon) + if not self.addons[name] then + self.addons[name] = addon + end + self:InitializeAddon(addon, name) + end +end + +local function RegisterOnEnable(self) + if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage then -- HACK + AceAddon.playerLoginFired = true + end + if AceAddon.playerLoginFired then + AceAddon.addonsStarted[self] = true + if (type(self.IsActive) ~= "function" or self:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(self) or AceModuleCore:IsModuleActive(self)) then + local current = self.class + while true do + if current == AceOO.Class then + break + end + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedEnable) == "function" then + safecall(mixin.OnEmbedEnable,mixin,self) + end + end + end + current = current.super + end + if type(self.OnEnable) == "function" then + safecall(self.OnEnable,self) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonEnabled", self) + end + end + else + if not AceAddon.addonsToOnEnable then + AceAddon.addonsToOnEnable = {} + end + table.insert(AceAddon.addonsToOnEnable, self) + end +end + +local function stripSpaces(text) + if type(text) == "string" then + return (string.gsub(string.gsub(text, "^%s*(.-)%s*$", "%1"), "%s%s+", " ")) + end + return text +end + +function AceAddon:InitializeAddon(addon, name) + if addon.name == nil then + addon.name = name + end + if GetAddOnMetadata then + -- TOC checks + if addon.title == nil then + addon.title = GetAddOnMetadata(name, "Title") + end + if addon.title then + local num = string.find(addon.title, " |cff7fff7f %-Ace2%-|r$") + if num then + addon.title = string.sub(addon.title, 1, num - 1) + end + addon.title = stripSpaces(addon.title) + end + + if addon.notes == nil then + addon.notes = GetAddOnMetadata(name, "Notes") + addon.notes = stripSpaces(addon.notes) + end + if addon.version == nil then + addon.version = GetAddOnMetadata(name, "Version") + end + if addon.version then + if string.find(addon.version, "%$Revision: (%d+) %$") then + addon.version = string.gsub(addon.version, "%$Revision: (%d+) %$", "%1") + elseif string.find(addon.version, "%$Rev: (%d+) %$") then + addon.version = string.gsub(addon.version, "%$Rev: (%d+) %$", "%1") + elseif string.find(addon.version, "%$LastChangedRevision: (%d+) %$") then + addon.version = string.gsub(addon.version, "%$LastChangedRevision: (%d+) %$", "%1") + end + end + addon.version = stripSpaces(addon.version) + if addon.author == nil then + addon.author = GetAddOnMetadata(name, "Author") + addon.author = stripSpaces(addon.author) + end + if addon.credits == nil then + addon.credits = GetAddOnMetadata(name, "X-Credits") + addon.credits = stripSpaces(addon.credits) + end + if addon.date == nil then + addon.date = GetAddOnMetadata(name, "X-Date") or GetAddOnMetadata(name, "X-ReleaseDate") + end + if addon.date then + if string.find(addon.date, "%$Date: (.-) %$") then + addon.date = string.gsub(addon.date, "%$Date: (.-) %$", "%1") + elseif string.find(addon.date, "%$LastChangedDate: (.-) %$") then + addon.date = string.gsub(addon.date, "%$LastChangedDate: (.-) %$", "%1") + end + end + addon.date = stripSpaces(addon.date) + + if addon.category == nil then + addon.category = GetAddOnMetadata(name, "X-Category") + addon.category = stripSpaces(addon.category) + end + if addon.email == nil then + addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email") + addon.email = stripSpaces(addon.email) + end + if addon.website == nil then + addon.website = GetAddOnMetadata(name, "X-Website") + addon.website = stripSpaces(addon.website) + end + end + local current = addon.class + while true do + if current == AceOO.Class then + break + end + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedInitialize) == "function" then + mixin:OnEmbedInitialize(addon, name) + end + end + end + current = current.super + end + if type(addon.OnInitialize) == "function" then + safecall(addon.OnInitialize, addon, name) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonInitialized", addon) + end + RegisterOnEnable(addon) +end + +function AceAddon.prototype:PrintAddonInfo() + local x + if self.title then + x = "|cffffff7f" .. tostring(self.title) .. "|r" + elseif self.name then + x = "|cffffff7f" .. tostring(self.name) .. "|r" + else + x = "|cffffff7f<" .. tostring(self.class) .. " instance>|r" + end + if type(self.IsActive) == "function" then + if not self:IsActive() then + x = x .. " " .. STANDBY + end + end + if self.version then + x = x .. " - |cffffff7f" .. tostring(self.version) .. "|r" + end + if self.notes then + x = x .. " - " .. tostring(self.notes) + end + print(x) + if self.author then + print(" - |cffffff7f" .. AUTHOR .. ":|r " .. tostring(self.author)) + end + if self.credits then + print(" - |cffffff7f" .. CREDITS .. ":|r " .. tostring(self.credits)) + end + if self.date then + print(" - |cffffff7f" .. DATE .. ":|r " .. tostring(self.date)) + end + if self.category then + local category = CATEGORIES[self.category] + if category then + print(" - |cffffff7f" .. CATEGORY .. ":|r " .. category) + end + end + if self.email then + print(" - |cffffff7f" .. EMAIL .. ":|r " .. tostring(self.email)) + end + if self.website then + print(" - |cffffff7f" .. WEBSITE .. ":|r " .. tostring(self.website)) + end +end + +local options +function AceAddon:GetAceOptionsDataTable(target) + if not options then + options = { + about = { + name = ABOUT, + desc = PRINT_ADDON_INFO, + type = "execute", + func = "PrintAddonInfo", + order = -1, + } + } + end + return options +end + +function AceAddon:PLAYER_LOGIN() + self.playerLoginFired = true + if self.addonsToOnEnable then + while table.getn(self.addonsToOnEnable) > 0 do + local addon = table.remove(self.addonsToOnEnable, 1) + self.addonsStarted[addon] = true + if (type(addon.IsActive) ~= "function" or addon:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(addon) or AceModuleCore:IsModuleActive(addon)) then + local current = addon.class + while true do + if current == AceOO.Class then + break + end + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedEnable) == "function" then + safecall(mixin.OnEmbedEnable,mixin,addon) + end + end + end + current = current.super + end + if type(addon.OnEnable) == "function" then + safecall(addon.OnEnable,addon) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonEnabled", addon) + end + end + end + self.addonsToOnEnable = nil + end +end + +function AceAddon.prototype:Inject(t) + AceAddon:argCheck(t, 2, "table") + for k,v in pairs(t) do + self[k] = v + end +end + +function AceAddon.prototype:init() + if not AceEvent then + error(MAJOR_VERSION .. " requires AceEvent-2.0", 4) + end + AceAddon.super.prototype.init(self) + + self.super = self.class.prototype + + AceAddon:RegisterEvent("ADDON_LOADED", "ADDON_LOADED", true) + table.insert(AceAddon.nextAddon, self) +end + +function AceAddon.prototype:ToString() + local x + if type(self.title) == "string" then + x = self.title + elseif type(self.name) == "string" then + x = self.name + else + x = "<" .. tostring(self.class) .. " instance>" + end + if (type(self.IsActive) == "function" and not self:IsActive()) or (AceModuleCore and AceModuleCore:IsModule(addon) and AceModuleCore:IsModuleActive(addon)) then + x = x .. " " .. STANDBY + end + return x +end + +AceAddon.new = function(self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) + local class = AceAddon:pcall(AceOO.Classpool, self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) + return class:new() +end + +local function external(self, major, instance) + if major == "AceEvent-2.0" then + AceEvent = instance + + AceEvent:embed(self) + + self:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true) + elseif major == "AceConsole-2.0" then + AceConsole = instance + + local slashCommands = { "/ace2" } + local _,_,_,enabled,loadable = GetAddOnInfo("Ace") + if not enabled or not loadable then + table.insert(slashCommands, "/ace") + end + local function listAddon(addon, depth) + if not depth then + depth = 0 + end + + local s = string.rep(" ", depth) .. " - " .. tostring(addon) + if rawget(addon, 'version') then + s = s .. " - |cffffff7f" .. tostring(addon.version) .. "|r" + end + if rawget(addon, 'slashCommand') then + s = s .. " |cffffff7f(" .. tostring(addon.slashCommand) .. ")|r" + end + print(s) + if type(rawget(addon, 'modules')) == "table" then + local i = 0 + for k,v in pairs(addon.modules) do + i = i + 1 + if i == 6 then + print(string.rep(" ", depth + 1) .. " - more...") + break + else + listAddon(v, depth + 1) + end + end + end + end + local function listNormalAddon(i) + local name,_,_,enabled,loadable = GetAddOnInfo(i) + if not loadable then + enabled = false + end + if self.addons[name] then + local addon = self.addons[name] + if not AceCoreAddon or not AceCoreAddon:IsModule(addon) then + listAddon(addon) + end + else + local s = " - " .. tostring(GetAddOnMetadata(i, "Title") or name) + local version = GetAddOnMetadata(i, "Version") + if version then + if string.find(version, "%$Revision: (%d+) %$") then + version = string.gsub(version, "%$Revision: (%d+) %$", "%1") + elseif string.find(version, "%$Rev: (%d+) %$") then + version = string.gsub(version, "%$Rev: (%d+) %$", "%1") + elseif string.find(version, "%$LastChangedRevision: (%d+) %$") then + version = string.gsub(version, "%$LastChangedRevision: (%d+) %$", "%1") + end + s = s .. " - |cffffff7f" .. version .. "|r" + end + if not enabled then + s = s .. " |cffff0000(disabled)|r" + end + if IsAddOnLoadOnDemand(i) then + s = s .. " |cff00ff00[LoD]|r" + end + print(s) + end + end + local function mySort(alpha, bravo) + return tostring(alpha) < tostring(bravo) + end + AceConsole.RegisterChatCommand(self, slashCommands, { + desc = "AddOn development framework", + name = "Ace2", + type = "group", + args = { + about = { + desc = "Get information about Ace2", + name = "About", + type = "execute", + func = function() + print("|cffffff7fAce2|r - |cffffff7f2.0." .. string.gsub(MINOR_VERSION, "%$Revision: (%d+) %$", "%1") .. "|r - AddOn development framework") + print(" - |cffffff7f" .. AUTHOR .. ":|r Ace Development Team") + print(" - |cffffff7f" .. WEBSITE .. ":|r http://www.wowace.com/") + end + }, + list = { + desc = "List addons", + name = "List", + type = "group", + args = { + ace2 = { + desc = "List addons using Ace2", + name = "Ace2", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0") + table.sort(self.addons, mySort) + for _,v in ipairs(self.addons) do + if not AceCoreAddon or not AceCoreAddon:IsModule(v) then + listAddon(v) + end + end + end + }, + all = { + desc = "List all addons", + name = "All", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0") + local count = GetNumAddOns() + for i = 1, count do + listNormalAddon(i) + end + end + }, + enabled = { + desc = "List all enabled addons", + name = "Enabled", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0") + local count = GetNumAddOns() + for i = 1, count do + local _,_,_,enabled,loadable = GetAddOnInfo(i) + if enabled and loadable then + listNormalAddon(i) + end + end + end + }, + disabled = { + desc = "List all disabled addons", + name = "Disabled", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0") + local count = GetNumAddOns() + for i = 1, count do + local _,_,_,enabled,loadable = GetAddOnInfo(i) + if not enabled or not loadable then + listNormalAddon(i) + end + end + end + }, + lod = { + desc = "List all LoadOnDemand addons", + name = "LoadOnDemand", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0") + local count = GetNumAddOns() + for i = 1, count do + if IsAddOnLoadOnDemand(i) then + listNormalAddon(i) + end + end + end + }, + ace1 = { + desc = "List all addons using Ace1", + name = "Ace 1.x", + type = "execute", + func = function() + print("|cffffff7fAddon list:|r") + local count = GetNumAddOns() + for i = 1, count do + local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i) + if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then + listNormalAddon(i) + end + end + end + }, + libs = { + desc = "List all libraries using AceLibrary", + name = "Libraries", + type = "execute", + func = function() + if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then + print("|cffffff7fLibrary list:|r") + for name, data in pairs(AceLibrary.libs) do + local s + if data.minor then + s = " - " .. tostring(name) .. "." .. tostring(data.minor) + else + s = " - " .. tostring(name) + end + if AceLibrary(name).slashCommand then + s = s .. " |cffffff7f(" .. tostring(AceLibrary(name).slashCommand) .. "|cffffff7f)" + end + print(s) + end + end + end + }, + search = { + desc = "Search by name", + name = "Search", + type = "text", + usage = "", + input = true, + get = false, + set = function(...) + for i,v in ipairs(arg) do + arg[i] = string.lower(string.gsub(string.gsub(v, '%*', '.*'), '%%', '%%%%')) + end + local count = GetNumAddOns() + for i = 1, count do + local name = GetAddOnInfo(i) + local good = true + for _,v in ipairs(arg) do + if not string.find(string.lower(name), v) then + good = false + break + end + end + if good then + listNormalAddon(i) + end + end + end + } + }, + }, + enable = { + desc = "Enable addon", + name = "Enable", + type = "text", + usage = "", + get = false, + set = function(text) + local name,title,_,_,_,reason = GetAddOnInfo(text) + if reason == "MISSING" then + print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text)) + else + EnableAddOn(text) + print(string.format("|cffffff7fAce2:|r %s is now enabled", title or name)) + end + end, + }, + disable = { + desc = "Disable addon", + name = "Disable", + type = "text", + usage = "", + get = false, + set = function(text) + local name,title,_,_,_,reason = GetAddOnInfo(text) + if reason == "MISSING" then + print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text)) + else + DisableAddOn(text) + print(string.format("|cffffff7fAce2:|r %s is now disabled", title or name)) + end + end, + }, + load = { + desc = "Load addon", + name = "Load", + type = "text", + usage = "", + get = false, + set = function(text) + local name,title,_,_,loadable,reason = GetAddOnInfo(text) + if reason == "MISSING" then + print(string.format("|cffffff7fAce2:|r AddOn %q does not exist.", text)) + elseif not loadable then + print(string.format("|cffffff7fAce2:|r AddOn %q is not loadable. Reason: %s", text, reason)) + else + LoadAddOn(text) + print(string.format("|cffffff7fAce2:|r %s is now loaded", title or name)) + end + end + }, + info = { + desc = "Display information", + name = "Information", + type = "execute", + func = function() + local mem, threshold = gcinfo() + print(string.format(" - |cffffff7fMemory usage [|r%.3f MiB|cffffff7f]|r", mem / 1024)) + print(string.format(" - |cffffff7fThreshold [|r%.3f MiB|cffffff7f]|r", threshold / 1024)) + print(string.format(" - |cffffff7fFramerate [|r%.0f fps|cffffff7f]|r", GetFramerate())) + local bandwidthIn, bandwidthOut, latency = GetNetStats() + bandwidthIn, bandwidthOut = floor(bandwidthIn * 1024), floor(bandwidthOut * 1024) + print(string.format(" - |cffffff7fLatency [|r%.0f ms|cffffff7f]|r", latency)) + print(string.format(" - |cffffff7fBandwidth in [|r%.0f B/s|cffffff7f]|r", bandwidthIn)) + print(string.format(" - |cffffff7fBandwidth out [|r%.0f B/s|cffffff7f]|r", bandwidthOut)) + print(string.format(" - |cffffff7fTotal addons [|r%d|cffffff7f]|r", GetNumAddOns())) + print(string.format(" - |cffffff7fAce2 addons [|r%d|cffffff7f]|r", table.getn(self.addons))) + local ace = 0 + local enabled = 0 + local disabled = 0 + local lod = 0 + for i = 1, GetNumAddOns() do + local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i) + if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then + ace = ace + 1 + end + if IsAddOnLoadOnDemand(i) then + lod = lod + 1 + end + local _,_,_,IsActive,loadable = GetAddOnInfo(i) + if not IsActive or not loadable then + disabled = disabled + 1 + else + enabled = enabled + 1 + end + end + print(string.format(" - |cffffff7fAce 1.x addons [|r%d|cffffff7f]|r", ace)) + print(string.format(" - |cffffff7fLoadOnDemand addons [|r%d|cffffff7f]|r", lod)) + print(string.format(" - |cffffff7fenabled addons [|r%d|cffffff7f]|r", enabled)) + print(string.format(" - |cffffff7fdisabled addons [|r%d|cffffff7f]|r", disabled)) + local libs = 0 + if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then + for _ in pairs(AceLibrary.libs) do + libs = libs + 1 + end + end + print(string.format(" - |cffffff7fAceLibrary instances [|r%d|cffffff7f]|r", libs)) + end + } + } + }) + elseif major == "AceModuleCore-2.0" then + AceModuleCore = instance + end +end + +local function activate(self, oldLib, oldDeactivate) + AceAddon = self + + if oldLib then + self.playerLoginFired = oldLib.playerLoginFired or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage + self.addonsToOnEnable = oldLib.addonsToOnEnable + self.addons = oldLib.addons + self.nextAddon = oldLib.nextAddon + self.addonsStarted = oldLib.addonsStarted + end + if not self.addons then + self.addons = {} + end + if not self.nextAddon then + self.nextAddon = {} + end + if not self.addonsStarted then + self.addonsStarted = {} + end + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceAddon, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) +AceAddon = AceLibrary(MAJOR_VERSION) diff --git a/Libs/AceConsole-2.0/AceConsole-2.0.lua b/Libs/AceConsole-2.0/AceConsole-2.0.lua new file mode 100644 index 0000000..6700cee --- /dev/null +++ b/Libs/AceConsole-2.0/AceConsole-2.0.lua @@ -0,0 +1,1898 @@ +--[[ +Name: AceConsole-2.0 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceConsole-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceConsole-2.0 +Description: Mixin to allow for input/output capabilities. This uses the + AceOptions data table format to determine input. + http://wiki.wowace.com/index.php/AceOptions_data_table +Dependencies: AceLibrary, AceOO-2.0 +]] + +local MAJOR_VERSION = "AceConsole-2.0" +local MINOR_VERSION = "$Revision: 17638 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end + +local MAP_ONOFF, USAGE, IS_CURRENTLY_SET_TO, IS_NOW_SET_TO, IS_NOT_A_VALID_OPTION_FOR, IS_NOT_A_VALID_VALUE_FOR, NO_OPTIONS_AVAILABLE, OPTION_HANDLER_NOT_FOUND, OPTION_HANDLER_NOT_VALID, OPTION_IS_DISABLED +if GetLocale() == "deDE" then + MAP_ONOFF = { [false] = "|cffff0000Aus|r", [true] = "|cff00ff00An|r" } + USAGE = "Benutzung" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r steht momentan auf |cffffff7f[|r%s|cffffff7f]|r" + IS_NOW_SET_TO = "|cffffff7f%s|r ist nun auf |cffffff7f[|r%s|cffffff7f]|r gesetzt" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] ist keine g\195\188ltige Option f\195\188r |cffffff7f%s|r" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] ist kein g\195\188ltiger Wert f\195\188r |cffffff7f%s|r" + NO_OPTIONS_AVAILABLE = "Keine Optionen verfรผgbar" + OPTION_HANDLER_NOT_FOUND = "Optionen handler |cffffff7f%q|r nicht gefunden." + OPTION_HANDLER_NOT_VALID = "Optionen handler nicht g\195\188ltig." + OPTION_IS_DISABLED = "Option |cffffff7f%s|r deaktiviert." +elseif GetLocale() == "frFR" then + MAP_ONOFF = { [false] = "|cffff0000Inactif|r", [true] = "|cff00ff00Actif|r" } + USAGE = "Utilisation" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r est actuellement positionn\195\169 sur |cffffff7f[|r%s|cffffff7f]|r" + IS_NOW_SET_TO = "|cffffff7f%s|r est maintenant positionn\195\169 sur |cffffff7f[|r%s|cffffff7f]|r" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] n'est pas une option valide pour |cffffff7f%s|r" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] n'est pas une valeur valide pour |cffffff7f%s|r" + NO_OPTIONS_AVAILABLE = "Pas d'options disponibles" + OPTION_HANDLER_NOT_FOUND = "Le gestionnaire d'option |cffffff7f%q|r n'a pas \195\169t\195\169 trouv\195\169." + OPTION_HANDLER_NOT_VALID = "Le gestionnaire d'option n'est pas valide." + OPTION_IS_DISABLED = "L'option |cffffff7f%s|r est d\195\169sactiv\195\169e." +elseif GetLocale() == "koKR" then + MAP_ONOFF = { [false] = "|cffff0000๋”|r", [true] = "|cff00ff00์ผฌ|r" } + USAGE = "์‚ฌ์šฉ๋ฒ•" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r|1์€;๋Š”; ํ˜„์žฌ ์ƒํƒœ๋Š” |cffffff7f[|r%s|cffffff7f]|r|1์œผ๋กœ;๋กœ; ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค" + IS_NOW_SET_TO = "|cffffff7f%s|r|1์„;๋ฅผ; |cffffff7f[|r%s|cffffff7f]|r ์ƒํƒœ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r]|1์€;๋Š”; |cffffff7f%s|r์—์„œ ์‚ฌ์šฉ๋ถˆ๊ฐ€๋Šฅํ•œ ์„ค์ •์ž…๋‹ˆ๋‹ค" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r]|1์€;๋Š”; |cffffff7f%s|r์—์„œ ์‚ฌ์šฉ๋ถˆ๊ฐ€๋Šฅํ•œ ์„ค์ •๊ฐ’์ž…๋‹ˆ๋‹ค" + NO_OPTIONS_AVAILABLE = "๊ฐ€๋Šฅํ•œ ์„ค์ •์ด ์—†์Šต๋‹ˆ๋‹ค" + OPTION_HANDLER_NOT_FOUND = "์„ค์ • ์กฐ์ •๊ฐ’์ธ |cffffff7f%q|r|1์„;๋ฅผ; ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค." + OPTION_HANDLER_NOT_VALID = "์„ค์ • ์กฐ์ •๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค." + OPTION_IS_DISABLED = "|cffffff7f%s|r ์„ค์ •์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค." +elseif GetLocale() == "zhCN" then + MAP_ONOFF = { [false] = "|cffff0000\229\133\179\233\151\173|r", [true] = "|cff00ff00\229\188\128\229\144\175|r" } + USAGE = "\231\148\168\230\179\149" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r \229\189\147\229\137\141\232\162\171\232\174\190\231\189\174 |cffffff7f[|r%s|cffffff7f]|r" + IS_NOW_SET_TO = "|cffffff7f%s|r \231\142\176\229\156\168\232\162\171\232\174\190\231\189\174\228\184\186 |cffffff7f[|r%s|cffffff7f]|r" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] \228\184\141\230\152\175\228\184\128\228\184\170\230\156\137\230\149\136\231\154\132\233\128\137\233\161\185 \228\184\186 |cffffff7f%s|r" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] \228\184\141\230\152\175\228\184\128\228\184\170\230\156\137\230\149\136\229\128\188 \228\184\186 |cffffff7f%s|r" + NO_OPTIONS_AVAILABLE = "\230\178\161\230\156\137\233\128\137\233\161\185\229\143\175\231\148\168" + OPTION_HANDLER_NOT_FOUND = "\233\128\137\233\161\185\229\164\132\231\144\134\231\168\139\229\186\143 |cffffff7f%q|r \230\178\161\230\159\165\230\137\190." + OPTION_HANDLER_NOT_VALID = "\233\128\137\233\161\185\229\164\132\231\144\134\231\168\139\229\186\143 \230\151\160\230\149\136." + OPTION_IS_DISABLED = "\233\128\137\233\161\185 |cffffff7f%s|r \228\184\141\229\174\140\230\149\180." +elseif GetLocale() == "zhTW" then + MAP_ONOFF = { [false] = "|cffff0000้—œ้–‰|r", [true] = "|cff00ff00้–‹ๅ•Ÿ|r" } + USAGE = "็”จๆณ•" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r ็›ฎๅ‰็š„่จญๅฎš็‚บ |cffffff7f[|r%s|cffffff7f]|r" + IS_NOW_SET_TO = "|cffffff7f%s|r ็พๅœจ่ขซ่จญๅฎš็‚บ |cffffff7f[|r%s|cffffff7f]|r" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] ๆ˜ฏไธ€ๅ€‹ไธ็ฌฆๅˆ่ฆๅฎš็š„้ธ้ …๏ผŒๅฐ |cffffff7f%s|r" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] ๆ˜ฏไธ€ๅ€‹ไธ็ฌฆๅˆ่ฆๅฎš็š„ๆ•ธๅ€ผ๏ผŒๅฐ |cffffff7f%s|r" + NO_OPTIONS_AVAILABLE = "ๆฒ’ๆœ‰ๅฏ็”จ็š„้ธ้ …่™•็†ๅ™จใ€‚" + OPTION_HANDLER_NOT_FOUND = "ๆ‰พไธๅˆฐ |cffffff7f%q|r ้ธ้ …่™•็†ๅ™จใ€‚" + OPTION_HANDLER_NOT_VALID = "้ธ้ …่™•็†ๅ™จไธ็ฌฆๅˆ่ฆๅฎšใ€‚" + OPTION_IS_DISABLED = "|cffffff7f%s|r ๅทฒ่ขซๅœ็”จใ€‚" +else -- enUS + MAP_ONOFF = { [false] = "|cffff0000Off|r", [true] = "|cff00ff00On|r" } + USAGE = "Usage" + IS_CURRENTLY_SET_TO = "|cffffff7f%s|r is currently set to |cffffff7f[|r%s|cffffff7f]|r" + IS_NOW_SET_TO = "|cffffff7f%s|r is now set to |cffffff7f[|r%s|cffffff7f]|r" + IS_NOT_A_VALID_OPTION_FOR = "[|cffffff7f%s|r] is not a valid option for |cffffff7f%s|r" + IS_NOT_A_VALID_VALUE_FOR = "[|cffffff7f%s|r] is not a valid value for |cffffff7f%s|r" + NO_OPTIONS_AVAILABLE = "No options available" + OPTION_HANDLER_NOT_FOUND = "Option handler |cffffff7f%q|r not found." + OPTION_HANDLER_NOT_VALID = "Option handler not valid." + OPTION_IS_DISABLED = "Option |cffffff7f%s|r is disabled." +end + +local NONE = NONE or "None" + +local AceOO = AceLibrary("AceOO-2.0") +local AceEvent + +local AceConsole = AceOO.Mixin { "Print", "PrintComma", "CustomPrint", "RegisterChatCommand" } +local Dewdrop + +local _G = getfenv(0) + +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local function print(text, name, r, g, b, frame, delay) + if not text or string.len(text) == 0 then + text = " " + end + if not name or name == AceConsole then + (frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, nil, delay or 5) + else + (frame or DEFAULT_CHAT_FRAME):AddMessage("|cffffff78" .. tostring(name) .. ":|r " .. text, r, g, b, nil, delay or 5) + end +end + +local tmp +function AceConsole:CustomPrint(r, g, b, frame, delay, connector, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + a1 = tostring(a1) + if string.find(a1, "%%") then + print(string.format(a1, tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20)), self, r, g, b, frame or self.printFrame, delay) + else + if not tmp then + tmp = {} + end + tmp[1] = a1 + tmp[2] = a2 + tmp[3] = a3 + tmp[4] = a4 + tmp[5] = a5 + tmp[6] = a6 + tmp[7] = a7 + tmp[8] = a8 + tmp[9] = a9 + tmp[10] = a10 + tmp[11] = a11 + tmp[12] = a12 + tmp[13] = a13 + tmp[14] = a14 + tmp[15] = a15 + tmp[16] = a16 + tmp[17] = a17 + tmp[18] = a18 + tmp[19] = a19 + tmp[20] = a20 + local n = 20 + while tmp[n] == nil do + n = n - 1 + end + table_setn(tmp, n) + for k = 1, n do + tmp[k] = tostring(tmp[k]) + end + print(table.concat(tmp, connector or " "), self, r, g, b, frame or self.printFrame, delay) + for k,v in pairs(tmp) do + tmp[k] = nil + end + table_setn(tmp, 0) + end +end + +function AceConsole:Print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + return AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, " ", a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + +function AceConsole:PrintComma(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + return AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, ", ", a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + +local work +local argwork + +local string_gfind = string.gmatch or string.gfind + +local function findTableLevel(self, options, chat, text, index, passTable) + if not index then + index = 1 + if work then + for k,v in pairs(work) do + work[k] = nil + end + table_setn(work, 0) + for k,v in pairs(argwork) do + argwork[k] = nil + end + table_setn(argwork, 0) + else + work = {} + argwork = {} + end + local len = string.len(text) + local count + repeat + text, count = string.gsub(text, "(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[[^%]]-) (.-%]|h|r)", "%1\001%2") + until count == 0 + text = string.gsub(text, "(%]|h|r)(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[)", "%1 %2") + for token in string_gfind(text, "([^%s]+)") do + local token = token + local num = tonumber(token) + if num then + token = num + else + token = string.gsub(token, "\001", " ") + end + table.insert(work, token) + end + end + + local path = chat + for i = 1, index - 1 do + path = path .. " " .. tostring(work[i]) + end + + if type(options.args) == "table" then + local disabled, hidden = options.disabled, options.cmdHidden or options.hidden + if hidden then + if type(hidden) == "function" then + hidden = hidden() + elseif type(hidden) == "string" then + local handler = options.handler or self + if type(handler[hidden]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, hidden)) + end + hidden = handler[hidden](handler) + end + end + if hidden then + disabled = true + elseif disabled then + if type(disabled) == "function" then + disabled = disabled() + elseif type(disabled) == "string" then + local handler = options.handler or self + if type(handler[disabled]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, disabled)) + end + disabled = handler[disabled](handler) + end + end + if not disabled then + local next = work[index] and string.lower(work[index]) + if next then + for k,v in pairs(options.args) do + local good = false + if string.lower(k) == next then + good = true + elseif type(v.aliases) == "table" then + for _,alias in ipairs(v.aliases) do + if string.lower(alias) == next then + good = true + break + end + end + elseif type(v.aliases) == "string" and string.lower(v.aliases) == next then + good = true + end + if good then + return findTableLevel(options.handler or self, v, chat, text, index + 1, options.pass and options or nil) + end + end + end + end + end + for i = index, table.getn(work) do + table.insert(argwork, work[i]) + end + return options, path, argwork, options.handler or self, passTable, passTable and work[index - 1] +end + +local function validateOptionsMethods(self, options, position) + if type(options) ~= "table" then + return "Options must be a table.", position + end + self = options.handler or self + if options.type == "execute" then + if options.func and type(options.func) ~= "string" and type(options.func) ~= "function" then + return "func must be a string or function", position + end + if options.func and type(options.func) == "string" and type(self[options.func]) ~= "function" then + return string.format("%q is not a proper function", options.func), position + end + else + if options.get then + if type(options.get) ~= "string" and type(options.get) ~= "function" then + return "get must be a string or function", position + end + if type(options.get) == "string" and type(self[options.get]) ~= "function" then + return string.format("%q is not a proper function", options.get), position + end + end + if options.set then + if type(options.set) ~= "string" and type(options.set) ~= "function" then + return "set must be a string or function", position + end + if type(options.set) == "string" and type(self[options.set]) ~= "function" then + return string.format("%q is not a proper function", options.set), position + end + end + if options.validate and type(options.validate) ~= "table" then + if type(options.validate) ~= "string" and type(options.validate) ~= "function" then + return "validate must be a string or function", position + end + if type(options.validate) == "string" and type(self[options.validate]) ~= "function" then + return string.format("%q is not a proper function", options.validate), position + end + end + end + if options.disabled and type(options.disabled) == "string" and type(self[options.disabled]) ~= "function" then + return string.format("%q is not a proper function", options.disabled), position + end + if options.cmdHidden and type(options.cmdHidden) == "string" and type(self[options.cmdHidden]) ~= "function" then + return string.format("%q is not a proper function", options.cmdHidden), position + end + if options.guiHidden and type(options.guiHidden) == "string" and type(self[options.guiHidden]) ~= "function" then + return string.format("%q is not a proper function", options.guiHidden), position + end + if options.hidden and type(options.hidden) == "string" and type(self[options.hidden]) ~= "function" then + return string.format("%q is not a proper function", options.hidden), position + end + if options.type == "group" and type(options.args) == "table" then + for k,v in pairs(options.args) do + if type(v) == "table" then + local newposition + if position then + newposition = position .. ".args." .. k + else + newposition = "args." .. k + end + local err, pos = validateOptionsMethods(self, v, newposition) + if err then + return err, pos + end + end + end + end +end + +local function validateOptions(options, position, baseOptions, fromPass) + if not baseOptions then + baseOptions = options + end + if type(options) ~= "table" then + return "Options must be a table.", position + end + local kind = options.type + if type(kind) ~= "string" then + return '"type" must be a string.', position + elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "header" then + return '"type" must either be "range", "text", "group", "toggle", "execute", "color", or "header".', position + end + if options.aliases then + if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then + return '"alias" must be a table or string', position + end + end + if not fromPass then + if kind == "execute" then + if type(options.func) ~= "string" and type(options.func) ~= "function" then + return '"func" must be a string or function', position + end + elseif kind == "range" or kind == "text" or kind == "toggle" then + if type(options.set) ~= "string" and type(options.set) ~= "function" then + return '"set" must be a string or function', position + end + if kind == "text" and options.get == false then + elseif type(options.get) ~= "string" and type(options.get) ~= "function" then + return '"get" must be a string or function', position + end + elseif kind == "group" and options.pass then + if options.pass ~= true then + return '"pass" must be either nil, true, or false', position + end + if not options.func then + if type(options.set) ~= "string" and type(options.set) ~= "function" then + return '"set" must be a string or function', position + end + if type(options.get) ~= "string" and type(options.get) ~= "function" then + return '"get" must be a string or function', position + end + elseif type(options.func) ~= "string" and type(options.func) ~= "function" then + return '"func" must be a string or function', position + end + end + else + if kind == "group" then + return 'cannot have "type" = "group" as a subgroup of a passing group', position + end + end + if options ~= baseOptions then + if kind == "header" then + elseif type(options.desc) ~= "string" then + return '"desc" must be a string', position + elseif string.len(options.desc) == 0 then + return '"desc" cannot be a 0-length string', position + end + end + + if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then + if options.type == "header" and not options.cmdName and not options.name then + elseif options.cmdName then + if type(options.cmdName) ~= "string" then + return '"cmdName" must be a string or nil', position + elseif string.len(options.cmdName) == 0 then + return '"cmdName" cannot be a 0-length string', position + end + if type(options.guiName) ~= "string" then + if not options.guiNameIsMap then + return '"guiName" must be a string or nil', position + end + elseif string.len(options.guiName) == 0 then + return '"guiName" cannot be a 0-length string', position + end + else + if type(options.name) ~= "string" then + return '"name" must be a string', position + elseif string.len(options.name) == 0 then + return '"name" cannot be a 0-length string', position + end + end + end + if options.guiNameIsMap then + if type(options.guiNameIsMap) ~= "boolean" then + return '"guiNameIsMap" must be a boolean or nil', position + elseif options.type ~= "toggle" then + return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position + elseif type(options.map) ~= "table" then + return '"map" must be a table', position + end + end + if options.message and type(options.message) ~= "string" then + return '"message" must be a string or nil', position + end + if options.error and type(options.error) ~= "string" then + return '"error" must be a string or nil', position + end + if options.current and type(options.current) ~= "string" then + return '"current" must be a string or nil', position + end + if options.order then + if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then + return '"order" must be a non-zero number or nil', position + end + end + if options.disabled then + if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then + return '"disabled" must be a function, string, or boolean', position + end + end + if options.cmdHidden then + if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then + return '"cmdHidden" must be a function, string, or boolean', position + end + end + if options.guiHidden then + if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then + return '"guiHidden" must be a function, string, or boolean', position + end + end + if options.hidden then + if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then + return '"hidden" must be a function, string, or boolean', position + end + end + if kind == "text" then + if type(options.validate) == "table" then + local t = options.validate + local iTable = nil + for k,v in pairs(t) do + if type(k) == "number" then + if iTable == nil then + iTable = true + elseif not iTable then + return '"validate" must either have all keys be indexed numbers or strings', position + elseif k < 1 or k > table.getn(t) then + return '"validate" numeric keys must be indexed properly. >= 1 and <= table.getn', position + end + else + if iTable == nil then + iTable = false + elseif iTable then + return '"validate" must either have all keys be indexed numbers or strings', position + end + end + if type(v) ~= "string" then + return '"validate" values must all be strings', position + end + end + else + if type(options.usage) ~= "string" then + return '"usage" must be a string', position + elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then + return '"validate" must be a string, function, or table', position + end + end + elseif kind == "range" then + if options.min or options.max then + if type(options.min) ~= "number" then + return '"min" must be a number', position + elseif type(options.max) ~= "number" then + return '"max" must be a number', position + elseif options.min >= options.max then + return '"min" must be less than "max"', position + end + end + if options.step then + if type(options.step) ~= "number" then + return '"step" must be a number', position + elseif options.step < 0 then + return '"step" must be nonnegative', position + end + end + if options.isPercent and options.isPercent ~= true then + return '"isPercent" must either be nil, true, or false', position + end + elseif kind == "toggle" then + if options.map then + if type(options.map) ~= "table" then + return '"map" must be a table', position + elseif type(options.map[true]) ~= "string" then + return '"map[true]" must be a string', position + elseif type(options.map[false]) ~= "string" then + return '"map[false]" must be a string', position + end + end + elseif kind == "color" then + if options.hasAlpha and options.hasAlpha ~= true then + return '"hasAlpha" must be nil, true, or false', position + end + elseif kind == "group" then + if options.pass and options.pass ~= true then + return '"pass" must be nil, true, or false', position + end + if type(options.args) ~= "table" then + return '"args" must be a table', position + end + for k,v in pairs(options.args) do + if type(k) ~= "string" then + return '"args" keys must be strings', position + elseif string.find(k, "%s") then + return string.format('"args" keys must not include spaces. %q is not appropriate.', k), position + elseif string.len(k) == 0 then + return '"args" keys must not be 0-length strings.', position + end + if type(v) ~= "table" then + return '"args" values must be tables', position and position .. "." .. k or k + end + local newposition + if position then + newposition = position .. ".args." .. k + else + newposition = "args." .. k + end + local err, pos = validateOptions(v, newposition, baseOptions, options.pass) + if err then + return err, pos + end + end + end +end + +local colorTable +local colorFunc +local colorCancelFunc + +local order + +local mysort_args +local mysort + +local function printUsage(self, handler, realOptions, options, path, args, quiet, filter) + if filter then + filter = "^" .. string.gsub(filter, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + end + local hidden, disabled = options.cmdHidden or options.hidden, options.disabled + if hidden then + if type(hidden) == "function" then + hidden = hidden() + elseif type(hidden) == "string" then + if type(handler[hidden]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, hidden)) + end + hidden = handler[hidden](handler) + end + end + if hidden then + disabled = true + elseif disabled then + if type(disabled) == "function" then + disabled = disabled() + elseif type(disabled) == "string" then + if type(handler[disabled]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, disabled)) + end + disabled = handler[disabled](handler) + end + end + local kind = string.lower(options.type or "group") + if disabled then + print(string.format(OPTION_IS_DISABLED, path), realOptions.cmdName or realOptions.name or self) + elseif kind == "text" then + local var + if passTable then + if not passTable.get then + elseif type(passTable.get) == "function" then + var = passTable.get(passValue) + else + local handler = passTable.handler or handler + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if not options.get then + elseif type(options.get) == "function" then + var = options.get() + else + local handler = options.handler or handler + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + + local usage + if type(options.validate) == "table" then + if filter then + if not order then + order = {} + end + for k,v in pairs(options.validate) do + if string.find(v, filter) then + table.insert(order, v) + end + end + usage = "{" .. table.concat(order, " || ") .. "}" + for k in pairs(order) do + order[k] = nil + end + table_setn(order, 0) + else + if not order then + order = {} + end + for k,v in pairs(options.validate) do + table.insert(order, v) + end + usage = "{" .. table.concat(order, " || ") .. "}" + for k in pairs(order) do + order[k] = nil + end + table_setn(order, 0) + end + var = options.validate[var] or var + else + usage = options.usage or "" + end + if not quiet then + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage), realOptions.cmdName or realOptions.name or self) + end + if (passTable and passTable.get) or options.get then + print(string.format(options.current or IS_CURRENTLY_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE))) + end + elseif kind == "range" then + local var + if passTable then + if type(passTable.get) == "function" then + var = passTable.get(passValue) + else + local handler = passTable.handler or handler + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if type(options.get) == "function" then + var = options.get() + else + local handler = options.handler or handler + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + + local usage + local min = options.min or 0 + local max = options.max or 1 + if options.isPercent then + min, max = min * 100, max * 100 + var = tostring(var * 100) .. "%" + end + local bit = "-" + if min < 0 or max < 0 then + bit = " - " + end + usage = string.format("(%s%s%s)", min, bit, max) + if not quiet then + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage), realOptions.cmdName or realOptions.name or self) + end + print(string.format(options.current or IS_CURRENTLY_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE))) + elseif kind == "group" then + local usage + if next(options.args) then + if not order then + order = {} + end + for k,v in pairs(options.args) do + if v.type ~= "header" then + local hidden = v.cmdHidden or v.hidden + if hidden then + if type(hidden) == "function" then + hidden = hidden() + elseif type(hidden) == "string" then + local handler = v.handler or handler + if type(handler[hidden]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, hidden)) + end + hidden = handler[hidden](handler) + end + end + if not hidden then + if filter then + if string.find(k, filter) then + table.insert(order, k) + elseif type(v.aliases) == "table" then + for _,bit in ipairs(v.aliases) do + if string.find(v.aliases, filter) then + table.insert(order, k) + break + end + end + elseif type(v.aliases) == "string" then + if string.find(v.aliases, filter) then + table.insert(order, k) + end + end + else + table.insert(order, k) + end + end + end + end + if not mysort then + mysort = function(a, b) + local alpha, bravo = mysort_args[a], mysort_args[b] + local alpha_order = alpha and alpha.order or 100 + local bravo_order = bravo and bravo.order or 100 + if alpha_order == bravo_order then + return tostring(a) < tostring(b) + else + if alpha_order < 0 then + if bravo_order > 0 then + return false + end + else + if bravo_order < 0 then + return true + end + end + if alpha_order > 0 and bravo_order > 0 then + return tostring(a) < tostring(b) + end + return alpha_order < bravo_order + end + end + end + mysort_args = options.args + table.sort(order, mysort) + mysort_args = nil + if not quiet then + if options == realOptions then + if options.desc then + print(tostring(options.desc), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}")) + elseif self.description or self.notes then + print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}")) + else + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) + end + else + if options.desc then + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) + print(tostring(options.desc)) + else + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self) + end + end + end + for _,k in ipairs(order) do + local v = options.args[k] + if v then + local disabled = v.disabled + if disabled then + if type(disabled) == "function" then + disabled = disabled() + elseif type(disabled) == "string" then + local handler = v.handler or handler + if type(handler[disabled]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, disabled)) + end + disabled = handler[disabled](handler) + end + end + if type(v.aliases) == "table" then + k = k .. " || " .. table.concat(v.aliases, " || ") + elseif type(v.aliases) == "string" then + k = k .. " || " .. v.aliases + end + if v.get then + local a1,a2,a3,a4 + if type(v.get) == "function" then + if options.pass then + a1,a2,a3,a4 = v.get(k) + else + a1,a2,a3,a4 = v.get() + end + else + local handler = v.handler or handler + if type(handler[v.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, v.get)) + end + if options.pass then + a1,a2,a3,a4 = handler[v.get](handler, k) + else + a1,a2,a3,a4 = handler[v.get](handler) + end + end + if v.type == "color" then + if v.hasAlpha then + if not a1 or not a2 or not a3 or not a4 then + s = NONE + else + s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a4*255, a1*255, a2*255, a3*255, a4*255, a1*255, a2*255, a3*255) + end + else + if not a1 or not a2 or not a3 then + s = NONE + else + s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", a1*255, a2*255, a3*255, a1*255, a2*255, a3*255) + end + end + elseif v.type == "toggle" then + if v.map then + s = tostring(v.map[a1 and true or false] or NONE) + else + s = tostring(MAP_ONOFF[a1 and true or false] or NONE) + end + elseif v.type == "range" then + if v.isPercent then + s = tostring(a1 * 100) .. "%" + else + s = tostring(a1) + end + elseif v.type == "text" and type(v.validate) == "table" then + s = tostring(v.validate[a1] or a1) + else + s = tostring(a1 or NONE) + end + if disabled then + local s = string.gsub(s, "|cff%x%x%x%x%x%x(.-)|r", "%1") + local desc = string.gsub(v.desc or NONE, "|cff%x%x%x%x%x%x(.-)|r", "%1") + print(string.format("|cffcfcfcf - %s: [%s] %s|r", k, s, desc)) + else + print(string.format(" - |cffffff7f%s: [|r%s|cffffff7f]|r %s", k, s, v.desc or NONE)) + end + else + if disabled then + local desc = string.gsub(v.desc or NONE, "|cff%x%x%x%x%x%x(.-)|r", "%1") + print(string.format("|cffcfcfcf - %s: %s", k, desc)) + else + print(string.format(" - |cffffff7f%s:|r %s", k, v.desc or NONE)) + end + end + end + end + for k in pairs(order) do + order[k] = nil + end + table_setn(order, 0) + else + if options.desc then + desc = options.desc + print(string.format("|cffffff7f%s:|r %s", USAGE, path), realOptions.cmdName or realOptions.name or self) + print(tostring(options.desc)) + elseif options == realOptions and (self.description or self.notes) then + print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s", USAGE, path)) + else + print(string.format("|cffffff7f%s:|r %s", USAGE, path), realOptions.cmdName or realOptions.name or self) + end + print(NO_OPTIONS_AVAILABLE) + end + end +end + +local function handlerFunc(self, chat, msg, options) + if not msg then + msg = "" + else + msg = string.gsub(msg, "^%s*(.-)%s*$", "%1") + msg = string.gsub(msg, "%s+", " ") + end + + local realOptions = options + local options, path, args, handler, passTable, passValue = findTableLevel(self, options, chat, msg) + + local hidden, disabled = options.cmdHidden or options.hidden, options.disabled + if hidden then + if type(hidden) == "function" then + hidden = hidden() + elseif type(hidden) == "string" then + if type(handler[hidden]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, hidden)) + end + hidden = handler[hidden](handler) + end + end + if hidden then + disabled = true + elseif disabled then + if type(disabled) == "function" then + disabled = disabled() + elseif type(disabled) == "string" then + if type(handler[disabled]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, disabled)) + end + disabled = handler[disabled](handler) + end + end + local _G_this = this + local kind = string.lower(options.type or "group") + if disabled then + print(string.format(OPTION_IS_DISABLED, path), realOptions.cmdName or realOptions.name or self) + elseif kind == "text" then + if table.getn(args) > 0 then + if (type(options.validate) == "table" and table.getn(args) > 1) or (type(options.validate) ~= "table" and not options.input) then + local arg = table.concat(args, " ") + for k,v in pairs(args) do + args[k] = nil + end + table_setn(args, 0) + table.insert(args, arg) + end + if options.validate then + local good + if type(options.validate) == "function" then + good = options.validate(unpack(args)) + elseif type(options.validate) == "table" then + local arg = args[1] + arg = string.lower(tostring(arg)) + for k,v in pairs(options.validate) do + if string.lower(v) == arg then + args[1] = type(k) == "string" and k or v + good = true + break + end + end + if not good and type((next(options.validate))) == "string" then + for k,v in pairs(options.validate) do + if type(k) == "string" and string.lower(k) == arg then + args[1] = k + good = true + break + end + end + end + else + if type(handler[options.validate]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.validate)) + end + good = handler[options.validate](handler, unpack(args)) + end + if not good then + local usage + if type(options.validate) == "table" then + if not order then + order = {} + end + for k,v in pairs(options.validate) do + table.insert(order, v) + end + usage = "{" .. table.concat(order, " || ") .. "}" + for k in pairs(order) do + order[k] = nil + end + table_setn(order, 0) + else + usage = options.usage or "" + end + print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, tostring(table.concat(args, " ")), path), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage)) + return + end + end + + local var + if passTable then + if not passTable.get then + elseif type(passTable.get) == "function" then + var = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if not options.get then + elseif type(options.get) == "function" then + var = options.get() + else + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + + if var ~= args[1] then + if passTable then + if type(passTable.set) == "function" then + passTable.set(passValue, unpack(args)) + else + if type(handler[passTable.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.set)) + end + handler[passTable.set](handler, passTable.set, unpack(args)) + end + else + if type(options.set) == "function" then + options.set(unpack(args)) + else + if type(handler[options.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.set)) + end + handler[options.set](handler, unpack(args)) + end + end + end + end + + if table.getn(args) > 0 then + local var + if passTable then + if not passTable.get then + elseif type(passTable.get) == "function" then + var = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if not options.get then + elseif type(options.get) == "function" then + var = options.get() + else + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + if type(options.validate) == "table" then + var = options.validate[var] or var + end + if (passTable and passTable.get) or options.get then + print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self) + end + if var == args[1] then + return + end + else + printUsage(self, handler, realOptions, options, path, args) + return + end + elseif kind == "execute" then + if passTable then + if type(passFunc) == "function" then + set(passValue) + else + if type(handler[passFunc]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passFunc)) + end + handler[passFunc](handler, passValue) + end + else + local ret, msg + if type(options.func) == "function" then + options.func() + else + local handler = options.handler or self + if type(handler[options.func]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.func)) + end + handler[options.func](handler) + end + end + elseif kind == "toggle" then + local var + if passTable then + if type(passTable.get) == "function" then + var = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + if type(passTable.set) == "function" then + passTable.set(passValue, not var) + else + if type(handler[passTable.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.set)) + end + handler[passTable.set](handler, passValue, not var) + end + if type(passTable.get) == "function" then + var = passTable.get(passValue) + else + var = handler[passTable.get](handler, passValue) + end + else + local handler = options.handler or self + if type(options.get) == "function" then + var = options.get() + else + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + if type(options.set) == "function" then + options.set(not var) + else + if type(handler[options.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.set)) + end + handler[options.set](handler, not var) + end + if type(options.get) == "function" then + var = options.get() + else + var = handler[options.get](handler) + end + end + + print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), (options.map or MAP_ONOFF)[var and true or false] or NONE), realOptions.cmdName or realOptions.name or self) + elseif kind == "range" then + local arg + if table.getn(args) <= 1 then + arg = args[1] + else + arg = table.concat(args, " ") + end + + if arg then + local min = options.min or 0 + local max = options.max or 1 + local good = false + if type(arg) == "number" then + if options.isPercent then + arg = arg / 100 + end + + if arg >= min and arg <= max then + good = true + end + + if good and type(options.step) == "number" and options.step > 0 then + local step = options.step + arg = math.floor((arg - min) / step + 0.5) * step + min + if arg > max then + arg = max + elseif arg < min then + arg = min + end + end + end + if not good then + local usage + local min = options.min or 0 + local max = options.max or 1 + if options.isPercent then + min, max = min * 100, max * 100 + end + local bit = "-" + if min < 0 or max < 0 then + bit = " - " + end + usage = string.format("(%s%s%s)", min, bit, max) + print(string.format(options.error or IS_NOT_A_VALID_VALUE_FOR, tostring(arg), path), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage)) + return + end + + local var + if passTable then + if type(passTable.get) == "function" then + var = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if type(options.get) == "function" then + var = options.get() + else + local handler = options.handler or self + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + + if var ~= arg then + if passTable then + if type(passTable.set) == "function" then + passTable.set(passValue, arg) + else + if type(handler[passTable.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.set)) + end + handler[passTable.set](handler, passValue, arg) + end + else + if type(options.set) == "function" then + options.set(arg) + else + local handler = options.handler or self + if type(handler[options.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.set)) + end + handler[options.set](handler, arg) + end + end + end + end + + if arg then + local var + if passTable then + if type(passTable.get) == "function" then + var = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + var = handler[passTable.get](handler, passValue) + end + else + if type(options.get) == "function" then + var = options.get() + else + local handler = options.handler or self + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + var = handler[options.get](handler) + end + end + + if var and options.isPercent then + var = tostring(var * 100) .. "%" + end + print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self) + if var == arg then + return + end + else + printUsage(self, handler, realOptions, options, path, args) + return + end + elseif kind == "color" then + if table.getn(args) > 0 then + local r,g,b,a + if table.getn(args) == 1 then + local arg = tostring(args[1]) + if options.hasAlpha then + if string.len(arg) == 8 and string.find(arg, "^%x*$") then + r,g,b,a = tonumber(string.sub(arg, 1, 2), 16) / 255, tonumber(string.sub(arg, 3, 4), 16) / 255, tonumber(string.sub(arg, 5, 6), 16) / 255, tonumber(string.sub(arg, 7, 8), 16) / 255 + end + else + if string.len(arg) == 6 and string.find(arg, "^%x*$") then + r,g,b = tonumber(string.sub(arg, 1, 2), 16) / 255, tonumber(string.sub(arg, 3, 4), 16) / 255, tonumber(string.sub(arg, 5, 6), 16) / 255 + end + end + elseif table.getn(args) == 4 and options.hasAlpha then + local a1,a2,a3,a4 = args[1], args[2], args[3], args[4] + if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and type(a4) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 and a4 <= 1 then + r,g,b,a = a1,a2,a3,a4 + elseif (type(a1) == "number" or string.len(a1) == 2) and string.find(a1, "^%x*$") and (type(a2) == "number" or string.len(a2) == 2) and string.find(a2, "^%x*$") and (type(a3) == "number" or string.len(a3) == 2) and string.find(a3, "^%x*$") and (type(a4) == "number" or string.len(a4) == 2) and string.find(a4, "^%x*$") then + r,g,b,a = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255, tonumber(a4, 16) / 255 + end + elseif table.getn(args) == 3 and not options.hasAlpha then + local a1,a2,a3 = args[1], args[2], args[3] + if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 then + r,g,b = a1,a2,a3 + elseif (type(a1) == "number" or string.len(a1) == 2) and string.find(a1, "^%x*$") and (type(a2) == "number" or string.len(a2) == 2) and string.find(a2, "^%x*$") and (type(a3) == "number" or string.len(a3) == 2) and string.find(a3, "^%x*$") then + r,g,b = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255 + end + end + if not r then + print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, table.concat(args, ' '), path), realOptions.cmdName or realOptions.name or self) + print(string.format("|cffffff7f%s:|r %s {0-1} {0-1} {0-1}%s", USAGE, path, options.hasAlpha and " {0-1}" or "")) + return + end + if passTable then + if type(passTable.set) == "function" then + passTable.set(passValue, r,g,b,a) + else + if type(handler[passTable.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.set)) + end + handler[passTable.set](handler, passValue, r,g,b,a) + end + else + if type(options.set) == "function" then + options.set(r,g,b,a) + else + if type(handler[options.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.set)) + end + handler[options.set](handler, r,g,b,a) + end + end + + local r,g,b,a + if passTable then + if type(passTable.get) == "function" then + r,g,b,a = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + r,g,b,a = handler[passTable.get](handler, passValue) + end + else + if type(options.get) == "function" then + r,g,b,a = options.get() + else + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + r,g,b,a = handler[options.get](handler) + end + end + + local s + if type(r) == "number" and type(g) == "number" and type(b) == "number" then + if options.hasAlpha and type(a) == "number" then + s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255) + else + s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", r*255, g*255, b*255, r*255, g*255, b*255) + end + else + s = NONE + end + print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), s), realOptions.cmdName or realOptions.name or self) + else + local r,g,b,a + if passTable then + if type(passTable.get) == "function" then + r,g,b,a = passTable.get(passValue) + else + if type(handler[passTable.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, passTable.get)) + end + r,g,b,a = handler[passTable.get](handler, passValue) + end + else + if type(options.get) == "function" then + r,g,b,a = options.get() + else + if type(handler[options.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, options.get)) + end + r,g,b,a = handler[options.get](handler) + end + end + + if not colorTable then + colorTable = {} + local t = colorTable + + if ColorPickerOkayButton then + local ColorPickerOkayButton_OnClick = ColorPickerOkayButton:GetScript("OnClick") + ColorPickerOkayButton:SetScript("OnClick", function() + if ColorPickerOkayButton_OnClick then + ColorPickerOkayButton_OnClick() + end + if t.active then + ColorPickerFrame.cancelFunc = nil + ColorPickerFrame.func = nil + ColorPickerFrame.opacityFunc = nil + local r,g,b,a + if t.passValue then + if type(t.get) == "function" then + r,g,b,a = t.get(t.passValue) + else + if type(t.handler[t.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.get)) + end + r,g,b,a = t.handler[t.get](t.handler, t.passValue) + end + else + if type(t.get) == "function" then + r,g,b,a = t.get() + else + if type(t.handler[t.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.get)) + end + r,g,b,a = t.handler[t.get](t.handler) + end + end + if r ~= t.r or g ~= t.g or b ~= t.b or (t.hasAlpha and a ~= t.a) then + local s + if type(r) == "number" and type(g) == "number" and type(b) == "number" then + if t.hasAlpha and type(a) == "number" then + s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255) + else + s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", r*255, g*255, b*255, r*255, g*255, b*255) + end + else + s = NONE + end + print(string.format(t.message, tostring(t.name), s), t.realOptions.cmdName or t.realOptions.name or self) + end + for k,v in pairs(t) do + t[k] = nil + end + end + end) + end + else + for k,v in pairs(colorTable) do + colorTable[k] = nil + end + end + + if type(r) ~= "number" or type(g) ~= "number" or type(b) ~= "number" then + r,g,b = 1, 1, 1 + end + if type(a) ~= "number" then + a = 1 + end + local t = colorTable + t.r = r + t.g = g + t.b = b + if hasAlpha then + t.a = a + end + t.realOptions = realOptions + t.hasAlpha = options.hasAlpha + t.handler = handler + t.set = passTable and passTable.set or options.set + t.get = passTable and passTable.get or options.get + t.name = options.cmdName or options.name + t.message = options.message or IS_NOW_SET_TO + t.passValue = passValue + t.active = true + + if not colorFunc then + colorFunc = function() + local r,g,b = ColorPickerFrame:GetColorRGB() + if t.hasAlpha then + local a = 1 - OpacitySliderFrame:GetValue() + if type(t.set) == "function" then + if t.passValue then + t.set(t.passValue, r,g,b,a) + else + t.set(r,g,b,a) + end + else + if type(t.handler[t.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.set)) + end + if t.passValue then + t.handler[t.set](t.handler, t.passValue, r,g,b,a) + else + t.handler[t.set](t.handler, r,g,b,a) + end + end + else + if type(t.set) == "function" then + if t.passValue then + t.set(t.passValue, r,g,b) + else + t.set(r,g,b) + end + else + if type(t.handler[t.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.set)) + end + if t.passValue then + t.handler[t.set](t.handler, t.passValue, r,g,b) + else + t.handler[t.set](t.handler, r,g,b) + end + end + end + end + end + + ColorPickerFrame.func = colorFunc + ColorPickerFrame.hasOpacity = options.hasAlpha + if options.hasAlpha then + ColorPickerFrame.opacityFunc = ColorPickerFrame.func + ColorPickerFrame.opacity = 1 - a + end + ColorPickerFrame:SetColorRGB(r,g,b) + + if not colorCancelFunc then + colorCancelFunc = function() + if t.hasAlpha then + if type(t.set) == "function" then + if t.passValue then + t.set(t.passValue, t.r,t.g,t.b,t.a) + else + t.set(t.r,t.g,t.b,t.a) + end + else + if type(t.handler[t.get]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.get)) + end + if t.passValue then + t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b,t.a) + else + t.handler[t.set](t.handler, t.r,t.g,t.b,t.a) + end + end + else + if type(t.set) == "function" then + if t.passValue then + t.set(t.passValue, t.r,t.g,t.b) + else + t.set(t.r,t.g,t.b) + end + else + if type(t.handler[t.set]) ~= "function" then + AceConsole:error("%s: %s", tostring(handler), string.format(OPTION_HANDLER_NOT_FOUND, t.set)) + end + if t.passValue then + t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b) + else + t.handler[t.set](t.handler, t.r,t.g,t.b) + end + end + end + for k,v in pairs(t) do + t[k] = nil + end + ColorPickerFrame.cancelFunc = nil + ColorPickerFrame.func = nil + ColorPickerFrame.opacityFunc = nil + end + end + + ColorPickerFrame.cancelFunc = colorCancelFunc + + ShowUIPanel(ColorPickerFrame) + end + return + elseif kind == "group" then + if table.getn(args) == 0 then + printUsage(self, handler, realOptions, options, path, args) + else + -- invalid argument + print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, args[1], path), realOptions.cmdName or realOptions.name or self) + end + return + end + this = _G_this + if Dewdrop then + Dewdrop:Refresh(1) + Dewdrop:Refresh(2) + Dewdrop:Refresh(3) + Dewdrop:Refresh(4) + Dewdrop:Refresh(5) + end +end + +local external +function AceConsole:RegisterChatCommand(slashCommands, options, name) + if type(slashCommands) ~= "table" and slashCommands ~= false then + AceConsole:error("Bad argument #2 to `RegisterChatCommand' (expected table, got %s)", type(slashCommands)) + end + if not slashCommands and type(name) ~= "string" then + AceConsole:error("Bad argument #4 to `RegisterChatCommand' (expected string, got %s)", type(name)) + end + if type(options) ~= "table" and type(options) ~= "function" and options ~= nil then + AceConsole:error("Bad argument #3 to `RegisterChatCommand' (expected table, function, or nil, got %s)", type(options)) + end + if name then + if type(name) ~= "string" then + AceConsole:error("Bad argument #4 to `RegisterChatCommand' (expected string or nil, got %s)", type(name)) + elseif not string.find(name, "^%w+$") or string.upper(name) ~= name or string.len(name) == 0 then + AceConsole:error("Argument #4 must be an uppercase, letters-only string with at least 1 character") + end + end + if slashCommands then + if table.getn(slashCommands) == 0 then + AceConsole:error("Argument #2 to `RegisterChatCommand' must include at least one string") + end + + for k,v in pairs(slashCommands) do + if type(k) ~= "number" then + AceConsole:error("All keys in argument #2 to `RegisterChatCommand' must be numbers") + end + if type(v) ~= "string" then + AceConsole:error("All values in argument #2 to `RegisterChatCommand' must be strings") + elseif not string.find(v, "^/[A-Za-z][A-Za-z0-9_]*$") then + AceConsole:error("All values in argument #2 to `RegisterChatCommand' must be in the form of \"/word\"") + end + end + end + + if not options then + options = { + type = 'group', + args = {}, + handler = self + } + end + + if type(options) == "table" then + local err, position = validateOptions(options) + if err then + if position then + AceConsole:error(position .. ": " .. err) + else + AceConsole:error(err) + end + end + + if not options.handler then + options.handler = self + end + + if options.handler == self and string.lower(options.type) == "group" and self.class then + AceConsole:InjectAceOptionsTable(self, options) + end + end + + local chat + if slashCommands then + chat = slashCommands[1] + else + chat = _G["SLASH_"..name..1] + end + + local handler + if type(options) == "function" then + handler = options + for k,v in pairs(_G) do + if handler == v then + local k = k + handler = function(msg) + return _G[k](msg) + end + end + end + else + function handler(msg) + handlerFunc(self, chat, msg, options) + end + end + + if not _G.SlashCmdList then + _G.SlashCmdList = {} + end + + if not name then + repeat + name = string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) + until not _G.SlashCmdList[name] + end + + if slashCommands then + if _G.SlashCmdList[name] then + local i = 0 + while true do + i = i + 1 + if _G["SLASH_"..name..i] then + _G["SLASH_"..name..i] = nil + else + break + end + end + end + + local i = 0 + for _,command in ipairs(slashCommands) do + i = i + 1 + _G["SLASH_"..name..i] = command + if string.lower(command) ~= command then + i = i + 1 + _G["SLASH_"..name..i] = string.lower(command) + end + end + end + _G.SlashCmdList[name] = handler + if self ~= AceConsole and self.slashCommand == nil then + self.slashCommand = chat + end + + if not AceEvent and AceLibrary:HasInstance("AceEvent-2.0") then + external(AceConsole, "AceEvent-2.0", AceLibrary("AceEvent-2.0")) + end + if AceEvent then + if not AceConsole.nextAddon then + AceConsole.nextAddon = {} + end + if type(options) == "table" then + AceConsole.nextAddon[self] = options + if not self.playerLogin then + AceConsole:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true) + end + end + end + + AceConsole.registry[name] = options +end + +function AceConsole:InjectAceOptionsTable(handler, options) + self:argCheck(handler, 2, "table") + self:argCheck(options, 3, "table") + if string.lower(options.type) ~= "group" then + self:error('Cannot inject into options table argument #3 if its type is not "group"') + end + if options.handler ~= nil and options.handler ~= handler then + self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") + end + options.handler = handler + local class = handler.class + if not class then + self:error("Cannot retrieve AceOptions tables from a non-object argument #2") + end + while class and class ~= AceOO.Class do + if type(class.GetAceOptionsDataTable) == "function" then + local t = class:GetAceOptionsDataTable(handler) + for k,v in pairs(t) do + if type(options.args) ~= "table" then + options.args = {} + end + if options.args[k] == nil then + options.args[k] = v + end + end + end + local mixins = class.mixins + if mixins then + for mixin in pairs(mixins) do + if type(mixin.GetAceOptionsDataTable) == "function" then + local t = mixin:GetAceOptionsDataTable(handler) + for k,v in pairs(t) do + if type(options.args) ~= "table" then + options.args = {} + end + if options.args[k] == nil then + options.args[k] = v + end + end + end + end + end + class = class.super + end + return options +end + +function AceConsole:PLAYER_LOGIN() + self.playerLogin = true + for addon, options in pairs(self.nextAddon) do + local err, position = validateOptionsMethods(addon, options) + if err then + if position then + error(tostring(addon) .. ": AceConsole: " .. position .. ": " .. err) + else + error(tostring(addon) .. ": AceConsole: " .. err) + end + end + self.nextAddon[addon] = nil + end + + self:RegisterChatCommand({ "/reload", "/rl", "/reloadui" }, ReloadUI, "RELOAD") + + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + self:RegisterChatCommand({ "/print" }, function(text) + RunScript("local function func(...) local arg = {...}; for k = 1,select('#', ...) do arg[k] = tostring(arg[k]) end DEFAULT_CHAT_FRAME:AddMessage(table.concat(arg, ' ')) end func(" .. text .. ")") + end, "PRINT") + else + self:RegisterChatCommand({ "/print" }, function(text) + RunScript("local function func(...) for k = 1,table.getn(arg) do arg[k] = tostring(arg[k]) end DEFAULT_CHAT_FRAME:AddMessage(table.concat(arg, ' ')) end func(" .. text .. ")") + end, "PRINT") + end +end + +function AceConsole:TabCompleteInfo(cmdpath) + local _, _, cmd = string.find(cmdpath, "(/%S+)") + if not cmd then + return + end + local path = string.sub(cmdpath, string.len(cmd) + 2) + for name in pairs(SlashCmdList) do --global + if AceConsole.registry[name] then + local i = 0 + while true do + i = i + 1 + local scmd = _G["SLASH_"..name..i] + if not scmd then break end + if cmd == scmd then + return name, cmd, path + end + end + end + end +end + +function external(self, major, instance) + if major == "AceEvent-2.0" then + if not AceEvent then + AceEvent = instance + + AceEvent:embed(self) + end + elseif major == "AceTab-2.0" then + instance:RegisterTabCompletion("AceConsole", "%/.*", function(t, cmdpath, pos) + local ac = AceLibrary("AceConsole-2.0") + local name, cmd, path = ac:TabCompleteInfo(string.sub(cmdpath, 1, pos)) + + if not ac.registry[name] then + return false + else + local validArgs = findTableLevel(ac, ac.registry[name], cmd, path or "") + if validArgs.args then + for arg in pairs(validArgs.args) do + table.insert(t, arg) + end + end + end + end, function(u, matches, gcs, cmdpath) + local ac = AceLibrary("AceConsole-2.0") + local name, cmd, path = ac:TabCompleteInfo(cmdpath) + if ac.registry[name] then + local validArgs, path2, argwork = findTableLevel(ac, ac.registry[name], cmd, path) + printUsage(ac, validArgs.handler, ac.registry[name], validArgs, path2, argwork, not gcs or gcs ~= "", gcs) + end + end) + elseif major == "Dewdrop-2.0" then + Dewdrop = instance + end +end + +local function activate(self, oldLib, oldDeactivate) + AceConsole = self + + self.super.activate(self, oldLib, oldDeactivate) + + if oldLib then + self.registry = oldLib.registry + self.nextAddon = oldLib.nextAddon + end + if not self.registry then + self.registry = {} + else + for name,options in pairs(self.registry) do + self:RegisterChatCommand(false, options, name) + end + end + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceConsole, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) +AceConsole = AceLibrary(MAJOR_VERSION) diff --git a/Libs/AceDB-2.0/AceDB-2.0.lua b/Libs/AceDB-2.0/AceDB-2.0.lua new file mode 100644 index 0000000..7d9a536 --- /dev/null +++ b/Libs/AceDB-2.0/AceDB-2.0.lua @@ -0,0 +1,1497 @@ +--[[ +Name: AceDB-2.0 +Revision: $Rev: 17797 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceDB-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceDB-2.0 +Description: Mixin to allow for fast, clean, and featureful saved variable + access. +Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0 +]] + +local MAJOR_VERSION = "AceDB-2.0" +local MINOR_VERSION = "$Revision: 17797 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end + +local ACTIVE, ENABLED, STATE, TOGGLE_ACTIVE, MAP_ACTIVESUSPENDED, SET_PROFILE, SET_PROFILE_USAGE, PROFILE, PLAYER_OF_REALM, CHOOSE_PROFILE_DESC, CHOOSE_PROFILE_GUI, COPY_PROFILE_DESC, COPY_PROFILE_GUI, OTHER_PROFILE_DESC, OTHER_PROFILE_GUI, OTHER_PROFILE_USAGE, CHARACTER, REALM, CLASS + +local function safecall(func,a,b,c,d,e,f,g,h,i) + local success, err = pcall(func,a,b,c,d,e,f,g,h,i) + if not success then geterrorhandler()(err) end +end + +if GetLocale() == "deDE" then + ACTIVE = "Aktiv" + ENABLED = "Aktiviert" + STATE = "Status" + TOGGLE_ACTIVE = "Stoppt/Aktiviert dieses Addon." + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Aktiv|r", [false] = "|cffff0000Gestoppt|r" } + SET_PROFILE = "Setzt das Profil f\195\188r dieses Addon." + SET_PROFILE_USAGE = "{Charakter || Klasse || Realm || }" + PROFILE = "Profil" + PLAYER_OF_REALM = "%s von %s" + CHOOSE_PROFILE_DESC = "W\195\164hle ein Profil." + CHOOSE_PROFILE_GUI = "W\195\164hle" + COPY_PROFILE_DESC = "Kopiert Einstellungen von einem anderem Profil." + COPY_PROFILE_GUI = "Kopiere von" + OTHER_PROFILE_DESC = "W\195\164hle ein anderes Profil." + OTHER_PROFILE_GUI = "Anderes" + OTHER_PROFILE_USAGE = "" + + CHARACTER = "Charakter: " + REALM = "Realm: " + CLASS = "Klasse: " +elseif GetLocale() == "frFR" then + ACTIVE = "Actif" + ENABLED = "Activ\195\169" + STATE = "Etat" + TOGGLE_ACTIVE = "Suspend/active cet addon." + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Actif|r", [false] = "|cffff0000Suspendu|r" } + SET_PROFILE = "S\195\169lectionne le profil pour cet addon." + SET_PROFILE_USAGE = "{perso || classe || royaume || }" + PROFILE = "Profil" + PLAYER_OF_REALM = "%s de %s" + CHOOSE_PROFILE_DESC = "Choisissez un profil." + CHOOSE_PROFILE_GUI = "Choix" + COPY_PROFILE_DESC = "Copier les param\195\168tres d'un autre profil." + COPY_PROFILE_GUI = "Copier \195\160 partir de" + OTHER_PROFILE_DESC = "Choisissez un autre profil." + OTHER_PROFILE_GUI = "Autre" + OTHER_PROFILE_USAGE = "" + + CHARACTER = "Personnage: " + REALM = "Royaume: " + CLASS = "Classe: " +elseif GetLocale() == "koKR" then + ACTIVE = "ํ™œ์„ฑํ™”" + ENABLED = "ํ™œ์„ฑํ™”" + STATE = "์ƒํƒœ" + TOGGLE_ACTIVE = "์ด ์• ๋“œ์˜จ ์ค‘์ง€/๊ณ„์† ์‹คํ–‰" + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00ํ™œ์„ฑํ™”|r", [false] = "|cffff0000์ค‘์ง€๋จ|r" } + SET_PROFILE = "์ด ์• ๋“œ์˜จ์— ํ”„๋กœํ•„ ์„ค์ •" + SET_PROFILE_USAGE = "{์บ๋ฆญํ„ฐ๋ช… || ์ง์—… || ์„œ๋ฒ„๋ช… || <ํ”„๋กœํ•„๋ช…>}" + PROFILE = "ํ”„๋กœํ•„" + PLAYER_OF_REALM = "%s (%s ์„œ๋ฒ„)" + CHOOSE_PROFILE_DESC = "ํ”„๋กœํŒŒ์ผ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค." + CHOOSE_PROFILE_GUI = "์„ ํƒ" + COPY_PROFILE_DESC = "๋‹ค๋ฅธ ํ”„๋กœํŒŒ์ผ์—์„œ ์„ค์ •์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค." + COPY_PROFILE_GUI = "๋ณต์‚ฌ" + OTHER_PROFILE_DESC = "๋‹ค๋ฅธ ํ”„๋กœํŒŒ์ผ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค." + OTHER_PROFILE_GUI = "๊ธฐํƒ€" + OTHER_PROFILE_USAGE = "<ํ”„๋กœํŒŒ์ผ๋ช…>" + + CHARACTER = "์บ๋ฆญํ„ฐ: " + REALM = "์„œ๋ฒ„: " + CLASS = "์ง์—…: " +elseif GetLocale() == "zhTW" then + ACTIVE = "ๅ•Ÿๅ‹•" + ENABLED = "ๅ•Ÿ็”จ" + STATE = "็‹€ๆ…‹" + TOGGLE_ACTIVE = "ๆšซๅœ/้‡ๅ•Ÿ้€™ๅ€‹ๆ’ไปถใ€‚" + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00ๅ•Ÿๅ‹•|r", [false] = "|cffff0000ๅทฒๆšซๅœ|r" } + SET_PROFILE = "่จญๅฎš้€™ๆ’ไปถ็š„่จ˜้Œ„ๆช”ใ€‚" + SET_PROFILE_USAGE = "{่ง’่‰ฒ || ่ฏๆฅญ || ไผบๆœๅ™จ || <่จ˜้Œ„ๆช”ๅ็จฑ>}" + PROFILE = "่จ˜้Œ„ๆช”" + PLAYER_OF_REALM = "%s ๆ–ผ %s" + CHOOSE_PROFILE_DESC = "้ธๆ“‡ไธ€ๅ€‹่จ˜้Œ„ๆช”" + CHOOSE_PROFILE_GUI = "้ธๆ“‡" + COPY_PROFILE_DESC = "็”ฑๅ…ถไป–่จ˜้Œ„ๆช”่ค‡่ฃฝ่จญๅฎšใ€‚" + COPY_PROFILE_GUI = "่ค‡่ฃฝ็”ฑ" + OTHER_PROFILE_DESC = "้ธๆ“‡ๅ…ถไป–่จ˜้Œ„ๆช”ใ€‚" + OTHER_PROFILE_GUI = "ๅ…ถไป–" + OTHER_PROFILE_USAGE = "<่จ˜้Œ„ๆช”ๅ็จฑ>" + + CHARACTER = "่ง’่‰ฒ๏ผš" + REALM = "ไผบๆœๅ™จ๏ผš" + CLASS = "่ฏๆฅญ๏ผš" +elseif GetLocale() == "zhCN" then + ACTIVE = "\230\156\137\230\149\136" + ENABLED = "\229\144\175\231\148\168" + STATE = "\231\138\182\230\128\129" + TOGGLE_ACTIVE = "\230\154\130\229\129\156/\230\129\162\229\164\141 \230\173\164\230\143\146\228\187\182." + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00\230\156\137\230\149\136|r", [false] = "|cffff0000\230\154\130\229\129\156|r" } + SET_PROFILE = "\232\174\190\231\189\174\233\133\141\231\189\174\230\150\135\228\187\182\228\184\186\232\191\153\230\143\146\228\187\182." + SET_PROFILE_USAGE = "{\229\173\151\231\172\166 || \233\128\137\228\187\182\231\177\187 || \229\159\159 || <\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>}" + PROFILE = "\233\133\141\231\189\174\230\150\135\228\187\182" + PLAYER_OF_REALM = "%s \231\154\132 %s" + CHOOSE_PROFILE_DESC = "\233\128\137\230\139\169\233\133\141\231\189\174\230\150\135\228\187\182." + CHOOSE_PROFILE_GUI = "\233\128\137\230\139\169" + COPY_PROFILE_DESC = "\229\164\141\229\136\182\232\174\190\231\189\174\228\187\142\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182." + COPY_PROFILE_GUI = "\229\164\141\229\136\182\228\187\142" + OTHER_PROFILE_DESC = "\233\128\137\230\139\169\229\143\166\228\184\128\228\184\170\233\133\141\231\189\174\230\150\135\228\187\182." + OTHER_PROFILE_GUI = "\229\133\182\228\187\150" + OTHER_PROFILE_USAGE = "<\233\133\141\231\189\174\230\150\135\228\187\182\229\144\141\229\173\151>" + + CHARACTER = "\229\173\151\231\172\166: " + REALM = "\229\159\159: " + CLASS = "\233\128\137\228\187\182\231\177\187: " +else -- enUS + ACTIVE = "Active" + ENABLED = "Enabled" + STATE = "State" + TOGGLE_ACTIVE = "Suspend/resume this addon." + MAP_ACTIVESUSPENDED = { [true] = "|cff00ff00Active|r", [false] = "|cffff0000Suspended|r" } + SET_PROFILE = "Set profile for this addon." + SET_PROFILE_USAGE = "{char || class || realm || }" + PROFILE = "Profile" + PLAYER_OF_REALM = "%s of %s" + CHOOSE_PROFILE_DESC = "Choose a profile." + CHOOSE_PROFILE_GUI = "Choose" + COPY_PROFILE_DESC = "Copy settings from another profile." + COPY_PROFILE_GUI = "Copy from" + OTHER_PROFILE_DESC = "Choose another profile." + OTHER_PROFILE_GUI = "Other" + OTHER_PROFILE_USAGE = "" + + CHARACTER = "Character: " + REALM = "Realm: " + CLASS = "Class: " +end + +local AceOO = AceLibrary("AceOO-2.0") +local AceEvent +local Mixin = AceOO.Mixin +local AceDB = Mixin { + "RegisterDB", + "RegisterDefaults", + "ResetDB", + "SetProfile", + "GetProfile", + "ToggleActive", + "IsActive", + "AcquireDBNamespace", + } +local Dewdrop = AceLibrary:HasInstance("Dewdrop-2.0") and AceLibrary("Dewdrop-2.0") + +local _G = getfenv(0) + +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local function inheritDefaults(t, defaults) + if not defaults then + return t + end + for k,v in pairs(defaults) do + if k == "*" then + local v = v + if type(v) == "table" then + setmetatable(t, { + __index = function(self, key) + if key == nil then + return nil + end + self[key] = {} + inheritDefaults(self[key], v) + return self[key] + end + } ) + else + setmetatable(t, { + __index = function(self, key) + if key == nil then + return nil + end + self[key] = v + return self[key] + end + } ) + end + for key in pairs(t) do + if (defaults[key] == nil or key == "*") and type(t[key]) == "table" then + inheritDefaults(t[key], v) + end + end + else + if type(v) == "table" then + if type(t[k]) ~= "table" then + t[k] = {} + end + inheritDefaults(t[k], v) + elseif t[k] == nil then + t[k] = v + end + end + end + return t +end + +local _,race = UnitRace("player") +local faction +if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" then + faction = FACTION_HORDE +else + faction = FACTION_ALLIANCE +end +local charID = string.format(PLAYER_OF_REALM, UnitName("player"), (string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1"))) +local realm = string.gsub(GetRealmName(), "^%s*(.-)%s*$", "%1") +local realmID = realm .. " - " .. faction +local classID = UnitClass("player") + +AceDB.CHAR_ID = charID +AceDB.REALM_ID = realmID +AceDB.CLASS_ID = classID + +AceDB.FACTION = faction +AceDB.REALM = realm +AceDB.NAME = UnitName("player") + +local new, del +do + local list = setmetatable({}, {__mode="k"}) + function new() + local t = next(list) + if t then + list[t] = nil + return t + else + return {} + end + end + + function del(t) + setmetatable(t, nil) + for k in pairs(t) do + t[k] = nil + end + table_setn(t, 0) + list[t] = true + end +end + +local caseInsensitive_mt = { + __index = function(self, key) + if type(key) ~= "string" then + return nil + end + local lowerKey = string.lower(key) + for k,v in pairs(self) do + if string.lower(k) == lowerKey then + return self[k] + end + end + end, + __newindex = function(self, key, value) + if type(key) ~= "string" then + return error("table index is nil", 2) + end + local lowerKey = string.lower(key) + for k in pairs(self) do + if string.lower(k) == lowerKey then + rawset(self, k, nil) + rawset(self, key, value) + return + end + end + rawset(self, key, value) + end +} + +local db_mt = { __index = function(db, key) + if key == "char" then + if db.charName then + if type(_G[db.charName]) ~= "table" then + _G[db.charName] = {} + end + if type(_G[db.charName].global) ~= "table" then + _G[db.charName].global = {} + end + rawset(db, 'char', _G[db.charName].global) + else + if type(db.raw.chars) ~= "table" then + db.raw.chars = {} + end + local id = charID + if type(db.raw.chars[id]) ~= "table" then + db.raw.chars[id] = {} + end + rawset(db, 'char', db.raw.chars[id]) + end + if db.defaults and db.defaults.char then + inheritDefaults(db.char, db.defaults.char) + end + return db.char + elseif key == "realm" then + if type(db.raw.realms) ~= "table" then + db.raw.realms = {} + end + local id = realmID + if type(db.raw.realms[id]) ~= "table" then + db.raw.realms[id] = {} + end + rawset(db, 'realm', db.raw.realms[id]) + if db.defaults and db.defaults.realm then + inheritDefaults(db.realm, db.defaults.realm) + end + return db.realm + elseif key == "account" then + if type(db.raw.account) ~= "table" then + db.raw.account = {} + end + rawset(db, 'account', db.raw.account) + if db.defaults and db.defaults.account then + inheritDefaults(db.account, db.defaults.account) + end + return db.account + elseif key == "class" then + if type(db.raw.classes) ~= "table" then + db.raw.classes = {} + end + local id = classID + if type(db.raw.classes[id]) ~= "table" then + db.raw.classes[id] = {} + end + rawset(db, 'class', db.raw.classes[id]) + if db.defaults and db.defaults.class then + inheritDefaults(db.class, db.defaults.class) + end + return db.class + elseif key == "profile" then + if type(db.raw.profiles) ~= "table" then + db.raw.profiles = setmetatable({}, caseInsensitive_mt) + else + setmetatable(db.raw.profiles, caseInsensitive_mt) + end + local id = db.raw.currentProfile[charID] + if id == "char" then + id = "char/" .. charID + elseif id == "class" then + id = "class/" .. classID + elseif id == "realm" then + id = "realm/" .. realmID + end + if type(db.raw.profiles[id]) ~= "table" then + db.raw.profiles[id] = {} + end + rawset(db, 'profile', db.raw.profiles[id]) + if db.defaults and db.defaults.profile then + inheritDefaults(db.profile, db.defaults.profile) + end + return db.profile + elseif key == "raw" or key == "defaults" or key == "name" or key == "charName" or key == "namespaces" then + return nil + end + error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) +end, __newindex = function(db, key, value) + error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) +end } + +local CrawlForSerialization +local CrawlForDeserialization + +local function SerializeObject(o) + local t = { o:Serialize() } + t[0] = o.class:GetLibraryVersion() + CrawlForSerialization(t) + return t +end + +local function DeserializeObject(t) + CrawlForDeserialization(t) + local className = t[0] + for i = 20, 1, -1 do + if t[i] then + table_setn(t, i) + break + end + end + local o = AceLibrary(className):Deserialize(unpack(t)) + table_setn(t, 0) + return o +end + +local function IsSerializable(t) + return AceOO.inherits(t, AceOO.Class) and t.class and type(t.class.Deserialize) == "function" and type(t.Serialize) == "function" and type(t.class.GetLibraryVersion) == "function" +end + +function CrawlForSerialization(t) + local tmp = new() + for k,v in pairs(t) do + tmp[k] = v + end + for k,v in pairs(tmp) do + if type(v) == "table" and type(v[0]) ~= "userdata" then + if IsSerializable(v) then + v = SerializeObject(v) + t[k] = v + else + CrawlForSerialization(v) + end + end + if type(k) == "table" and type(k[0]) ~= "userdata" then + if IsSerializable(k) then + t[k] = nil + t[SerializeObject(k)] = v + else + CrawlForSerialization(k) + end + end + tmp[k] = nil + k = nil + end + tmp = del(tmp) +end + +local function IsDeserializable(t) + return type(t[0]) == "string" and AceLibrary:HasInstance(t[0]) +end + +function CrawlForDeserialization(t) + local tmp = new() + for k,v in pairs(t) do + tmp[k] = v + end + for k,v in pairs(tmp) do + if type(v) == "table" then + if IsDeserializable(v) then + t[k] = DeserializeObject(v) + del(v) + v = t[k] + elseif type(v[0]) ~= "userdata" then + CrawlForDeserialization(v) + end + end + if type(k) == "table" then + if IsDeserializable(k) then + t[k] = nil + t[DeserializeObject(k)] = v + del(k) + elseif type(k[0]) ~= "userdata" then + CrawlForDeserialization(k) + end + end + tmp[k] = nil + k = nil + end + tmp = del(tmp) +end + +local namespace_mt = { __index = function(namespace, key) + local db = namespace.db + local name = namespace.name + if key == "char" then + if db.charName then + if type(_G[db.charName]) ~= "table" then + _G[db.charName] = {} + end + if type(_G[db.charName].namespaces) ~= "table" then + _G[db.charName].namespaces = {} + end + if type(_G[db.charName].namespaces[name]) ~= "table" then + _G[db.charName].namespaces[name] = {} + end + rawset(namespace, 'char', _G[db.charName].namespaces[name]) + else + if type(db.raw.namespaces) ~= "table" then + db.raw.namespaces = {} + end + if type(db.raw.namespaces[name]) ~= "table" then + db.raw.namespaces[name] = {} + end + if type(db.raw.namespaces[name].chars) ~= "table" then + db.raw.namespaces[name].chars = {} + end + local id = charID + if type(db.raw.namespaces[name].chars[id]) ~= "table" then + db.raw.namespaces[name].chars[id] = {} + end + rawset(namespace, 'char', db.raw.namespaces[name].chars[id]) + end + if namespace.defaults and namespace.defaults.char then + inheritDefaults(namespace.char, namespace.defaults.char) + end + return namespace.char + elseif key == "realm" then + if type(db.raw.namespaces) ~= "table" then + db.raw.namespaces = {} + end + if type(db.raw.namespaces[name]) ~= "table" then + db.raw.namespaces[name] = {} + end + if type(db.raw.namespaces[name].realms) ~= "table" then + db.raw.namespaces[name].realms = {} + end + local id = realmID + if type(db.raw.namespaces[name].realms[id]) ~= "table" then + db.raw.namespaces[name].realms[id] = {} + end + rawset(namespace, 'realm', db.raw.namespaces[name].realms[id]) + if namespace.defaults and namespace.defaults.realm then + inheritDefaults(namespace.realm, namespace.defaults.realm) + end + return namespace.realm + elseif key == "account" then + if type(db.raw.namespaces) ~= "table" then + db.raw.namespaces = {} + end + if type(db.raw.namespaces[name]) ~= "table" then + db.raw.namespaces[name] = {} + end + if type(db.raw.namespaces[name].account) ~= "table" then + db.raw.namespaces[name].account = {} + end + rawset(namespace, 'account', db.raw.namespaces[name].account) + if namespace.defaults and namespace.defaults.account then + inheritDefaults(namespace.account, namespace.defaults.account) + end + return namespace.account + elseif key == "class" then + if type(db.raw.namespaces) ~= "table" then + db.raw.namespaces = {} + end + if type(db.raw.namespaces[name]) ~= "table" then + db.raw.namespaces[name] = {} + end + if type(db.raw.namespaces[name].classes) ~= "table" then + db.raw.namespaces[name].classes = {} + end + local id = classID + if type(db.raw.namespaces[name].classes[id]) ~= "table" then + db.raw.namespaces[name].classes[id] = {} + end + rawset(namespace, 'class', db.raw.namespaces[name].classes[id]) + if namespace.defaults and namespace.defaults.class then + inheritDefaults(namespace.class, namespace.defaults.class) + end + return namespace.class + elseif key == "profile" then + if type(db.raw.namespaces) ~= "table" then + db.raw.namespaces = {} + end + if type(db.raw.namespaces[name]) ~= "table" then + db.raw.namespaces[name] = {} + end + if type(db.raw.namespaces[name].profiles) ~= "table" then + db.raw.namespaces[name].profiles = setmetatable({}, caseInsensitive_mt) + else + setmetatable(db.raw.namespaces[name].profiles, caseInsensitive_mt) + end + local id = db.raw.currentProfile[charID] + if id == "char" then + id = "char/" .. charID + elseif id == "class" then + id = "class/" .. classID + elseif id == "realm" then + id = "realm/" .. realmID + end + if type(db.raw.namespaces[name].profiles[id]) ~= "table" then + db.raw.namespaces[name].profiles[id] = {} + end + rawset(namespace, 'profile', db.raw.namespaces[name].profiles[id]) + if namespace.defaults and namespace.defaults.profile then + inheritDefaults(namespace.profile, namespace.defaults.profile) + end + return namespace.profile + elseif key == "defaults" or key == "name" or key == "db" then + return nil + end + error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) +end, __newindex = function(db, key, value) + error(string.format('Cannot access key %q in db table. You may want to use db.profile[%q]', tostring(key), tostring(key)), 2) +end } + +function AceDB:InitializeDB(addonName) + local db = self.db + + if not db then + if addonName then + AceDB.addonsLoaded[addonName] = true + end + return + end + + if db.raw then + -- someone manually initialized + return + end + + if type(_G[db.name]) ~= "table" then + _G[db.name] = {} + else + CrawlForDeserialization(_G[db.name]) + end + if type(_G[db.charName]) == "table" then + CrawlForDeserialization(_G[db.charName]) + end + rawset(db, 'raw', _G[db.name]) + if not db.raw.currentProfile then + db.raw.currentProfile = {} + end + if not db.raw.currentProfile[charID] then + db.raw.currentProfile[charID] = "Default" + end + if db.raw.disabled then + setmetatable(db.raw.disabled, caseInsensitive_mt) + end + if self['acedb-profile-copylist'] then + local t = self['acedb-profile-copylist'] + for k,v in pairs(t) do + t[k] = nil + end + if db.raw.profiles then + for k in pairs(db.raw.profiles) do + if string.find(k, '^char/') then + local name = string.sub(k, 6) + if name ~= charID then + t[k] = CHARACTER .. name + end + elseif string.find(k, '^realm/') then + local name = string.sub(k, 7) + if name ~= realmID then + t[k] = REALM .. name + end + elseif string.find(k, '^class/') then + local name = string.sub(k, 7) + if name ~= classID then + t[k] = CLASS .. name + end + end + end + end + end + if self['acedb-profile-list'] then + local t = self['acedb-profile-list'] + for k,v in pairs(t) do + t[k] = nil + end + t.char = CHARACTER .. charID + t.realm = REALM .. realmID + t.class = CLASS .. classID + t.Default = "Default" + if db.raw.profiles then + for k in pairs(db.raw.profiles) do + if not string.find(k, '^char/') and not string.find(k, '^realm/') and not string.find(k, '^class/') then + t[k] = k + end + end + end + end + setmetatable(db, db_mt) +end + +function AceDB:OnEmbedInitialize(target, name) + if name then + self:ADDON_LOADED(name) + end + self.InitializeDB(target, name) +end + +function AceDB:RegisterDB(name, charName) + AceDB:argCheck(name, 2, "string") + AceDB:argCheck(charName, 3, "string", "nil") + if self.db then + AceDB:error("Cannot call \"RegisterDB\" if self.db is set.") + end + local stack = debugstack() + local addonName = string.gsub(stack, ".-\n.-\\AddOns\\(.-)\\.*", "%1") + self.db = { + name = name, + charName = charName + } + if AceDB.addonsLoaded[addonName] then + AceDB.InitializeDB(self, addonName) + else + AceDB.addonsToBeInitialized[self] = addonName + end + AceDB.registry[self] = true +end + +function AceDB:RegisterDefaults(kind, defaults, a3) + local name + if a3 then + name, kind, defaults = kind, defaults, a3 + AceDB:argCheck(name, 2, "string") + AceDB:argCheck(kind, 3, "string") + AceDB:argCheck(defaults, 4, "table") + if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then + AceDB:error("Bad argument #3 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind) + end + else + AceDB:argCheck(kind, 2, "string") + AceDB:argCheck(defaults, 3, "table") + if kind ~= "char" and kind ~= "class" and kind ~= "profile" and kind ~= "account" and kind ~= "realm" then + AceDB:error("Bad argument #2 to `RegisterDefaults' (\"char\", \"class\", \"profile\", \"account\", or \"realm\" expected, got %q)", kind) + end + end + if type(self.db) ~= "table" or type(self.db.name) ~= "string" then + AceDB:error("Cannot call \"RegisterDefaults\" unless \"RegisterDB\" has been previously called.") + end + local db + if name then + local namespace = self:AcquireDBNamespace(name) + if namespace.defaults and namespace.defaults[kind] then + AceDB:error("\"RegisterDefaults\" has already been called for %q::%q.", name, kind) + end + db = namespace + else + if self.db.defaults and self.db.defaults[kind] then + AceDB:error("\"RegisterDefaults\" has already been called for %q.", kind) + end + db = self.db + end + if not db.defaults then + rawset(db, 'defaults', {}) + end + db.defaults[kind] = defaults + if rawget(db, kind) then + inheritDefaults(db[kind], defaults) + end +end + +function AceDB:ResetDB(kind) + AceDB:argCheck(kind, 2, "nil", "string") + if not self.db or not self.db.raw then + AceDB:error("Cannot call \"ResetDB\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") + end + local db = self.db + if kind == nil then + if db.charName then + _G[db.charName] = nil + end + _G[db.name] = nil + rawset(db, 'raw', nil) + AceDB.InitializeDB(self) + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'account', nil) + rawset(v, 'char', nil) + rawset(v, 'class', nil) + rawset(v, 'profile', nil) + rawset(v, 'realm', nil) + end + end + elseif kind == "account" then + db.raw.account = nil + rawset(db, 'account', nil) + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'account', nil) + end + end + elseif kind == "char" then + if db.charName then + _G[db.charName] = nil + else + if db.raw.chars then + db.raw.chars[charID] = nil + end + if db.raw.namespaces then + for name,v in pairs(db.raw.namespaces) do + if v.chars then + v.chars[charID] = nil + end + end + end + end + rawset(db, 'char', nil) + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'char', nil) + end + end + elseif kind == "realm" then + if db.raw.realms then + db.raw.realms[realmID] = nil + end + rawset(db, 'realm', nil) + if db.raw.namespaces then + for name,v in pairs(db.raw.namespaces) do + if v.realms then + v.realms[realmID] = nil + end + end + end + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'realm', nil) + end + end + elseif kind == "class" then + if db.raw.realms then + db.raw.realms[classID] = nil + end + rawset(db, 'class', nil) + if db.raw.namespaces then + for name,v in pairs(db.raw.namespaces) do + if v.classes then + v.classes[classID] = nil + end + end + end + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'class', nil) + end + end + elseif kind == "profile" then + local id = db.raw.currentProfile and db.raw.currentProfile[charID] or "Default" + if id == "char" then + id = "char/" .. charID + elseif id == "class" then + id = "class/" .. classID + elseif id == "realm" then + id = "realm/" .. realmID + end + if db.raw.profiles then + db.raw.profiles[id] = nil + end + rawset(db, 'profile', nil) + if db.raw.namespaces then + for name,v in pairs(db.raw.namespaces) do + if v.profiles then + v.profiles[id] = nil + end + end + end + if db.namespaces then + for name,v in pairs(db.namespaces) do + rawset(v, 'profile', nil) + end + end + end +end + +local function cleanDefaults(t, defaults) + if defaults then + for k,v in pairs(defaults) do + if k == "*" then + if type(v) == "table" then + for k in pairs(t) do + if (defaults[k] == nil or k == "*") and type(t[k]) == "table" then + if cleanDefaults(t[k], v) then + t[k] = nil + end + end + end + else + for k in pairs(t) do + if (defaults[k] == nil or k == "*") and t[k] == v then + t[k] = nil + end + end + end + else + if type(v) == "table" then + if type(t[k]) == "table" then + if cleanDefaults(t[k], v) then + t[k] = nil + end + end + elseif t[k] == v then + t[k] = nil + end + end + end + end + return t and not next(t) +end + +function AceDB:GetProfile() + if not self.db or not self.db.raw then + return nil + end + if not self.db.raw.currentProfile then + self.db.raw.currentProfile = {} + end + if not self.db.raw.currentProfile[charID] then + self.db.raw.currentProfile[charID] = "Default" + end + local profile = self.db.raw.currentProfile[charID] + if profile == "char" then + return "char", "char/" .. charID + elseif profile == "class" then + return "class", "class/" .. classID + elseif profile == "realm" then + return "realm", "realm/" .. realmID + end + return profile, profile +end + +local function copyTable(to, from) + setmetatable(to, nil) + for k,v in pairs(from) do + if type(k) == "table" then + k = copyTable({}, k) + end + if type(v) == "table" then + v = copyTable({}, v) + end + to[k] = v + end + table_setn(to, table.getn(from)) + setmetatable(to, from) + return to +end + +function AceDB:SetProfile(name, copyFrom) + AceDB:argCheck(name, 2, "string") + AceDB:argCheck(copyFrom, 3, "string", "nil") + if not self.db or not self.db.raw then + AceDB:error("Cannot call \"SetProfile\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") + end + local db = self.db + local copy = false + local lowerName = string.lower(name) + local lowerCopyFrom = copyFrom and string.lower(copyFrom) + if string.sub(lowerName, 1, 5) == "char/" or string.sub(lowerName, 1, 6) == "realm/" or string.sub(lowerName, 1, 6) == "class/" then + if string.sub(lowerName, 1, 5) == "char/" then + name, copyFrom = "char", name + else + name, copyFrom = string.sub(lowerName, 1, 5), name + end + lowerName = string.lower(name) + lowerCopyFrom = string.lower(copyFrom) + end + if copyFrom then + if string.sub(lowerCopyFrom, 1, 5) == "char/" then + AceDB:assert(lowerName == "char", "If argument #3 starts with `char/', argument #2 must be `char'") + elseif string.sub(lowerCopyFrom, 1, 6) == "realm/" then + AceDB:assert(lowerName == "realm", "If argument #3 starts with `realm/', argument #2 must be `realm'") + elseif string.sub(lowerCopyFrom, 1, 6) == "class/" then + AceDB:assert(lowerName == "class", "If argument #3 starts with `class/', argument #2 must be `class'") + else + AceDB:assert(lowerName ~= "char" and lowerName ~= "realm" and lowerName ~= "class", "If argument #3 does not start with a special prefix, that prefix cannot be copied to.") + end + if not db.raw.profiles or not db.raw.profiles[copyFrom] then + AceDB:error("Cannot copy profile %q, it does not exist.", copyFrom) + elseif (string.sub(lowerName, 1, 5) == "char/" and string.sub(lowerName, 6) == string.lower(charID)) or (string.sub(lowerName, 1, 6) == "realm/" and string.sub(lowerName, 7) == string.lower(realmID)) or (string.sub(lowerName, 1, 6) == "class/" and string.sub(lowerName, 7) == string.lower(classID)) then + AceDB:error("Cannot copy profile %q, it is currently in use.", name) + end + end + local oldName = db.raw.currentProfile[charID] + if string.lower(oldName) == string.lower(name) then + return + end + local oldProfileData = db.profile + local realName = name + if lowerName == "char" then + realName = name .. "/" .. charID + elseif lowerName == "realm" then + realName = name .. "/" .. realmID + elseif lowerName == "class" then + realName = name .. "/" .. classID + end + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedProfileDisable) == "function" then + safecall(mixin.OnEmbedProfileDisable, mixin, self, realName) + end + end + end + current = current.super + end + if type(self.OnProfileDisable) == "function" then + safecall(self.OnProfileDisable, self, realName) + end + local active = self:IsActive() + db.raw.currentProfile[charID] = name + rawset(db, 'profile', nil) + if db.namespaces then + for k,v in pairs(db.namespaces) do + rawset(v, 'profile', nil) + end + end + if copyFrom then + for k,v in pairs(db.profile) do + db.profile[k] = nil + end + copyTable(db.profile, db.raw.profiles[copyFrom]) + inheritDefaults(db.profile, db.defaults and db.defaults.profile) + if db.namespaces then + for l,u in pairs(db.namespaces) do + for k,v in pairs(u.profile) do + u.profile[k] = nil + end + copyTable(u.profile, db.raw.namespaces[l].profiles[copyFrom]) + inheritDefaults(u.profile, u.defaults and u.defaults.profile) + end + end + end + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedProfileEnable) == "function" then + safecall(mixin.OnEmbedProfileEnable, mixin, self, oldName, oldProfileData, copyFrom) + end + end + end + current = current.super + end + if type(self.OnProfileEnable) == "function" then + safecall(self.OnProfileEnable, self, oldName, oldProfileData, copyFrom) + end + if cleanDefaults(oldProfileData, db.defaults and db.defaults.profile) then + db.raw.profiles[oldName] = nil + if not next(db.raw.profiles) then + db.raw.profiles = nil + end + end + local newactive = self:IsActive() + if active ~= newactive then + if AceOO.inherits(self, "AceAddon-2.0") then + local AceAddon = AceLibrary("AceAddon-2.0") + if not AceAddon.addonsStarted[self] then + return + end + end + if newactive then + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedEnable) == "function" then + safecall(mixin.OnEmbedEnable, mixin, self) + end + end + end + current = current.super + end + if type(self.OnEnable) == "function" then + safecall(self.OnEnable, self) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonEnabled", self) + end + else + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedDisable) == "function" then + safecall(mixin.OnEmbedDisable, mixin, self) + end + end + end + current = current.super + end + if type(self.OnDisable) == "function" then + safecall(self.OnDisable, self) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonDisabled", self) + end + end + end + if self['acedb-profile-list'] then + if not self['acedb-profile-list'][name] then + self['acedb-profile-list'][name] = name + end + end + if Dewdrop then + Dewdrop:Refresh(1) + Dewdrop:Refresh(2) + Dewdrop:Refresh(3) + Dewdrop:Refresh(4) + Dewdrop:Refresh(5) + end +end + +function AceDB:IsActive() + return not self.db or not self.db.raw or not self.db.raw.disabled or not self.db.raw.disabled[self.db.raw.currentProfile[charID]] +end + +function AceDB:ToggleActive(state) + AceDB:argCheck(state, 2, "boolean", "nil") + if not self.db or not self.db.raw then + AceDB:error("Cannot call \"ToggleActive\" before \"RegisterDB\" has been called and before \"ADDON_LOADED\" has been fired.") + end + local db = self.db + if not db.raw.disabled then + db.raw.disabled = setmetatable({}, caseInsensitive_mt) + end + local profile = db.raw.currentProfile[charID] + local disable + if state == nil then + disable = not db.raw.disabled[profile] + else + disable = not state + if disable == db.raw.disabled[profile] then + return + end + end + db.raw.disabled[profile] = disable or nil + if AceOO.inherits(self, "AceAddon-2.0") then + local AceAddon = AceLibrary("AceAddon-2.0") + if not AceAddon.addonsStarted[self] then + return + end + end + if not disable then + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedEnable) == "function" then + safecall(mixin.OnEmbedEnable, mixin, self) + end + end + end + current = current.super + end + if type(self.OnEnable) == "function" then + safecall(self.OnEnable, self) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonEnabled", self) + end + else + local current = self.class + while current and current ~= AceOO.Class do + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnEmbedDisable) == "function" then + safecall(mixin.OnEmbedDisable, mixin, self) + end + end + end + current = current.super + end + if type(self.OnDisable) == "function" then + safecall(self.OnDisable, self) + end + if AceEvent then + AceEvent:TriggerEvent("Ace2_AddonDisabled", self) + end + end + return not disable +end + +function AceDB:embed(target) + self.super.embed(self, target) + if not AceEvent then + AceDB:error(MAJOR_VERSION .. " requires AceEvent-2.0") + end +end + +function AceDB:ADDON_LOADED(name) + AceDB.addonsLoaded[name] = true + for addon, addonName in pairs(AceDB.addonsToBeInitialized) do + if name == addonName then + AceDB.InitializeDB(addon, name) + AceDB.addonsToBeInitialized[addon] = nil + end + end +end + +function AceDB:PLAYER_LOGOUT() + for addon in pairs(AceDB.registry) do + local db = addon.db + if db then + setmetatable(db, nil) + CrawlForSerialization(db.raw) + if type(_G[db.charName]) == "table" then + CrawlForSerialization(_G[db.charName]) + end + if db.char and cleanDefaults(db.char, db.defaults and db.defaults.char) then + if db.charName and _G[db.charName] and _G[db.charName].global == db.char then + _G[db.charName].global = nil + if not next(_G[db.charName]) then + _G[db.charName] = nil + end + else + if db.raw.chars then + db.raw.chars[charID] = nil + if not next(db.raw.chars) then + db.raw.chars = nil + end + end + end + end + if db.realm and cleanDefaults(db.realm, db.defaults and db.defaults.realm) then + if db.raw.realms then + db.raw.realms[realmID] = nil + if not next(db.raw.realms) then + db.raw.realms = nil + end + end + end + if db.class and cleanDefaults(db.class, db.defaults and db.defaults.class) then + if db.raw.classes then + db.raw.classes[classID] = nil + if not next(db.raw.classes) then + db.raw.classes = nil + end + end + end + if db.account and cleanDefaults(db.account, db.defaults and db.defaults.account) then + db.raw.account = nil + end + if db.profile and cleanDefaults(db.profile, db.defaults and db.defaults.profile) then + if db.raw.profiles then + db.raw.profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or "Default"] = nil + if not next(db.raw.profiles) then + db.raw.profiles = nil + end + end + end + if db.namespaces and db.raw.namespaces then + for name,v in pairs(db.namespaces) do + if db.raw.namespaces[name] then + setmetatable(v, nil) + if v.char and cleanDefaults(v.char, v.defaults and v.defaults.char) then + if db.charName and _G[db.charName] and _G[db.charName].namespaces and _G[db.charName].namespaces[name] == v then + _G[db.charName].namespaces[name] = nil + if not next(_G[db.charName].namespaces) then + _G[db.charName].namespaces = nil + if not next(_G[db.charName]) then + _G[db.charName] = nil + end + end + else + if db.raw.namespaces[name].chars then + db.raw.namespaces[name].chars[charID] = nil + if not next(db.raw.namespaces[name].chars) then + db.raw.namespaces[name].chars = nil + end + end + end + end + if v.realm and cleanDefaults(v.realm, v.defaults and v.defaults.realm) then + if db.raw.namespaces[name].realms then + db.raw.namespaces[name].realms[realmID] = nil + if not next(db.raw.namespaces[name].realms) then + db.raw.namespaces[name].realms = nil + end + end + end + if v.class and cleanDefaults(v.class, v.defaults and v.defaults.class) then + if db.raw.namespaces[name].classes then + db.raw.namespaces[name].classes[classID] = nil + if not next(db.raw.namespaces[name].classes) then + db.raw.namespaces[name].classes = nil + end + end + end + if v.account and cleanDefaults(v.account, v.defaults and v.defaults.account) then + db.raw.namespaces[name].account = nil + end + if v.profile and cleanDefaults(v.profile, v.defaults and v.defaults.profile) then + if db.raw.namespaces[name].profiles then + db.raw.namespaces[name].profiles[db.raw.currentProfile and db.raw.currentProfile[charID] or "Default"] = nil + if not next(db.raw.namespaces[name].profiles) then + db.raw.namespaces[name].profiles = nil + end + end + end + if not next(db.raw.namespaces[name]) then + db.raw.namespaces[name] = nil + end + end + end + if not next(db.raw.namespaces) then + db.raw.namespaces = nil + end + end + if db.raw.disabled and not next(db.raw.disabled) then + db.raw.disabled = nil + end + if db.raw.currentProfile then + for k,v in pairs(db.raw.currentProfile) do + if string.lower(v) == "default" then + db.raw.currentProfile[k] = nil + end + end + if not next(db.raw.currentProfile) then + db.raw.currentProfile = nil + end + end + if _G[db.name] and not next(_G[db.name]) then + _G[db.name] = nil + end + end + end +end + +function AceDB:AcquireDBNamespace(name) + AceDB:argCheck(name, 2, "string") + local db = self.db + if not db then + AceDB:error("Cannot call `AcquireDBNamespace' before `RegisterDB' has been called.", 2) + end + if not db.namespaces then + rawset(db, 'namespaces', {}) + end + if not db.namespaces[name] then + local namespace = {} + db.namespaces[name] = namespace + namespace.db = db + namespace.name = name + setmetatable(namespace, namespace_mt) + end + return db.namespaces[name] +end + +function AceDB:GetAceOptionsDataTable(target) + if not target['acedb-profile-list'] then + target['acedb-profile-list'] = setmetatable({}, caseInsensitive_mt) + local t = target['acedb-profile-list'] + for k,v in pairs(t) do + t[k] = nil + end + t.char = CHARACTER .. charID + t.realm = REALM .. realmID + t.class = CLASS .. classID + t.Default = "Default" + if target.db and target.db.raw then + local db = target.db + if db.raw.profiles then + for k in pairs(db.raw.profiles) do + if not string.find(k, '^char/') and not string.find(k, '^realm/') and not string.find(k, '^class/') then + t[k] = k + end + end + end + end + end + if not target['acedb-profile-copylist'] then + target['acedb-profile-copylist'] = setmetatable({}, caseInsensitive_mt) + if target.db and target.db.raw then + local t = target['acedb-profile-copylist'] + local db = target.db + + if db.raw.profiles then + for k in pairs(db.raw.profiles) do + if string.find(k, '^char/') then + local name = string.sub(k, 6) + if name ~= charID then + t[k] = CHARACTER .. name + end + elseif string.find(k, '^realm/') then + local name = string.sub(k, 7) + if name ~= realmID then + t[k] = REALM .. name + end + elseif string.find(k, '^class/') then + local name = string.sub(k, 7) + if name ~= classID then + t[k] = CLASS .. name + end + end + end + end + end + end + return { + standby = { + cmdName = STATE, + guiName = ENABLED, + name = ACTIVE, + desc = TOGGLE_ACTIVE, + type = "toggle", + get = "IsActive", + set = "ToggleActive", + map = MAP_ACTIVESUSPENDED, + order = -3, + }, + profile = { + type = 'group', + name = PROFILE, + desc = SET_PROFILE, + order = -3.5, + get = "GetProfile", + args = { + choose = { + guiName = CHOOSE_PROFILE_GUI, + cmdName = PROFILE, + desc = CHOOSE_PROFILE_DESC, + type = 'text', + get = "GetProfile", + set = "SetProfile", + validate = target['acedb-profile-list'] + }, + copy = { + guiName = COPY_PROFILE_GUI, + cmdName = PROFILE, + desc = COPY_PROFILE_DESC, + type = 'text', + get = "GetProfile", + set = "SetProfile", + validate = target['acedb-profile-copylist'], + disabled = function() + return not next(target['acedb-profile-copylist']) + end, + }, + other = { + guiName = OTHER_PROFILE_GUI, + cmdName = PROFILE, + desc = OTHER_PROFILE_DESC, + usage = OTHER_PROFILE_USAGE, + type = 'text', + get = "GetProfile", + set = "SetProfile", + } + } + }, + } +end + +local function activate(self, oldLib, oldDeactivate) + AceDB = self + AceEvent = AceLibrary:HasInstance("AceEvent-2.0") and AceLibrary("AceEvent-2.0") + + self.super.activate(self, oldLib, oldDeactivate) + + for t in pairs(self.embedList) do + if t.db then + rawset(t.db, 'char', nil) + rawset(t.db, 'realm', nil) + rawset(t.db, 'class', nil) + rawset(t.db, 'account', nil) + rawset(t.db, 'profile', nil) + setmetatable(t.db, db_mt) + end + end + + if oldLib then + self.addonsToBeInitialized = oldLib.addonsToBeInitialized + self.addonsLoaded = oldLib.addonsLoaded + self.registry = oldLib.registry + end + if not self.addonsToBeInitialized then + self.addonsToBeInitialized = {} + end + if not self.addonsLoaded then + self.addonsLoaded = {} + end + if not self.registry then + self.registry = {} + end + + if oldLib then + oldDeactivate(oldLib) + end +end + +local function external(self, major, instance) + if major == "AceEvent-2.0" then + AceEvent = instance + + AceEvent:embed(self) + + self:RegisterEvent("ADDON_LOADED") + self:RegisterEvent("PLAYER_LOGOUT") + elseif major == "Dewdrop-2.0" then + Dewdrop = instance + end +end + +AceLibrary:Register(AceDB, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) +AceDB = AceLibrary(MAJOR_VERSION) diff --git a/Libs/AceDebug-2.0/AceDebug-2.0.lua b/Libs/AceDebug-2.0/AceDebug-2.0.lua new file mode 100644 index 0000000..bd0d806 --- /dev/null +++ b/Libs/AceDebug-2.0/AceDebug-2.0.lua @@ -0,0 +1,239 @@ +--[[ +Name: AceDebug-2.0 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceDebug-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceDebug-2.0 +Description: Mixin to allow for simple debugging capabilities. +Dependencies: AceLibrary, AceOO-2.0 +]] + +local MAJOR_VERSION = "AceDebug-2.0" +local MINOR_VERSION = "$Revision: 17638 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end + +local DEBUGGING, TOGGLE_DEBUGGING + +if GetLocale() == "frFR" then + DEBUGGING = "D\195\169boguage" + TOGGLE_DEBUGGING = "Activer/d\195\169sactiver le d\195\169boguage" +elseif GetLocale() == "deDE" then + DEBUGGING = "Debuggen" + TOGGLE_DEBUGGING = "Aktiviert/Deaktiviert Debugging" +elseif GetLocale() == "koKR" then + DEBUGGING = "๋””๋ฒ„๊น…" + TOGGLE_DEBUGGING = "๋””๋ฒ„๊น… ๊ธฐ๋Šฅ ์‚ฌ์šฉํ•จ/์‚ฌ์šฉ์•ˆํ•จ" +elseif GetLocale() == "zhTW" then + DEBUGGING = "้™ค้Œฏ" + TOGGLE_DEBUGGING = "ๅ•Ÿ็”จ/ๅœ็”จ้™ค้ŒฏๅŠŸ่ƒฝ" +elseif GetLocale() == "zhCN" then + DEBUGGING = "\232\176\131\232\175\149" + TOGGLE_DEBUGGING = "\229\144\175\231\148\168/\231\166\129\231\148\168 \232\176\131\232\175\149" +else -- enUS + DEBUGGING = "Debugging" + TOGGLE_DEBUGGING = "Enable/disable debugging" +end + +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local math_mod = math.mod or math.fmod + +local AceOO = AceLibrary:GetInstance("AceOO-2.0") +local AceDebug = AceOO.Mixin {"Debug", "CustomDebug", "IsDebugging", "SetDebugging", "SetDebugLevel", "LevelDebug", "CustomLevelDebug", "GetDebugLevel"} + +local function print(text, r, g, b, frame, delay) + (frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, 1, delay or 5) +end + +local tmp + +function AceDebug:CustomDebug(r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if not self.debugging then return end + + local output = string.format("|cff7fff7f(DEBUG) %s:[%s%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000) + + if string.find(tostring(a1), "%%") then + output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20)) + else + if not tmp then + tmp = {} + end + + -- This block dynamically rebuilds the tmp array stopping on the first nil. + table.insert(tmp, output) + + table.insert(tmp, tostring(a1)) + table.insert(tmp, a2) + table.insert(tmp, a3) + table.insert(tmp, a4) + table.insert(tmp, a5) + table.insert(tmp, a6) + table.insert(tmp, a7) + table.insert(tmp, a8) + table.insert(tmp, a9) + table.insert(tmp, a10) + table.insert(tmp, a11) + table.insert(tmp, a12) + table.insert(tmp, a13) + table.insert(tmp, a14) + table.insert(tmp, a15) + table.insert(tmp, a16) + table.insert(tmp, a17) + table.insert(tmp, a18) + table.insert(tmp, a19) + table.insert(tmp, a20) + while tmp[table.getn(tmp)] == nil do + table.remove(tmp) + end + for k = 1, table.getn(tmp) do + tmp[k] = tostring(tmp[k]) + end + + output = table.concat(tmp, " ") + + for k,v in pairs(tmp) do + tmp[k] = nil + end + table_setn(tmp, 0) + end + + print(output, r, g, b, frame or self.debugFrame, delay) +end + +function AceDebug:Debug(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + AceDebug.CustomDebug(self, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + +function AceDebug:IsDebugging() + return self.debugging +end + +function AceDebug:SetDebugging(debugging) + self.debugging = debugging +end + +-- Takes a number 1-3 +-- Level 1: Critical messages that every user should receive +-- Level 2: Should be used for local debugging (function calls, etc) +-- Level 3: Very verbose debugging, will dump everything and anything +-- If set to nil, you will receive no debug information +function AceDebug:SetDebugLevel(level) + AceDebug:argCheck(level, 1, "number", "nil") + if not level then + self.debuglevel = nil + return + end + if level < 1 or level > 3 then + AceDebug:error("Bad argument #1 to `SetDebugLevel`, must be a number 1-3") + end + self.debuglevel = level +end + +function AceDebug:GetDebugLevel() + return self.debuglevel +end + +function AceDebug:CustomLevelDebug(level, r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if not self.debugging or not self.debuglevel then return end + AceDebug:argCheck(level, 1, "number") + if level < 1 or level > 3 then + AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3") + end + if level > self.debuglevel then return end + + local output = string.format("|cff7fff7f(DEBUG) %s:[%s.%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000) + + if string.find(tostring(a1), "%%") then + output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20)) + else + if not tmp then + tmp = {} + end + + -- This block dynamically rebuilds the tmp array stopping on the first nil. + table.insert(tmp, output) + + table.insert(tmp, tostring(a1)) + table.insert(tmp, a2) + table.insert(tmp, a3) + table.insert(tmp, a4) + table.insert(tmp, a5) + table.insert(tmp, a6) + table.insert(tmp, a7) + table.insert(tmp, a8) + table.insert(tmp, a9) + table.insert(tmp, a10) + table.insert(tmp, a11) + table.insert(tmp, a12) + table.insert(tmp, a13) + table.insert(tmp, a14) + table.insert(tmp, a15) + table.insert(tmp, a16) + table.insert(tmp, a17) + table.insert(tmp, a18) + table.insert(tmp, a19) + table.insert(tmp, a20) + while tmp[table.getn(tmp)] == nil do + table.remove(tmp) + end + for k = 1, table.getn(tmp) do + tmp[k] = tostring(tmp[k]) + end + + output = table.concat(tmp, " ") + + for k,v in pairs(tmp) do + tmp[k] = nil + end + table_setn(tmp, 0) + end + + print(output, r, g, b, frame or self.debugFrame, delay) +end + +function AceDebug:LevelDebug(level, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if not self.debugging or not self.debuglevel then return end + AceDebug:argCheck(level, 1, "number") + if level < 1 or level > 3 then + AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3") + end + if level > self.debuglevel then return end + + AceDebug.CustomLevelDebug(self, level, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + + +local options +function AceDebug:GetAceOptionsDataTable(target) + if not options then + options = { + debug = { + name = DEBUGGING, + desc = TOGGLE_DEBUGGING, + type = "toggle", + get = "IsDebugging", + set = "SetDebugging", + order = -2, + } + } + end + return options +end +AceLibrary:Register(AceDebug, MAJOR_VERSION, MINOR_VERSION, AceDebug.activate) +AceDebug = AceLibrary(MAJOR_VERSION) diff --git a/Libs/AceEvent-2.0/AceEvent-2.0.lua b/Libs/AceEvent-2.0/AceEvent-2.0.lua new file mode 100644 index 0000000..c654568 --- /dev/null +++ b/Libs/AceEvent-2.0/AceEvent-2.0.lua @@ -0,0 +1,973 @@ +--[[ +Name: AceEvent-2.0 +Revision: $Rev: 17803 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceEvent-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0 +Description: Mixin to allow for event handling, scheduling, and inter-addon + communication. +Dependencies: AceLibrary, AceOO-2.0 +]] + +local MAJOR_VERSION = "AceEvent-2.0" +local MINOR_VERSION = "$Revision: 17803 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end + +local AceOO = AceLibrary:GetInstance("AceOO-2.0") +local Mixin = AceOO.Mixin +local AceEvent = Mixin { + "RegisterEvent", + "RegisterAllEvents", + "UnregisterEvent", + "UnregisterAllEvents", + "TriggerEvent", + "ScheduleEvent", + "ScheduleRepeatingEvent", + "CancelScheduledEvent", + "CancelAllScheduledEvents", + "IsEventRegistered", + "IsEventScheduled", + "RegisterBucketEvent", + "UnregisterBucketEvent", + "UnregisterAllBucketEvents", + "IsBucketEventRegistered", + } + +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local weakKey = {__mode="k"} +local new, del +do + local list = setmetatable({}, weakKey) + function new() + local t = next(list) + if t then + list[t] = nil + return t + else + return {} + end + end + + function del(t) + setmetatable(t, nil) + for k in pairs(t) do + t[k] = nil + end + list[t] = true + end +end + +local FAKE_NIL +local RATE + +local eventsWhichHappenOnce = { + PLAYER_LOGIN = true, + AceEvent_FullyInitialized = true, + VARIABLES_LOADED = true, + PLAYER_LOGOUT = true, +} + +local registeringFromAceEvent +function AceEvent:RegisterEvent(event, method, once) + AceEvent:argCheck(event, 2, "string") + if self == AceEvent and not registeringFromAceEvent then + AceEvent:argCheck(method, 3, "function") + self = method + else + AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number") + if type(method) == "boolean" or type(method) == "number" then + AceEvent:argCheck(once, 4, "nil") + once, method = method, event + end + end + AceEvent:argCheck(once, 4, "number", "boolean", "nil") + if eventsWhichHappenOnce[event] then + once = true + end + local throttleRate + if type(once) == "number" then + throttleRate, once = once + end + if not method then + method = event + end + if type(method) == "string" and type(self[method]) ~= "function" then + AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) + else + assert(type(method) == "function" or type(method) == "string") + end + + local AceEvent_registry = AceEvent.registry + if not AceEvent_registry[event] then + AceEvent_registry[event] = new() + AceEvent.frame:RegisterEvent(event) + end + + local remember = true + if AceEvent_registry[event][self] then + remember = false + end + AceEvent_registry[event][self] = method + + local AceEvent_onceRegistry = AceEvent.onceRegistry + if once then + if not AceEvent_onceRegistry then + AceEvent.onceRegistry = new() + AceEvent_onceRegistry = AceEvent.onceRegistry + end + if not AceEvent_onceRegistry[event] then + AceEvent_onceRegistry[event] = new() + end + AceEvent_onceRegistry[event][self] = true + else + if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then + AceEvent_onceRegistry[event][self] = nil + if not next(AceEvent_onceRegistry[event]) then + AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) + end + end + end + + local AceEvent_throttleRegistry = AceEvent.throttleRegistry + if throttleRate then + if not AceEvent_throttleRegistry then + AceEvent.throttleRegistry = new() + AceEvent_throttleRegistry = AceEvent.throttleRegistry + end + if not AceEvent_throttleRegistry[event] then + AceEvent_throttleRegistry[event] = new() + end + if AceEvent_throttleRegistry[event][self] then + AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self]) + end + AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey) + local t = AceEvent_throttleRegistry[event][self] + t[RATE] = throttleRate + else + if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then + if AceEvent_throttleRegistry[event][self] then + AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self]) + end + if not next(AceEvent_throttleRegistry[event]) then + AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) + end + end + end + + if remember then + AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event) + end +end + +local ALL_EVENTS + +function AceEvent:RegisterAllEvents(method) + if self == AceEvent then + AceEvent:argCheck(method, 1, "function") + self = method + else + AceEvent:argCheck(method, 1, "string", "function") + if type(method) == "string" and type(self[method]) ~= "function" then + AceEvent:error("Cannot register all events to method %q, it does not exist", method) + end + end + + local AceEvent_registry = AceEvent.registry + if not AceEvent_registry[ALL_EVENTS] then + AceEvent_registry[ALL_EVENTS] = new() + AceEvent.frame:RegisterAllEvents() + end + + AceEvent_registry[ALL_EVENTS][self] = method +end + +local _G = getfenv(0) +local memstack, timestack = {}, {} +local memdiff, timediff +function AceEvent:TriggerEvent(event, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + AceEvent:argCheck(event, 2, "string") + local AceEvent_registry = AceEvent.registry + if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then + return + end + local _G_event = _G.event + _G.event = event + local lastEvent = AceEvent.currentEvent + AceEvent.currentEvent = event + + local AceEvent_onceRegistry = AceEvent.onceRegistry + local AceEvent_debugTable = AceEvent.debugTable + if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then + local tmp = new() + for obj, method in pairs(AceEvent_onceRegistry[event]) do + tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil + end + local obj = next(tmp) + while obj do + local mem, time + if AceEvent_debugTable then + if not AceEvent_debugTable[event] then + AceEvent_debugTable[event] = new() + end + if not AceEvent_debugTable[event][obj] then + AceEvent_debugTable[event][obj] = new() + AceEvent_debugTable[event][obj].mem = 0 + AceEvent_debugTable[event][obj].time = 0 + AceEvent_debugTable[event][obj].count = 0 + end + if memdiff then + table.insert(memstack, memdiff) + table.insert(timestack, timediff) + end + memdiff, timediff = 0, 0 + mem, time = gcinfo(), GetTime() + end + local method = tmp[obj] + AceEvent.UnregisterEvent(obj, event) + if type(method) == "string" then + local obj_method = obj[method] + if obj_method then + obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + elseif method then -- function + method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + if AceEvent_debugTable then + local dmem, dtime = memdiff, timediff + mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff + AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem + AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time + AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 + + memdiff, timediff = table.remove(memstack), table.remove(timestack) + if memdiff then + memdiff = memdiff + mem + dmem + timediff = timediff + time + dtime + end + end + tmp[obj] = nil + obj = next(tmp) + end + del(tmp) + end + + local AceEvent_throttleRegistry = AceEvent.throttleRegistry + local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] + if AceEvent_registry[event] then + local tmp = new() + for obj, method in pairs(AceEvent_registry[event]) do + tmp[obj] = method + end + local obj = next(tmp) + while obj do + local method = tmp[obj] + local continue = false + if throttleTable and throttleTable[obj] then + local a1 = a1 + if a1 == nil then + a1 = FAKE_NIL + end + if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then + throttleTable[obj][a1] = GetTime() + else + continue = true + end + end + if not continue then + local mem, time + if AceEvent_debugTable then + if not AceEvent_debugTable[event] then + AceEvent_debugTable[event] = new() + end + if not AceEvent_debugTable[event][obj] then + AceEvent_debugTable[event][obj] = new() + AceEvent_debugTable[event][obj].mem = 0 + AceEvent_debugTable[event][obj].time = 0 + AceEvent_debugTable[event][obj].count = 0 + end + if memdiff then + table.insert(memstack, memdiff) + table.insert(timestack, timediff) + end + memdiff, timediff = 0, 0 + mem, time = gcinfo(), GetTime() + end + if type(method) == "string" then + local obj_method = obj[method] + if obj_method then + obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + elseif method then -- function + method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + if AceEvent_debugTable then + local dmem, dtime = memdiff, timediff + mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff + AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem + AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time + AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 + + memdiff, timediff = table.remove(memstack), table.remove(timestack) + if memdiff then + memdiff = memdiff + mem + dmem + timediff = timediff + time + dtime + end + end + end + tmp[obj] = nil + obj = next(tmp) + end + del(tmp) + end + if AceEvent_registry[ALL_EVENTS] then + local tmp = new() + for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do + tmp[obj] = method + end + local obj = next(tmp) + while obj do + local method = tmp[obj] + local mem, time + if AceEvent_debugTable then + if not AceEvent_debugTable[event] then + AceEvent_debugTable[event] = new() + end + if not AceEvent_debugTable[event][obj] then + AceEvent_debugTable[event][obj] = new() + AceEvent_debugTable[event][obj].mem = 0 + AceEvent_debugTable[event][obj].time = 0 + AceEvent_debugTable[event][obj].count = 0 + end + if memdiff then + table.insert(memstack, memdiff) + table.insert(timestack, timediff) + end + memdiff, timediff = 0, 0 + mem, time = gcinfo(), GetTime() + end + if type(method) == "string" then + local obj_method = obj[method] + if obj_method then + obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + elseif method then -- function + method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + end + if AceEvent_debugTable then + local dmem, dtime = memdiff, timediff + mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff + AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem + AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time + AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 + + memdiff, timediff = table.remove(memstack), table.remove(timestack) + if memdiff then + memdiff = memdiff + mem + dmem + timediff = timediff + time + dtime + end + end + tmp[obj] = nil + obj = next(tmp) + end + del(tmp) + end + _G.event = _G_event + AceEvent.currentEvent = lastEvent +end + +-- local accessors +local getn = table.getn +local tinsert = table.insert +local tremove = table.remove +local floor = math.floor +local GetTime = GetTime +local next = next +local pairs = pairs +local unpack = unpack + +local delayRegistry +local tmp = {} +local function OnUpdate() + local t = GetTime() + for k,v in pairs(delayRegistry) do + tmp[k] = true + end + for k in pairs(tmp) do + local v = delayRegistry[k] + if v then + local v_time = v.time + if not v_time then + delayRegistry[k] = del(v) + elseif v_time <= t then + local v_repeatDelay = v.repeatDelay + if v_repeatDelay then + -- use the event time, not the current time, else timing inaccuracies add up over time + v.time = v_time + v_repeatDelay + end + local event = v.event + local mem, time + if AceEvent_debugTable then + mem, time = gcinfo(), GetTime() + end + if type(event) == "function" then + event(unpack(v)) + else + AceEvent:TriggerEvent(event, unpack(v)) + end + if AceEvent_debugTable then + mem, time = gcinfo() - mem, GetTime() - time + v.mem = v.mem + mem + v.timeSpent = v.timeSpent + time + v.count = v.count + 1 + end + if not v_repeatDelay then + local x = delayRegistry[k] + if x and x.time == v_time then -- check if it was manually reset + delayRegistry[k] = del(v) + end + end + end + end + end + for k in pairs(tmp) do + tmp[k] = nil + end + if not next(delayRegistry) then + AceEvent.frame:Hide() + end +end + +local function ScheduleEvent(self, repeating, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + local id + if type(event) == "string" or type(event) == "table" then + if type(event) == "table" then + if not delayRegistry or not delayRegistry[event] then + AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") + end + end + if type(delay) ~= "number" then + id, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 + AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number") + AceEvent:argCheck(delay, 4, "number") + self:CancelScheduledEvent(id) + end + else + AceEvent:argCheck(event, 2, "string", "function") + AceEvent:argCheck(delay, 3, "number") + end + + if not delayRegistry then + AceEvent.delayRegistry = new() + delayRegistry = AceEvent.delayRegistry + AceEvent.frame:SetScript("OnUpdate", OnUpdate) + end + local t + if type(id) == "table" then + for k in pairs(id) do + id[k] = nil + end + t = id + else + t = new() + end + t[1] = a1 + t[2] = a2 + t[3] = a3 + t[4] = a4 + t[5] = a5 + t[6] = a6 + t[7] = a7 + t[8] = a8 + t[9] = a9 + t[10] = a10 + t[11] = a11 + t[12] = a12 + t[13] = a13 + t[14] = a14 + t[15] = a15 + t[16] = a16 + t[17] = a17 + t[18] = a18 + t[19] = a19 + t[20] = a20 + table_setn(t, 20) + t.event = event + t.time = GetTime() + delay + t.self = self + t.id = id or t + t.repeatDelay = repeating and delay + if AceEvent_debugTable then + t.mem = 0 + t.count = 0 + t.timeSpent = 0 + end + delayRegistry[t.id] = t + AceEvent.frame:Show() + return t.id +end + +function AceEvent:ScheduleEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if type(event) == "string" or type(event) == "table" then + if type(event) == "table" then + if not delayRegistry or not delayRegistry[event] then + AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") + end + end + if type(delay) ~= "number" then + AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") + AceEvent:argCheck(a1, 4, "number") + end + else + AceEvent:argCheck(event, 2, "string", "function") + AceEvent:argCheck(delay, 3, "number") + end + + return ScheduleEvent(self, false, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + +function AceEvent:ScheduleRepeatingEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if type(event) == "string" or type(event) == "table" then + if type(event) == "table" then + if not delayRegistry or not delayRegistry[event] then + AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") + end + end + if type(delay) ~= "number" then + AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") + AceEvent:argCheck(a1, 4, "number") + end + else + AceEvent:argCheck(event, 2, "string", "function") + AceEvent:argCheck(delay, 3, "number") + end + + return ScheduleEvent(self, true, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) +end + +function AceEvent:CancelScheduledEvent(t) + AceEvent:argCheck(t, 2, "string", "table") + if delayRegistry then + local v = delayRegistry[t] + if v then + delayRegistry[t] = del(v) + if not next(delayRegistry) then + AceEvent.frame:Hide() + end + return true + end + end + return false +end + +function AceEvent:IsEventScheduled(t) + AceEvent:argCheck(t, 2, "string", "table") + if delayRegistry then + local v = delayRegistry[t] + if v then + return true, v.time - GetTime() + end + end + return false, nil +end + +function AceEvent:UnregisterEvent(event) + AceEvent:argCheck(event, 2, "string") + local AceEvent_registry = AceEvent.registry + if AceEvent_registry[event] and AceEvent_registry[event][self] then + AceEvent_registry[event][self] = nil + local AceEvent_onceRegistry = AceEvent.onceRegistry + if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then + AceEvent_onceRegistry[event][self] = nil + if not next(AceEvent_onceRegistry[event]) then + AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) + end + end + local AceEvent_throttleRegistry = AceEvent.throttleRegistry + if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then + AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self]) + if not next(AceEvent_throttleRegistry[event]) then + AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) + end + end + if not next(AceEvent_registry[event]) then + AceEvent_registry[event] = del(AceEvent_registry[event]) + if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then + AceEvent.frame:UnregisterEvent(event) + end + end + else + if self == AceEvent then + error(string.format("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0.", event), 2) + else + AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self) + end + end + AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) +end + +function AceEvent:UnregisterAllEvents() + local AceEvent_registry = AceEvent.registry + if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then + AceEvent_registry[ALL_EVENTS][self] = nil + if not next(AceEvent_registry[ALL_EVENTS]) then + del(AceEvent_registry[ALL_EVENTS]) + AceEvent.frame:UnregisterAllEvents() + for k,v in pairs(AceEvent_registry) do + if k ~= ALL_EVENTS then + AceEvent.frame:RegisterEvent(k) + end + end + AceEvent_registry[event] = nil + end + end + local first = true + for event, data in pairs(AceEvent_registry) do + if first then + if AceEvent_registry.AceEvent_EventUnregistered then + event = "AceEvent_EventUnregistered" + else + first = false + end + end + local x = data[self] + data[self] = nil + if x and event ~= ALL_EVENTS then + if not next(data) then + del(data) + if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then + AceEvent.frame:UnregisterEvent(event) + end + AceEvent_registry[event] = nil + end + AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) + end + if first then + event = nil + end + end + if AceEvent.onceRegistry then + for event, data in pairs(AceEvent.onceRegistry) do + data[self] = nil + end + end +end + +function AceEvent:CancelAllScheduledEvents() + if delayRegistry then + for k,v in pairs(delayRegistry) do + if v.self == self then + delayRegistry[k] = del(v) + end + end + if not next(delayRegistry) then + AceEvent.frame:Hide() + end + end +end + +function AceEvent:IsEventRegistered(event) + AceEvent:argCheck(event, 2, "string") + local AceEvent_registry = AceEvent.registry + if self == AceEvent then + return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false + end + if AceEvent_registry[event] and AceEvent_registry[event][self] then + return true, AceEvent_registry[event][self] + end + return false, nil +end + +local bucketfunc +function AceEvent:RegisterBucketEvent(event, delay, method) + AceEvent:argCheck(event, 2, "string", "table") + if type(event) == "table" then + for k,v in pairs(event) do + if type(k) ~= "number" then + AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.") + elseif type(v) ~= "string" then + AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.") + end + end + end + AceEvent:argCheck(delay, 3, "number") + if AceEvent == self then + AceEvent:argCheck(method, 4, "function") + self = method + else + if type(event) == "string" then + AceEvent:argCheck(method, 4, "string", "function", "nil") + if not method then + method = event + end + else + AceEvent:argCheck(method, 4, "string", "function") + end + + if type(method) == "string" and type(self[method]) ~= "function" then + AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) + end + end + if not AceEvent.buckets then + AceEvent.buckets = new() + end + if not AceEvent.buckets[event] then + AceEvent.buckets[event] = new() + end + if not AceEvent.buckets[event][self] then + AceEvent.buckets[event][self] = new() + AceEvent.buckets[event][self].current = new() + AceEvent.buckets[event][self].self = self + else + AceEvent.CancelScheduledEvent(self, AceEvent.buckets[event][self].id) + end + local bucket = AceEvent.buckets[event][self] + bucket.method = method + + local func = function(arg1) + bucket.run = true + if arg1 then + bucket.current[arg1] = true + end + end + AceEvent.buckets[event][self].func = func + if type(event) == "string" then + AceEvent.RegisterEvent(self, event, func) + else + for _,v in ipairs(event) do + AceEvent.RegisterEvent(self, v, func) + end + end + if not bucketfunc then + bucketfunc = function(bucket) + local current = bucket.current + local method = bucket.method + local self = bucket.self + if bucket.run then + if type(method) == "string" then + self[method](self, current) + elseif method then -- function + method(current) + end + for k in pairs(current) do + current[k] = nil + k = nil + end + bucket.run = false + end + end + end + bucket.id = AceEvent.ScheduleRepeatingEvent(self, bucketfunc, delay, bucket) +end + +function AceEvent:IsBucketEventRegistered(event) + AceEvent:argCheck(event, 2, "string", "table") + return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self] +end + +function AceEvent:UnregisterBucketEvent(event) + AceEvent:argCheck(event, 2, "string", "table") + if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then + AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self) + end + + local bucket = AceEvent.buckets[event][self] + + if type(event) == "string" then + AceEvent.UnregisterEvent(self, event) + else + for _,v in ipairs(event) do + AceEvent.UnregisterEvent(self, v) + end + end + AceEvent:CancelScheduledEvent(bucket.id) + + del(bucket.current) + AceEvent.buckets[event][self] = del(AceEvent.buckets[event][self]) + if not next(AceEvent.buckets[event]) then + AceEvent.buckets[event] = del(AceEvent.buckets[event]) + end +end + +function AceEvent:UnregisterAllBucketEvents() + if not AceEvent.buckets or not next(AceEvent.buckets) then + return + end + for k,v in pairs(AceEvent.buckets) do + if v == self then + AceEvent.UnregisterBucketEvent(self, k) + k = nil + end + end +end + +function AceEvent:OnEmbedDisable(target) + self.UnregisterAllEvents(target) + + self.CancelAllScheduledEvents(target) + + self.UnregisterAllBucketEvents(target) +end + +function AceEvent:EnableDebugging() + if not self.debugTable then + self.debugTable = new() + + if delayRegistry then + for k,v in pairs(self.delayRegistry) do + if not v.mem then + v.mem = 0 + v.count = 0 + v.timeSpent = 0 + end + end + end + end +end + +function AceEvent:IsFullyInitialized() + return self.postInit or false +end + +function AceEvent:IsPostPlayerLogin() + return self.playerLogin or false +end + +function AceEvent:activate(oldLib, oldDeactivate) + AceEvent = self + + if oldLib then + self.onceRegistry = oldLib.onceRegistry + self.throttleRegistry = oldLib.throttleRegistry + self.delayRegistry = oldLib.delayRegistry + self.buckets = oldLib.buckets + self.registry = oldLib.registry + self.frame = oldLib.frame + self.debugTable = oldLib.debugTable + self.playerLogin = oldLib.pew or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage and true + self.postInit = oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true + self.ALL_EVENTS = oldLib.ALL_EVENTS + self.FAKE_NIL = oldLib.FAKE_NIL + self.RATE = oldLib.RATE + end + if not self.registry then + self.registry = {} + end + if not self.frame then + self.frame = CreateFrame("Frame", "AceEvent20Frame") + end + if not self.ALL_EVENTS then + self.ALL_EVENTS = {} + end + if not self.FAKE_NIL then + self.FAKE_NIL = {} + end + if not self.RATE then + self.RATE = {} + end + ALL_EVENTS = self.ALL_EVENTS + FAKE_NIL = self.FAKE_NIL + RATE = self.RATE + local inPlw = false + local blacklist = { + UNIT_INVENTORY_CHANGED = true, + BAG_UPDATE = true, + ITEM_LOCK_CHANGED = true, + ACTIONBAR_SLOT_CHANGED = true, + } + self.frame:SetScript("OnEvent", function() + local event = event + if event == "PLAYER_ENTERING_WORLD" then + inPlw = false + elseif event == "PLAYER_LEAVING_WORLD" then + inPlw = true + end + if event and (not inPlw or not blacklist[event]) then + self:TriggerEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + end + end) + if self.delayRegistry then + delayRegistry = self.delayRegistry + self.frame:SetScript("OnUpdate", OnUpdate) + end + + self:UnregisterAllEvents() + self:CancelAllScheduledEvents() + + registeringFromAceEvent = true + self:RegisterEvent("LOOT_OPENED", function() + SendAddonMessage("LOOT_OPENED", "", "RAID") + end) + registeringFromAceEvent = nil + + if not self.playerLogin then + registeringFromAceEvent = true + self:RegisterEvent("PLAYER_LOGIN", function() + self.playerLogin = true + end, true) + registeringFromAceEvent = nil + end + + if not self.postInit then + local isReload = true + local function func() + self.postInit = true + self:TriggerEvent("AceEvent_FullyInitialized") + if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then + self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE") + end + if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then + self:UnregisterEvent("MEETINGSTONE_CHANGED") + end + if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then + self:UnregisterEvent("MINIMAP_ZONE_CHANGED") + end + if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then + self:UnregisterEvent("LANGUAGE_LIST_CHANGED") + end + end + registeringFromAceEvent = true + local f = function() + self.playerLogin = true + self:ScheduleEvent("AceEvent_FullyInitialized", func, 1) + end + self:RegisterEvent("MEETINGSTONE_CHANGED", f, true) + self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function() + self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.05) + end) + self:RegisterEvent("LANGUAGE_LIST_CHANGED", function() + if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then + registeringFromAceEvent = true + self:UnregisterEvent("MEETINGSTONE_CHANGED") + self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true) + registeringFromAceEvent = nil + end + end) + self:ScheduleEvent("AceEvent_FullyInitialized", func, 10) + registeringFromAceEvent = nil + end + + self.super.activate(self, oldLib, oldDeactivate) + if oldLib then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, AceEvent.activate) +AceEvent = AceLibrary(MAJOR_VERSION) diff --git a/Libs/AceHook-2.1/AceHook-2.1.lua b/Libs/AceHook-2.1/AceHook-2.1.lua new file mode 100644 index 0000000..8beaf66 --- /dev/null +++ b/Libs/AceHook-2.1/AceHook-2.1.lua @@ -0,0 +1,569 @@ +--[[ +Name: AceHook-2.1 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceHook-2.1 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1 +Description: Mixin to allow for safe hooking of functions, methods, and scripts. +Dependencies: AceLibrary, AceOO-2.0 +]] + +local MAJOR_VERSION = "AceHook-2.1" +local MINOR_VERSION = "$Revision: 17638 $" + +-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end + +--[[--------------------------------------------------------------------------------- + Create the library object +----------------------------------------------------------------------------------]] + +local AceOO = AceLibrary:GetInstance("AceOO-2.0") +local AceHook = AceOO.Mixin { + "Hook", + "HookScript", + "SecureHook", + "Unhook", + "UnhookAll", + "HookReport", + "IsHooked", + } + +--[[--------------------------------------------------------------------------------- + Library Definitions +----------------------------------------------------------------------------------]] + +local protFuncs = { + CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true, + TurnOrActionStart = true, TurnOrActionStop = true, + PitchUpStart = true, PitchUpStop = true, + PitchDownStart = true, PitchDownStop = true, + MoveBackwardStart = true, MoveBackwardStop = true, + MoveForwardStart = true, MoveForwardStop = true, + Jump = true, StrafeLeftStart = true, + StrafeLeftStop = true, StrafeRightStart = true, + StrafeRightStop = true, ToggleMouseMove = true, + ToggleRun = true, TurnLeftStart = true, + TurnLeftStop = true, TurnRightStart = true, + TurnRightStop = true, +} + +local function issecurevariable(x) + if protFuncs[x] then + return 1 + else + return nil + end +end + +local _G = getfenv(0) + +local function hooksecurefunc(arg1, arg2, arg3) + if type(arg1) == "string" then + arg1, arg2, arg3 = _G, arg1, arg2 + end + local orig = arg1[arg2] + arg1[arg2] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + local x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 = orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + + arg3(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + + return x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 + end +end + +local protectedScripts = { + OnClick = true, +} + + +local handlers, scripts, actives, registry + +--[[--------------------------------------------------------------------------------- + Private definitions (Not exposed) +----------------------------------------------------------------------------------]] + +local new, del +do + local list = setmetatable({}, {__mode = "k"}) + function new() + local t = next(list) + if not t then + return {} + end + list[t] = nil + return t + end + + function del(t) + setmetatable(t, nil) + for k in pairs(t) do + t[k] = nil + end + list[t] = true + end +end + +local function createFunctionHook(self, func, handler, orig, secure) + if not secure then + if type(handler) == "string" then + -- The handler is a method, need to self it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + else + -- secure hooks don't call the original method + if type(handler) == "string" then + -- The handler is a method, need to self it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + end +end + +local function createMethodHook(self, object, method, handler, orig, secure, script) + if script then + if type(handler) == "string" then + local uid + uid = function() + if actives[uid] then + return self[handler](self, object) + else + return orig() + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function() + if actives[uid] then + return handler(object) + else + return orig() + end + end + return uid + end + elseif not secure then + if type(handler) == "string" then + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + else + -- secure hooks don't call the original method + if type(handler) == "string" then + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + end +end + +local function hookFunction(self, func, handler, secure) + local orig = _G[func] + + if not orig or type(orig) ~= "function" then + AceHook:error("Attempt to hook a non-existant function %q", func) + end + + if not handler then + handler = func + end + + if registry[self][func] then + local uid = registry[self][func] + + if actives[uid] then + -- We have an active hook from this source. Don't multi-hook + AceHook:error("%q already has an active hook from this source.", func) + end + + if handlers[uid] == handler then + -- The hook is inactive, so reactivate it + actives[uid] = true + return + else + AceHook:error("There is a stale hook for %q can't hook or reactivate.", func) + end + end + + if type(handler) == "string" then + if type(self[handler]) ~= "function" then + AceHook:error("Could not find the the handler %q when hooking function %q", handler, func) + end + elseif type(handler) ~= "function" then + AceHook:error("Could not find the handler you supplied when hooking %q", func) + end + + local uid = createFunctionHook(self, func, handler, orig, secure) + registry[self][func] = uid + actives[uid] = true + handlers[uid] = handler + + if not secure then + _G[func] = uid + self.hooks[func] = orig + else + hooksecurefunc(func, uid) + end +end + +local function unhookFunction(self, func) + if not registry[self][func] then + AceHook:error("Tried to unhook %q which is not currently hooked.", func) + end + + local uid = registry[self][func] + + if actives[uid] then + -- See if we own the global function + if self.hooks[func] and _G[func] == uid then + _G[func] = self.hooks[func] + self.hooks[func] = nil + registry[self][func] = nil + handlers[uid] = nil + scripts[uid] = nil + actives[uid] = nil + -- Magically all-done + else + actives[uid] = nil + end + end +end + +local function hookMethod(self, obj, method, handler, script, secure) + if not handler then + handler = method + end + + if not obj or type(obj) ~= "table" then + AceHook:error("The object you supplied could not be found, or isn't a table.") + end + + local uid = registry[self][obj] and registry[self][obj][method] + if uid then + if actives[uid] then + -- We have an active hook from this source. Don't multi-hook + AceHook:error("%q already has an active hook from this source.", method) + end + + if handlers[uid] == handler then + -- The hook is inactive, reactivate it. + actives[uid] = true + return + else + AceHook:error("There is a stale hook for %q can't hook or reactivate.", method) + end + end + + if type(handler) == "string" then + if type(self[handler]) ~= "function" then + AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method) + end + elseif type(handler) ~= "function" then + AceHook:error("Could not find the handler you supplied when hooking method %q", method) + end + + local orig + if script then + if not obj.GetScript then + AceHook:error("The object you supplied does not have a GetScript method.") + end + if not obj:HasScript(method) then + AceHook:error("The object you supplied doesn't allow the %q method.", method) + end + + orig = obj:GetScript(method) + if type(orig) ~= "function" then + -- Sometimes there is not a original function for a script. + orig = function() end + end + else + orig = obj[method] + end + if not orig then + AceHook:error("Could not find the method or script %q you are trying to hook.", method) + end + + if not registry[self][obj] then + registry[self][obj] = new() + end + + if not self.hooks[obj] then + self.hooks[obj] = new() + end + + local uid = createMethodHook(self, obj, method, handler, orig, secure, script) + registry[self][obj][method] = uid + actives[uid] = true + handlers[uid] = handler + scripts[uid] = script and true or nil + + if script then + obj:SetScript(method, uid) + self.hooks[obj][method] = orig + elseif not secure then + obj[method] = uid + self.hooks[obj][method] = orig + else + hooksecurefunc(obj, method, uid) + end +end + +local function unhookMethod(self, obj, method) + if not registry[self][obj] or not registry[self][obj][method] then + AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method) + return + end + + local uid = registry[self][obj][method] + + if actives[uid] then + if scripts[uid] then -- If this is a script + if obj:GetScript(method) == uid then + -- We own the script. Revert to normal. + obj:SetScript(method, self.hooks[obj][method]) + self.hooks[obj][method] = nil + registry[self][obj][method] = nil + handlers[uid] = nil + scripts[uid] = nil + actives[uid] = nil + else + actives[uid] = nil + end + else + if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then + -- We own the method. Revert to normal. + obj[method] = self.hooks[obj][method] + self.hooks[obj][method] = nil + registry[self][obj][method] = nil + handlers[uid] = nil + actives[uid] = nil + else + actives[uid] = nil + end + end + end + if self.hooks[obj] and not next(self.hooks[obj]) then + self.hooks[obj] = del(self.hooks[obj]) + end + if not next(registry[self][obj]) then + registry[self][obj] = del(registry[self][obj]) + end +end + +-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure]) +function AceHook:Hook(object, method, handler, hookSecure) + if type(object) == "string" then + method, handler, hookSecure = object, method, handler + if handler == true then + handler, hookSecure = nil, true + end + if not hookSecure and issecurevariable(method) then + AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method) + end + AceHook:argCheck(handler, 3, "function", "string", "nil") + AceHook:argCheck(hookSecure, 4, "boolean", "nil") + hookFunction(self, method, handler, false) + else + if handler == true then + handler, hookSecure = nil, true + end + if not hookSecure and issecurevariable(object, method) then + AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method) + end + AceHook:argCheck(object, 2, "table") + AceHook:argCheck(method, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + AceHook:argCheck(hookSecure, 5, "boolean", "nil") + hookMethod(self, object, method, handler, false, false) + end +end + +-- ("function", handler) or (object, "method", handler) +function AceHook:SecureHook(object, method, handler) + if type(object) == "string" then + method, handler = object, method + AceHook:argCheck(handler, 3, "function", "string", "nil") + hookFunction(self, method, handler, true) + else + AceHook:argCheck(object, 2, "table") + AceHook:argCheck(method, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + hookMethod(self, object, method, handler, false, true) + end +end + +function AceHook:HookScript(frame, script, handler) + AceHook:argCheck(frame, 2, "table") + if not frame[0] or type(frame.IsFrameType) ~= "function" then + AceHook:error("Bad argument #2 to `HookScript'. Expected frame.") + end + AceHook:argCheck(script, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + hookMethod(self, frame, script, handler, true, false) +end + +-- ("function") or (object, "method") +function AceHook:IsHooked(obj, method) + if type(obj) == "string" then + if registry[self][obj] and actives[registry[self][obj]] then + return true, handlers[registry[self][obj]] + end + else + AceHook:argCheck(obj, 2, "string", "table") + AceHook:argCheck(method, 3, "string") + if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then + return true, handlers[registry[self][obj][method]] + end + end + + return false, nil +end + +-- ("function") or (object, "method") +function AceHook:Unhook(obj, method) + if type(obj) == "string" then + unhookFunction(self, obj) + else + AceHook:argCheck(obj, 2, "string", "table") + AceHook:argCheck(method, 3, "string") + unhookMethod(self, obj, method) + end +end + +function AceHook:UnhookAll() + for key, value in pairs(registry[self]) do + if type(key) == "table" then + for method in pairs(value) do + self:Unhook(key, method) + end + else + self:Unhook(key) + end + end +end + +function AceHook:HookReport() + DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:") + if not next(registry[self]) then + DEFAULT_CHAT_FRAME:AddMessage("No hooks") + end + + for key, value in pairs(registry[self]) do + if type(value) == "table" then + for method, uid in pairs(value) do + DEFAULT_CHAT_FRAME:AddMessage(string.format("object: %s method: %q |cff%s|r%s", tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or "")) + end + else + DEFAULT_CHAT_FRAME:AddMessage(string.format("function: %q |cff%s|r%s", tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or "")) + end + end +end + +function AceHook:OnInstanceInit(object) + if not object.hooks then + object.hooks = new() + end + if not registry[object] then + registry[object] = new() + end +end + +AceHook.OnManualEmbed = AceHook.OnInstanceInit + +function AceHook:OnEmbedDisable(target) + self.UnhookAll(target) +end + +local function activate(self, oldLib, oldDeactivate) + AceHook = self + + self.handlers = oldLib and oldLib.handlers or {} + self.registry = oldLib and oldLib.registry or {} + self.scripts = oldLib and oldLib.scripts or {} + self.actives = oldLib and oldLib.actives or {} + + handlers = self.handlers + registry = self.registry + scripts = self.scripts + actives = self.actives + + AceHook.super.activate(self, oldLib, oldDeactivate) + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate) diff --git a/Libs/AceLibrary/AceLibrary.lua b/Libs/AceLibrary/AceLibrary.lua new file mode 100644 index 0000000..0f2b237 --- /dev/null +++ b/Libs/AceLibrary/AceLibrary.lua @@ -0,0 +1,757 @@ +--[[ +Name: AceLibrary +Revision: $Rev: 17722 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Iriel (iriel@vigilance-committee.org) + Tekkub (tekkub@gmail.com) + Revision: $Rev: 17722 $ +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceLibrary +SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary +Description: Versioning library to handle other library instances, upgrading, + and proper access. + It also provides a base for libraries to work off of, providing + proper error tools. It is handy because all the errors occur in the + file that called it, not in the library file itself. +Dependencies: None +]] + +local ACELIBRARY_MAJOR = "AceLibrary" +local ACELIBRARY_MINOR = "$Revision: 17722 $" + +if loadstring("return function(...) return ... end") and AceLibrary and AceLibrary:HasInstance(ACELIBRARY_MAJOR) then return end -- lua51 check +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local string_gfind = string.gmatch or string.gfind + +local _G = getfenv(0) +local previous = _G[ACELIBRARY_MAJOR] +if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end + +local function safecall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + local success, err = pcall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) + if not success then geterrorhandler()(err) end +end + +-- @table AceLibrary +-- @brief System to handle all versioning of libraries. +local AceLibrary = {} +local AceLibrary_mt = {} +setmetatable(AceLibrary, AceLibrary_mt) + +local tmp +local function error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if type(self) ~= "table" then + _G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2) + end + if not tmp then + tmp = {} + else + for k in pairs(tmp) do tmp[k] = nil end + table_setn(tmp, 0) + end + + table.insert(tmp, a1) + table.insert(tmp, a2) + table.insert(tmp, a3) + table.insert(tmp, a4) + table.insert(tmp, a5) + table.insert(tmp, a6) + table.insert(tmp, a7) + table.insert(tmp, a8) + table.insert(tmp, a9) + table.insert(tmp, a10) + table.insert(tmp, a11) + table.insert(tmp, a12) + table.insert(tmp, a13) + table.insert(tmp, a14) + table.insert(tmp, a15) + table.insert(tmp, a16) + table.insert(tmp, a17) + table.insert(tmp, a18) + table.insert(tmp, a19) + table.insert(tmp, a20) + + local stack = debugstack() + if not message then + local _,_,second = string.find(stack, "\n(.-)\n") + message = "error raised! " .. second + else + for i = 1,table.getn(tmp) do + tmp[i] = tostring(tmp[i]) + end + for i = 1,10 do + table.insert(tmp, "nil") + end + message = string.format(message, unpack(tmp)) + end + + if getmetatable(self) and getmetatable(self).__tostring then + message = string.format("%s: %s", tostring(self), message) + elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then + message = string.format("%s: %s", self:GetLibraryVersion(), message) + elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then + message = string.format("%s: %s", self.class:GetLibraryVersion(), message) + end + + local first = string.gsub(stack, "\n.*", "") + local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1") + file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + + local i = 0 + for s in string_gfind(stack, "\n([^\n]*)") do + i = i + 1 + if not string.find(s, file .. "%.lua:%d+:") then + file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1") + file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + break + end + end + local j = 0 + for s in string_gfind(stack, "\n([^\n]*)") do + j = j + 1 + if j > i and not string.find(s, file .. "%.lua:%d+:") then + _G.error(message, j + 1) + return + end + end + _G.error(message, 2) + return +end + +local function assert(self, condition, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if not condition then + if not message then + local stack = debugstack() + local _,_,second = string.find(stack, "\n(.-)\n") + message = "assertion failed! " .. second + end + error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + return + end + return condition +end + +local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5) + if type(num) ~= "number" then + error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num)) + elseif type(kind) ~= "string" then + error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind)) + end + local errored = false + arg = type(arg) + if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then + local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])") + if not func then + _,_,func = string.find(debugstack(), "([`<].-['>])") + end + if kind5 then + error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg) + elseif kind4 then + error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg) + elseif kind3 then + error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg) + elseif kind2 then + error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg) + else + error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg) + end + end +end + +local function pcall(self, func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = _G.pcall(func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + if not a1 then + error(self, string.gsub(a2, ".-%.lua:%d-: ", "")) + else + return a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 + end +end + +local recurse = {} +local function addToPositions(t, major) + if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then + rawset(t, recurse, true) + AceLibrary.positions[t] = major + for k,v in pairs(t) do + if type(v) == "table" and not rawget(v, recurse) then + addToPositions(v, major) + end + if type(k) == "table" and not rawget(k, recurse) then + addToPositions(k, major) + end + end + local mt = getmetatable(t) + if mt and not rawget(mt, recurse) then + addToPositions(mt, major) + end + rawset(t, recurse, nil) + end +end + +local function svnRevisionToNumber(text) + if type(text) == "string" then + if string.find(text, "^%$Revision: (%d+) %$$") then + return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1"))) + elseif string.find(text, "^%$Rev: (%d+) %$$") then + return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1"))) + elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then + return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1"))) + end + elseif type(text) == "number" then + return text + end + return nil +end + +local crawlReplace +do + local recurse = {} + local function func(t, to, from) + if recurse[t] then + return + end + recurse[t] = true + local mt = getmetatable(t) + setmetatable(t, nil) + rawset(t, to, rawget(t, from)) + rawset(t, from, nil) + for k,v in pairs(t) do + if v == from then + t[k] = to + elseif type(v) == "table" then + if not recurse[v] then + func(v, to, from) + end + end + + if type(k) == "table" then + if not recurse[k] then + func(k, to, from) + end + end + end + setmetatable(t, mt) + if mt then + if mt == from then + setmetatable(t, to) + elseif not recurse[mt] then + func(mt, to, from) + end + end + end + function crawlReplace(t, to, from) + func(t, to, from) + for k in pairs(recurse) do + recurse[k] = nil + end + end +end + +-- @function destroyTable +-- @brief remove all the contents of a table +-- @param t table to destroy +local function destroyTable(t) + setmetatable(t, nil) + for k,v in pairs(t) do t[k] = nil end + table_setn(t, 0) +end + +local function isFrame(frame) + return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function" +end + +local new, del +do + local tables = setmetatable({}, {__mode = "k"}) + + function new() + local t = next(tables) + if t then + tables[t] = nil + return t + else + return {} + end + end + + function del(t, depth) + if depth and depth > 0 then + for k,v in pairs(t) do + if type(v) == "table" and not isFrame(v) then + del(v, depth - 1) + end + end + end + destroyTable(t) + tables[t] = true + end +end + +-- @function copyTable +-- @brief Create a shallow copy of a table and return it. +-- @param from The table to copy from +-- @return A shallow copy of the table +local function copyTable(from) + local to = new() + for k,v in pairs(from) do to[k] = v end + table_setn(to, table.getn(from)) + setmetatable(to, getmetatable(from)) + return to +end + +-- @function deepTransfer +-- @brief Fully transfer all data, keeping proper previous table +-- backreferences stable. +-- @param to The table with which data is to be injected into +-- @param from The table whose data will be injected into the first +-- @param saveFields If available, a shallow copy of the basic data is saved +-- in here. +-- @param list The account of table references +-- @param list2 The current status on which tables have been traversed. +local deepTransfer +do + -- @function examine + -- @brief Take account of all the table references to be shared + -- between the to and from tables. + -- @param to The table with which data is to be injected into + -- @param from The table whose data will be injected into the first + -- @param list An account of the table references + local function examine(to, from, list, major) + list[from] = to + for k,v in pairs(from) do + if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then + if from[k] == to[k] then + list[from[k]] = to[k] + elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then + list[from[k]] = from[k] + elseif not list[from[k]] then + examine(to[k], from[k], list, major) + end + end + end + return list + end + + function deepTransfer(to, from, saveFields, major, list, list2) + setmetatable(to, nil) + local createdList + if not list then + createdList = true + list = new() + list2 = new() + examine(to, from, list, major) + end + list2[to] = to + for k,v in pairs(to) do + if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then + if saveFields then + saveFields[k] = v + end + to[k] = nil + elseif v ~= _G then + if saveFields then + saveFields[k] = copyTable(v) + end + end + end + for k in pairs(from) do + if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then + if not list2[to[k]] then + deepTransfer(to[k], from[k], nil, major, list, list2) + end + to[k] = list[to[k]] or list2[to[k]] + else + rawset(to, k, from[k]) + end + end + table_setn(to, table.getn(from)) + setmetatable(to, getmetatable(from)) + local mt = getmetatable(to) + if mt then + if list[mt] then + setmetatable(to, list[mt]) + elseif mt.__index and list[mt.__index] then + mt.__index = list[mt.__index] + end + end + destroyTable(from) + if createdList then + del(list) + del(list2) + end + end +end + +-- @method TryToLoadStandalone +-- @brief Attempt to find and load a standalone version of the requested library +-- @param major A string representing the major version +-- @return If library is found, return values from the call to LoadAddOn are returned +-- If the library has been requested previously, nil is returned. +local function TryToLoadStandalone(major) + if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end + if AceLibrary.scannedlibs[major] then return end + + AceLibrary.scannedlibs[major] = true + + local name, _, _, enabled, loadable = GetAddOnInfo(major) + if loadable then + return LoadAddOn(name) + end + + for i=1,GetNumAddOns() do + if GetAddOnMetadata(i, "X-AceLibrary-"..major) then + local name, _, _, enabled, loadable = GetAddOnInfo(i) + if loadable then + return LoadAddOn(name) + end + end + end +end + +-- @method IsNewVersion +-- @brief Obtain whether the supplied version would be an upgrade to the +-- current version. This allows for bypass code in library +-- declaration. +-- @param major A string representing the major version +-- @param minor An integer or an svn revision string representing the minor version +-- @return whether the supplied version would be newer than what is +-- currently available. +function AceLibrary:IsNewVersion(major, minor) + argCheck(self, major, 2, "string") + TryToLoadStandalone(major) + + if type(minor) == "string" then + local m = svnRevisionToNumber(minor) + if m then + minor = m + else + _G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) + end + end + argCheck(self, minor, 3, "number") + local data = self.libs[major] + if not data then + return true + end + return data.minor < minor +end + +-- @method HasInstance +-- @brief Returns whether an instance exists. This allows for optional support of a library. +-- @param major A string representing the major version. +-- @param minor (optional) An integer or an svn revision string representing the minor version. +-- @return Whether an instance exists. +function AceLibrary:HasInstance(major, minor) + argCheck(self, major, 2, "string") + TryToLoadStandalone(major) + + if minor then + if type(minor) == "string" then + local m = svnRevisionToNumber(minor) + if m then + minor = m + else + _G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) + end + end + argCheck(self, minor, 3, "number") + if not self.libs[major] then + return + end + return self.libs[major].minor == minor + end + return self.libs[major] and true +end + +-- @method GetInstance +-- @brief Returns the library with the given major/minor version. +-- @param major A string representing the major version. +-- @param minor (optional) An integer or an svn revision string representing the minor version. +-- @return The library with the given major/minor version. +function AceLibrary:GetInstance(major, minor) + argCheck(self, major, 2, "string") + TryToLoadStandalone(major) + + local data = self.libs[major] + if not data then + _G.error(string.format("Cannot find a library instance of %s.", major), 2) + return + end + if minor then + if type(minor) == "string" then + local m = svnRevisionToNumber(minor) + if m then + minor = m + else + _G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) + end + end + argCheck(self, minor, 2, "number") + if data.minor ~= minor then + _G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2) + return + end + end + return data.instance +end + +-- Syntax sugar. AceLibrary("FooBar-1.0") +AceLibrary_mt.__call = AceLibrary.GetInstance + +local donothing + +local AceEvent + +-- @method Register +-- @brief Registers a new version of a given library. +-- @param newInstance the library to register +-- @param major the major version of the library +-- @param minor the minor version of the library +-- @param activateFunc (optional) A function to be called when the library is +-- fully activated. Takes the arguments +-- (newInstance [, oldInstance, oldDeactivateFunc]). If +-- oldInstance is given, you should probably call +-- oldDeactivateFunc(oldInstance). +-- @param deactivateFunc (optional) A function to be called by a newer library's +-- activateFunc. +-- @param externalFunc (optional) A function to be called whenever a new +-- library is registered. +function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc) + argCheck(self, newInstance, 2, "table") + argCheck(self, major, 3, "string") + if type(minor) == "string" then + local m = svnRevisionToNumber(minor) + if m then + minor = m + else + _G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) + end + end + argCheck(self, minor, 4, "number") + if math.floor(minor) ~= minor or minor < 0 then + error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor) + end + argCheck(self, activateFunc, 5, "function", "nil") + argCheck(self, deactivateFunc, 6, "function", "nil") + argCheck(self, externalFunc, 7, "function", "nil") + if not deactivateFunc then + if not donothing then + donothing = function() end + end + deactivateFunc = donothing + end + local data = self.libs[major] + if not data then + -- This is new + local instance = copyTable(newInstance) + crawlReplace(instance, instance, newInstance) + destroyTable(newInstance) + if AceLibrary == newInstance then + self = instance + AceLibrary = instance + end + self.libs[major] = { + instance = instance, + minor = minor, + deactivateFunc = deactivateFunc, + externalFunc = externalFunc, + } + rawset(instance, 'GetLibraryVersion', function(self) + return major, minor + end) + if not rawget(instance, 'error') then + rawset(instance, 'error', error) + end + if not rawget(instance, 'assert') then + rawset(instance, 'assert', assert) + end + if not rawget(instance, 'argCheck') then + rawset(instance, 'argCheck', argCheck) + end + if not rawget(instance, 'pcall') then + rawset(instance, 'pcall', pcall) + end + addToPositions(instance, major) + if activateFunc then + safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil + end + + if externalFunc then + for k,data in pairs(self.libs) do + if k ~= major then + safecall(externalFunc, instance, k, data.instance) + end + end + end + + for k,data in pairs(self.libs) do + if k ~= major and data.externalFunc then + safecall(data.externalFunc, data.instance, major, instance) + end + end + if major == "AceEvent-2.0" then + AceEvent = instance + end + if AceEvent then + AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance) + end + + return instance + end + local instance = data.instance + if minor <= data.minor then + -- This one is already obsolete, raise an error. + _G.error(string.format("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end", major, data.minor, minor, major, minor), 2) + return + end + -- This is an update + local oldInstance = new() + + addToPositions(newInstance, major) + local isAceLibrary = (AceLibrary == newInstance) + local old_error, old_assert, old_argCheck, old_pcall + if isAceLibrary then + self = instance + AceLibrary = instance + + old_error = instance.error + old_assert = instance.assert + old_argCheck = instance.argCheck + old_pcall = instance.pcall + + self.error = error + self.assert = assert + self.argCheck = argCheck + self.pcall = pcall + end + deepTransfer(instance, newInstance, oldInstance, major) + crawlReplace(instance, instance, newInstance) + local oldDeactivateFunc = data.deactivateFunc + data.minor = minor + data.deactivateFunc = deactivateFunc + data.externalFunc = externalFunc + rawset(instance, 'GetLibraryVersion', function(self) + return major, minor + end) + if not rawget(instance, 'error') then + rawset(instance, 'error', error) + end + if not rawget(instance, 'assert') then + rawset(instance, 'assert', assert) + end + if not rawget(instance, 'argCheck') then + rawset(instance, 'argCheck', argCheck) + end + if not rawget(instance, 'pcall') then + rawset(instance, 'pcall', pcall) + end + if isAceLibrary then + for _,v in pairs(self.libs) do + local i = type(v) == "table" and v.instance + if type(i) == "table" then + if not rawget(i, 'error') or i.error == old_error then + rawset(i, 'error', error) + end + if not rawget(i, 'assert') or i.assert == old_assert then + rawset(i, 'assert', assert) + end + if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then + rawset(i, 'argCheck', argCheck) + end + if not rawget(i, 'pcall') or i.pcall == old_pcall then + rawset(i, 'pcall', pcall) + end + end + end + end + if activateFunc then + safecall(activateFunc, instance, oldInstance, oldDeactivateFunc) + else + safecall(oldDeactivateFunc, oldInstance) + end + del(oldInstance) + + if externalFunc then + for k,data in pairs(self.libs) do + if k ~= major then + safecall(externalFunc, instance, k, data.instance) + end + end + end + + return instance +end + +local iter +function AceLibrary:IterateLibraries() + if not iter then + local function iter(t, k) + k = next(t, k) + if not k then + return nil + else + return k, t[k].instance + end + end + end + return iter, self.libs, nil +end + +-- @function Activate +-- @brief The activateFunc for AceLibrary itself. Called when +-- AceLibrary properly registers. +-- @param self Reference to AceLibrary +-- @param oldLib (optional) Reference to an old version of AceLibrary +-- @param oldDeactivate (optional) Function to deactivate the old lib +local function activate(self, oldLib, oldDeactivate) + if not self.libs then + if oldLib then + self.libs = oldLib.libs + self.scannedlibs = oldLib.scannedlibs + end + if not self.libs then + self.libs = {} + end + if not self.scannedlibs then + self.scannedlibs = {} + end + end + if not self.positions then + if oldLib then + self.positions = oldLib.positions + end + if not self.positions then + self.positions = setmetatable({}, { __mode = "k" }) + end + end + + -- Expose the library in the global environment + _G[ACELIBRARY_MAJOR] = self + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +if not previous then + previous = AceLibrary +end +if not previous.libs then + previous.libs = {} +end +AceLibrary.libs = previous.libs +if not previous.positions then + previous.positions = setmetatable({}, { __mode = "k" }) +end +AceLibrary.positions = previous.positions +AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate) diff --git a/Libs/AceLocale-2.2/AceLocale-2.2.lua b/Libs/AceLocale-2.2/AceLocale-2.2.lua new file mode 100644 index 0000000..cc2759a --- /dev/null +++ b/Libs/AceLocale-2.2/AceLocale-2.2.lua @@ -0,0 +1,538 @@ +--[[ +Name: AceLocale-2.2 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceLocale-2.2 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.2 +Description: Localization library for addons to use to handle proper + localization and internationalization. +Dependencies: AceLibrary +]] + +local MAJOR_VERSION = "AceLocale-2.2" +local MINOR_VERSION = "$Revision: 17638 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +local AceLocale = {} + +local DEFAULT_LOCALE = "enUS" +local _G = getfenv(0) + +local BASE_TRANSLATIONS, DEBUGGING, TRANSLATIONS, BASE_LOCALE, TRANSLATION_TABLES, REVERSE_TRANSLATIONS, STRICTNESS, DYNAMIC_LOCALES, CURRENT_LOCALE, NAME + +local rawget = rawget +local rawset = rawset +local type = type + +local newRegistries = {} +local scheduleClear + +local lastSelf +local __index = function(self, key) + lastSelf = self + local value = (rawget(self, TRANSLATIONS) or AceLocale.prototype)[key] + rawset(self, key, value) + return value +end + +local __newindex = function(self, k, v) + if type(v) ~= "function" and type(k) ~= "table" then + AceLocale.error(self, "Cannot change the values of an AceLocale instance.") + end + rawset(self, k, v) +end + +local __tostring = function(self) + if type(rawget(self, 'GetLibraryVersion')) == "function" then + return self:GetLibraryVersion() + else + return "AceLocale(" .. self[NAME] .. ")" + end +end + +local function clearCache(self) + if not rawget(self, BASE_TRANSLATIONS) then + return + end + + local cache = self[BASE_TRANSLATIONS] + rawset(self, REVERSE_TRANSLATIONS, nil) + + for k in pairs(self) do + if rawget(cache, k) ~= nil then + self[k] = nil + end + end + rawset(self, 'tmp', true) + self.tmp = nil +end + +local function refixInstance(instance) + if getmetatable(instance) then + setmetatable(instance, nil) + end + local translations = instance[TRANSLATIONS] + if translations then + if getmetatable(translations) then + setmetatable(translations, nil) + end + local baseTranslations = instance[BASE_TRANSLATIONS] + if getmetatable(baseTranslations) then + setmetatable(baseTranslations, nil) + end + if translations == baseTranslations or instance[STRICTNESS] then + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __tostring = __tostring + }) + + setmetatable(translations, { + __index = AceLocale.prototype + }) + else + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __tostring = __tostring + }) + + setmetatable(translations, { + __index = baseTranslations, + }) + + setmetatable(baseTranslations, { + __index = AceLocale.prototype, + }) + end + else + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __tostring = __tostring, + }) + end + clearCache(instance) + newRegistries[instance] = true + scheduleClear() + return instance +end + +function AceLocale:new(name) + self:argCheck(name, 2, "string") + + if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then + return self.registry[name] + end + + AceLocale.registry[name] = refixInstance({ + [STRICTNESS] = false, + [NAME] = name, + }) + newRegistries[AceLocale.registry[name]] = true + return AceLocale.registry[name] +end + +AceLocale.prototype = { class = AceLocale } + +function AceLocale.prototype:EnableDebugging() + if rawget(self, BASE_TRANSLATIONS) then + AceLocale.error(self, "Cannot enable debugging after a translation has been registered.") + end + rawset(self, DEBUGGING, true) +end + +function AceLocale.prototype:EnableDynamicLocales(override) + AceLocale.argCheck(self, override, 2, "boolean", "nil") + if not override and rawget(self, BASE_TRANSLATIONS) then + AceLocale.error(self, "Cannot enable dynamic locales after a translation has been registered.") + end + if not rawget(self, DYNAMIC_LOCALES) then + rawset(self, DYNAMIC_LOCALES, true) + if rawget(self, BASE_LOCALE) then + if not rawget(self, TRANSLATION_TABLES) then + rawset(self, TRANSLATION_TABLES, {}) + end + self[TRANSLATION_TABLES][self[BASE_LOCALE]] = self[BASE_TRANSLATIONS] + self[TRANSLATION_TABLES][self[CURRENT_LOCALE]] = self[TRANSLATIONS] + end + end +end + +function AceLocale.prototype:RegisterTranslations(locale, func) + AceLocale.argCheck(self, locale, 2, "string") + AceLocale.argCheck(self, func, 3, "function") + + if locale == rawget(self, BASE_LOCALE) then + AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) + end + + if rawget(self, BASE_TRANSLATIONS) and GetLocale() ~= locale then + if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then + if not rawget(self, TRANSLATION_TABLES) then + rawset(self, TRANSLATION_TABLES, {}) + end + if self[TRANSLATION_TABLES][locale] then + AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) + end + local t = func() + func = nil + if type(t) ~= "table" then + AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) + end + self[TRANSLATION_TABLES][locale] = t + t = nil + end + func = nil + return + end + local t = func() + func = nil + if type(t) ~= "table" then + AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) + end + + rawset(self, TRANSLATIONS, t) + if not rawget(self, BASE_TRANSLATIONS) then + rawset(self, BASE_TRANSLATIONS, t) + rawset(self, BASE_LOCALE, locale) + for key,value in pairs(t) do + if value == true then + t[key] = key + end + end + else + for key, value in pairs(self[TRANSLATIONS]) do + if not rawget(self[BASE_TRANSLATIONS], key) then + AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale) + end + if value == true then + AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, BASE_LOCALE), locale) + end + end + end + rawset(self, CURRENT_LOCALE, locale) + refixInstance(self) + if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then + if not rawget(self, TRANSLATION_TABLES) then + rawset(self, TRANSLATION_TABLES, {}) + end + self[TRANSLATION_TABLES][locale] = t + end + t = nil +end + +function AceLocale.prototype:SetLocale(locale) + AceLocale.argCheck(self, locale, 2, "string", "boolean") + if not rawget(self, DYNAMIC_LOCALES) then + AceLocale.error(self, "Cannot call `SetLocale' without first calling `EnableDynamicLocales'.") + end + if not rawget(self, TRANSLATION_TABLES) then + AceLocale.error(self, "Cannot call `SetLocale' without first calling `RegisterTranslations'.") + end + if locale == true then + locale = GetLocale() + if not self[TRANSLATION_TABLES][locale] then + locale = self[BASE_LOCALE] + end + end + + if self[CURRENT_LOCALE] == locale then + return + end + + if not self[TRANSLATION_TABLES][locale] then + AceLocale.error(self, "Locale %q not registered.", locale) + end + + self[TRANSLATIONS] = self[TRANSLATION_TABLES][locale] + self[CURRENT_LOCALE] = locale + refixInstance(self) +end + +function AceLocale.prototype:GetLocale() + if not rawget(self, TRANSLATION_TABLES) then + AceLocale.error(self, "Cannot call `GetLocale' without first calling `RegisterTranslations'.") + end + return self[CURRENT_LOCALE] +end + +local function iter(t, position) + return (next(t, position)) +end + +function AceLocale.prototype:IterateAvailableLocales() + if not rawget(self, DYNAMIC_LOCALES) then + AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `EnableDynamicLocales'.") + end + if not rawget(self, TRANSLATION_TABLES) then + AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `RegisterTranslations'.") + end + return iter, self[TRANSLATION_TABLES], nil +end + +function AceLocale.prototype:HasLocale(locale) + if not rawget(self, DYNAMIC_LOCALES) then + AceLocale.error(self, "Cannot call `HasLocale' without first calling `EnableDynamicLocales'.") + end + AceLocale.argCheck(self, locale, 2, "string") + return rawget(self, TRANSLATION_TABLES) and self[TRANSLATION_TABLES][locale] ~= nil +end + +function AceLocale.prototype:SetStrictness(strict) + AceLocale.argCheck(self, strict, 2, "boolean") + local mt = getmetatable(self) + if not mt then + AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.") + end + if not rawget(self, TRANSLATIONS) then + AceLocale.error(self, "No translations registered.") + end + rawset(self, STRICTNESS, strict) + refixInstance(self) +end + +local function initReverse(self) + rawset(self, REVERSE_TRANSLATIONS, {}) + local alpha = self[TRANSLATIONS] + local bravo = self[REVERSE_TRANSLATIONS] + for base, localized in pairs(alpha) do + bravo[localized] = base + end +end + +function AceLocale.prototype:GetTranslation(text) + AceLocale.argCheck(self, text, 1, "string", "number") + if not rawget(self, TRANSLATIONS) then + AceLocale.error(self, "No translations registered") + end + return self[text] +end + +function AceLocale.prototype:GetStrictTranslation(text) + AceLocale.argCheck(self, text, 1, "string", "number") + local x = rawget(self, TRANSLATIONS) + if not x then + AceLocale.error(self, "No translations registered") + end + local value = rawget(x, text) + if value == nil then + AceLocale.error(self, "Translation %q does not exist for locale %s", text, self[CURRENT_LOCALE]) + end + return value +end + +function AceLocale.prototype:GetReverseTranslation(text) + local x = rawget(self, REVERSE_TRANSLATIONS) + if not x then + if not rawget(self, TRANSLATIONS) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[REVERSE_TRANSLATIONS] + end + local translation = x[text] + if not translation then + AceLocale.error(self, "Reverse translation for %q does not exist", text) + end + return translation +end + +function AceLocale.prototype:GetIterator() + local x = rawget(self, TRANSLATIONS) + if not x then + AceLocale.error(self, "No translations registered") + end + return next, x, nil +end + +function AceLocale.prototype:GetReverseIterator() + local x = rawget(self, REVERSE_TRANSLATIONS) + if not x then + if not rawget(self, TRANSLATIONS) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[REVERSE_TRANSLATIONS] + end + return next, x, nil +end + +function AceLocale.prototype:HasTranslation(text) + AceLocale.argCheck(self, text, 1, "string", "number") + local x = rawget(self, TRANSLATIONS) + if not x then + AceLocale.error(self, "No translations registered") + end + return rawget(x, text) and true +end + +function AceLocale.prototype:HasReverseTranslation(text) + local x = rawget(self, REVERSE_TRANSLATIONS) + if not x then + if not rawget(self, TRANSLATIONS) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[REVERSE_TRANSLATIONS] + end + return x[text] and true +end + +function AceLocale.prototype:Debug() + if not rawget(self, DEBUGGING) then + return + end + local words = {} + local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW", "esES"} + local localizations = {} + DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---") + for _,locale in ipairs(locales) do + if not self[TRANSLATION_TABLES][locale] then + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q not found", locale)) + else + localizations[locale] = self[TRANSLATION_TABLES][locale] + end + end + local localeDebug = {} + for locale, localization in pairs(localizations) do + localeDebug[locale] = {} + for word in pairs(localization) do + if type(localization[word]) == "table" then + if type(words[word]) ~= "table" then + words[word] = {} + end + for bit in pairs(localization[word]) do + if type(localization[word][bit]) == "string" then + words[word][bit] = true + end + end + elseif type(localization[word]) == "string" then + words[word] = true + end + end + end + for word in pairs(words) do + if type(words[word]) == "table" then + for bit in pairs(words[word]) do + for locale, localization in pairs(localizations) do + if not rawget(localization, word) or not localization[word][bit] then + localeDebug[locale][word .. "::" .. bit] = true + end + end + end + else + for locale, localization in pairs(localizations) do + if not rawget(localization, word) then + localeDebug[locale][word] = true + end + end + end + end + for locale, t in pairs(localeDebug) do + if not next(t) then + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q complete", locale)) + else + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q missing:", locale)) + for word in pairs(t) do + DEFAULT_CHAT_FRAME:AddMessage(string.format(" %q", word)) + end + end + end + DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---") +end + +setmetatable(AceLocale.prototype, { + __index = function(self, k) + if type(k) ~= "table" and k ~= 0 and k ~= "GetLibraryVersion" and k ~= "error" and k ~= "assert" and k ~= "argCheck" and k ~= "pcall" then -- HACK: remove "GetLibraryVersion" and such later. + AceLocale.error(lastSelf or self, "Translation %q does not exist.", k) + end + return nil + end +}) + +local function activate(self, oldLib, oldDeactivate) + AceLocale = self + + self.frame = oldLib and oldLib.frame or CreateFrame("Frame") + self.registry = oldLib and oldLib.registry or {} + self.BASE_TRANSLATIONS = oldLib and oldLib.BASE_TRANSLATIONS or {} + self.DEBUGGING = oldLib and oldLib.DEBUGGING or {} + self.TRANSLATIONS = oldLib and oldLib.TRANSLATIONS or {} + self.BASE_LOCALE = oldLib and oldLib.BASE_LOCALE or {} + self.TRANSLATION_TABLES = oldLib and oldLib.TRANSLATION_TABLES or {} + self.REVERSE_TRANSLATIONS = oldLib and oldLib.REVERSE_TRANSLATIONS or {} + self.STRICTNESS = oldLib and oldLib.STRICTNESS or {} + self.NAME = oldLib and oldLib.NAME or {} + self.DYNAMIC_LOCALES = oldLib and oldLib.DYNAMIC_LOCALES or {} + self.CURRENT_LOCALE = oldLib and oldLib.CURRENT_LOCALE or {} + + BASE_TRANSLATIONS = self.BASE_TRANSLATIONS + DEBUGGING = self.DEBUGGING + TRANSLATIONS = self.TRANSLATIONS + BASE_LOCALE = self.BASE_LOCALE + TRANSLATION_TABLES = self.TRANSLATION_TABLES + REVERSE_TRANSLATIONS = self.REVERSE_TRANSLATIONS + STRICTNESS = self.STRICTNESS + NAME = self.NAME + DYNAMIC_LOCALES = self.DYNAMIC_LOCALES + CURRENT_LOCALE = self.CURRENT_LOCALE + + + local GetTime = GetTime + local timeUntilClear = GetTime() + 5 + scheduleClear = function() + if next(newRegistries) then + self.frame:Show() + timeUntilClear = GetTime() + 5 + end + end + + if not self.registry then + self.registry = {} + else + for name, instance in pairs(self.registry) do + local name = name + local mt = getmetatable(instance) + setmetatable(instance, nil) + instance[NAME] = name + local strict + if instance[STRICTNESS] ~= nil then + strict = instance[STRICTNESS] + elseif instance[TRANSLATIONS] ~= instance[BASE_TRANSLATIONS] then + if getmetatable(instance[TRANSLATIONS]).__index == oldLib.prototype then + strict = true + end + end + instance[STRICTNESS] = strict and true or false + refixInstance(instance) + end + end + + self.frame:SetScript("OnEvent", scheduleClear) + self.frame:SetScript("OnUpdate", function() -- (this, elapsed) + if timeUntilClear - GetTime() <= 0 then + self.frame:Hide() + for k in pairs(newRegistries) do + clearCache(k) + newRegistries[k] = nil + k = nil + end + end + end) + self.frame:UnregisterAllEvents() + self.frame:RegisterEvent("ADDON_LOADED") + self.frame:RegisterEvent("PLAYER_ENTERING_WORLD") + self.frame:Show() + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate) diff --git a/Libs/AceOO-2.0/AceOO-2.0.lua b/Libs/AceOO-2.0/AceOO-2.0.lua new file mode 100644 index 0000000..659be0f --- /dev/null +++ b/Libs/AceOO-2.0/AceOO-2.0.lua @@ -0,0 +1,1004 @@ +--[[ +Name: AceOO-2.0 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceOO-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceOO-2.0 +Description: Library to provide an object-orientation framework. +Dependencies: AceLibrary +]] + +local MAJOR_VERSION = "AceOO-2.0" +local MINOR_VERSION = "$Revision: 17638 $" + +-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +local table_setn +do + local version = GetBuildInfo() + if string.find(version, "^2%.") then + -- 2.0.0 + table_setn = function() end + else + table_setn = table.setn + end +end + +local AceOO = { + error = AceLibrary.error, + argCheck = AceLibrary.argCheck +} + +-- @function getuid +-- @brief Obtain a unique string identifier for the object in question. +-- @param t The object to obtain the uid for. +-- @return The uid string. +local function pad(cap) + return string.rep('0', 8 - string.len(cap)) .. cap +end +local function getuid(t) + local mt = getmetatable(t) + setmetatable(t, nil) + local str = tostring(t) + setmetatable(t, mt) + local _,_,cap = string.find(str, '[^:]*: 0x(.*)$') + if cap then return pad(cap) end + _,_,cap = string.find(str, '[^:]*: (.*)$') + if cap then return pad(cap) end +end + +local function getlibrary(o) + if type(o) == "table" then + return o + elseif type(o) == "string" then + if not AceLibrary:HasInstance(o) then + AceOO:error("Library %q does not exist.", o) + end + return AceLibrary(o) + end +end + +-- @function Factory +-- @brief Construct a factory for the creation of objects. +-- @param obj The object whose init method will be called on the new factory +-- object. +-- @param newobj The object whose init method will be called on the new +-- objects that the Factory creates, to initialize them. +-- @param (a1..a20) Arguments which will be passed to obj.init() in addition +-- to the Factory object. +-- @return The new factory which creates a newobj when its new method is called, +-- or when it is called directly (__call metamethod). +local Factory +do + local function new(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + local t = {} + local uid = getuid(t) + local l = getlibrary + obj:init(t, l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), + l(a8), l(a9), l(a10), l(a11), l(a12), l(a13), + l(a14), l(a15), l(a16), l(a17), l(a18), l(a19), + l(a20)) + t.uid = uid + return t + end + + local function createnew(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, + a19, a20) + local o = self.prototype + local l = getlibrary + return new(o, l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), + l(a8), l(a9), l(a10), l(a11), l(a12), l(a13), + l(a14), l(a15), l(a16), l(a17), l(a18), l(a19), + l(a20)) + end + + function Factory(obj, newobj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, + a19, a20) + local t = new(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + t.prototype = newobj + t.new = createnew + getmetatable(t).__call = t.new + return t + end +end + + +local function objtostring(self) + if self.ToString then + return self:ToString() + elseif self.GetLibraryVersion then + return (self:GetLibraryVersion()) + elseif self.super then + local s = "Sub-" .. tostring(self.super) + local first = true + if self.interfaces then + for interface in pairs(self.interfaces) do + if first then + s = s .. "(" .. tostring(interface) + first = false + else + s = s .. ", " .. tostring(interface) + end + end + end + if self.mixins then + for mixin in pairs(self.mixins) do + if first then + s = s .. tostring(mixin) + first = false + else + s = s .. ", " .. tostring(mixin) + end + end + end + if first then + if self.uid then + return s .. ":" .. self.uid + else + return s + end + else + return s .. ")" + end + else + return self.uid and 'Subclass:' .. self.uid or 'Subclass' + end +end + +-- @table Object +-- @brief Base of all objects, including Class. +-- +-- @method init +-- @brief Initialize a new object. +-- @param newobject The object to initialize +-- @param class The class to make newobject inherit from +local Object +do + Object = {} + function Object:init(newobject, class) + local parent = class or self + if not rawget(newobject, 'uid') then + newobject.uid = getuid(newobject) + end + local mt = { + __index = parent, + __tostring = objtostring, + } + setmetatable(newobject, mt) + end + Object.uid = getuid(Object) + setmetatable(Object, { __tostring = function() return 'Object' end }) +end + +local Interface + +local function validateInterface(object, interface) + if not object.class and object.prototype then + object = object.prototype + end + for k,v in pairs(interface.interface) do + if tostring(type(object[k])) ~= v then + return false + end + end + if interface.superinterfaces then + for superinterface in pairs(interface.superinterfaces) do + if not validateInterface(object, superinterface) then + return false + end + end + end + if type(object.class) == "table" and rawequal(object.class.prototype, object) then + if not object.class.interfaces then + rawset(object.class, 'interfaces', {}) + end + object.class.interfaces[interface] = true + elseif type(object.class) == "table" and type(object.class.prototype) == "table" then + validateInterface(object.class.prototype, interface) + -- check if class is proper, thus preventing future checks. + end + return true +end + +-- @function inherits +-- @brief Return whether an Object or Class inherits from a given +-- parent. +-- @param object Object or Class to check +-- @param parent Parent to test inheritance from +-- @return whether an Object or Class inherits from a given +-- parent. +local function inherits(object, parent) + object = getlibrary(object) + if type(parent) == "string" then + if not AceLibrary:HasInstance(parent) then + return false + else + parent = AceLibrary(parent) + end + end + AceOO:argCheck(parent, 2, "table") + if type(object) ~= "table" then + return false + end + local current + if object.class then + current = object.class + else + current = object + end + if type(current) ~= "table" then + return false + end + if rawequal(current, parent) then + return true + end + if parent.class then + while true do + if rawequal(current, Object) then + break + end + if current.mixins then + for mixin in pairs(current.mixins) do + if rawequal(mixin, parent) then + return true + end + end + end + if current.interfaces then + for interface in pairs(current.interfaces) do + if rawequal(interface, parent) then + return true + end + end + end + current = current.super + if type(current) ~= "table" then + break + end + end + + local isInterface = false + local curr = parent.class + while true do + if rawequal(curr, Object) then + break + elseif rawequal(curr, Interface) then + isInterface = true + break + end + curr = curr.super + if type(curr) ~= "table" then + break + end + end + return isInterface and validateInterface(object, parent) + else + while true do + if rawequal(current, parent) then + return true + elseif rawequal(current, Object) then + return false + end + current = current.super + if type(current) ~= "table" then + return false + end + end + end +end + +-- @table Class +-- @brief An object factory which sets up inheritence and supports +-- 'mixins'. +-- +-- @metamethod Class call +-- @brief Call ClassFactory:new() to create a new class. +-- +-- @method Class new +-- @brief Construct a new object. +-- @param (a1..a20) Arguments to pass to the object init function. +-- @return The new object. +-- +-- @method Class init +-- @brief Initialize a new class. +-- @param parent Superclass. +-- @param (a1..a20) Mixins. +-- +-- @method Class ToString +-- @return A string representing the object, in this case 'Class'. +local initStatus +local Class +local Mixin +local autoEmbed = false +local function traverseInterfaces(bit, total) + if bit.superinterfaces then + for interface in pairs(bit.superinterfaces) do + if not total[interface] then + total[interface] = true + traverseInterfaces(interface, total) + end + end + end +end +local class_new +do + Class = Factory(Object, setmetatable({}, {__index = Object}), Object) + Class.super = Object + + local function protostring(t) + return '<' .. tostring(t.class) .. ' prototype>' + end + local function classobjectstring(t) + if t.ToString then + return t:ToString() + elseif t.GetLibraryVersion then + return (t:GetLibraryVersion()) + else + return '<' .. tostring(t.class) .. ' instance>' + end + end + local function classobjectequal(self, other) + if type(self) == "table" and self.Equals then + return self:Equals(other) + elseif type(other) == "table" and other.Equals then + return other:Equals(self) + elseif type(self) == "table" and self.CompareTo then + return self:CompareTo(other) == 0 + elseif type(other) == "table" and other.CompareTo then + return other:CompareTo(self) == 0 + else + return rawequal(self, other) + end + end + local function classobjectlessthan(self, other) + if type(self) == "table" and self.IsLessThan then + return self:IsLessThan(other) + elseif type(other) == "table" and other.IsLessThanOrEqualTo then + return not other:IsLessThanOrEqualTo(self) + elseif type(self) == "table" and self.CompareTo then + return self:CompareTo(other) < 0 + elseif type(other) == "table" and other.CompareTo then + return other:CompareTo(self) > 0 + elseif type(other) == "table" and other.IsLessThan and other.Equals then + return other:Equals(self) or other:IsLessThan(self) + else + AceOO:error("cannot compare two objects") + end + end + local function classobjectlessthanequal(self, other) + if type(self) == "table" and self.IsLessThanOrEqualTo then + return self:IsLessThanOrEqualTo(other) + elseif type(other) == "table" and other.IsLessThan then + return not other:IsLessThan(self) + elseif type(self) == "table" and self.CompareTo then + return self:CompareTo(other) <= 0 + elseif type(other) == "table" and other.CompareTo then + return other:CompareTo(self) >= 0 + elseif type(self) == "table" and self.IsLessThan and self.Equals then + return self:Equals(other) or self:IsLessThan(other) + else + AceOO:error("cannot compare two incompatible objects") + end + end + local function classobjectadd(self, other) + if type(self) == "table" and self.Add then + return self:Add(other) + else + AceOO:error("cannot add two incompatible objects") + end + end + local function classobjectsub(self, other) + if type(self) == "table" and self.Subtract then + return self:Subtract(other) + else + AceOO:error("cannot subtract two incompatible objects") + end + end + local function classobjectunm(self, other) + if type(self) == "table" and self.UnaryNegation then + return self:UnaryNegation(other) + else + AceOO:error("attempt to negate an incompatible object") + end + end + local function classobjectmul(self, other) + if type(self) == "table" and self.Multiply then + return self:Multiply(other) + else + AceOO:error("cannot multiply two incompatible objects") + end + end + local function classobjectdiv(self, other) + if type(self) == "table" and self.Divide then + return self:Divide(other) + else + AceOO:error("cannot divide two incompatible objects") + end + end + local function classobjectpow(self, other) + if type(self) == "table" and self.Exponent then + return self:Exponent(other) + else + AceOO:error("cannot exponentiate two incompatible objects") + end + end + local function classobjectconcat(self, other) + if type(self) == "table" and self.Concatenate then + return self:Concatenate(other) + else + AceOO:error("cannot concatenate two incompatible objects") + end + end + function class_new(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + if self.virtual then + AceOO:error("Cannot instantiate a virtual class.") + end + + local o = self.prototype + local newobj = {} + if o.class and o.class.instancemeta then + setmetatable(newobj, o.class.instancemeta) + else + Object:init(newobj, o) + end + + if self.interfaces and not self.interfacesVerified then + -- Verify the interfaces + + for interface in pairs(self.interfaces) do + for field,kind in pairs(interface.interface) do + if tostring(type(newobj[field])) ~= kind then + AceOO:error("Class did not satisfy all interfaces. %q is required to be a %s. It is a %s", field, kind, tostring(type(newobj[field]))) + end + end + end + self.interfacesVerified = true + end + local tmp = initStatus + initStatus = newobj + newobj:init(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + if initStatus then + initStatus = tmp + AceOO:error("Initialization not completed, be sure to call the superclass's init method.") + return + end + initStatus = tmp + return newobj + end + local classmeta = { + __tostring = objtostring, + __call = function(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + return self:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20) + end, + } + function Class:init(newclass, parent, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, + a17, a18, a19, a20) + parent = parent or self + + local total + + if parent.class then + total = { + parent, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, + a17, a18, a19, a20 + } + parent = self + else + total = { + a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, + a17, a18, a19, a20 + } + end + if not inherits(parent, Class) then + AceOO:error("Classes must inherit from a proper class") + end + if parent.sealed then + AceOO:error("Cannot inherit from a sealed class") + end + for i,v in ipairs(total) do + if inherits(v, Mixin) and v.class then + if not newclass.mixins then + newclass.mixins = {} + end + if newclass.mixins[v] then + AceOO:error("Cannot explicitly inherit from the same mixin twice") + end + newclass.mixins[v] = true + elseif inherits(v, Interface) and v.class then + if not newclass.interfaces then + newclass.interfaces = {} + end + if newclass.interfaces[v] then + AceOO:error("Cannot explicitly inherit from the same interface twice") + end + newclass.interfaces[v] = true + else + AceOO:error("Classes can only inherit from one or zero classes and any number of mixins or interfaces") + end + end + if parent.interfaces then + if newclass.interfaces then + for interface in pairs(parent.interfaces) do + newclass.interfaces[interface] = true + end + else + newclass.interfaces = parent.interfaces + end + end + for k in pairs(total) do + total[k] = nil + end + table_setn(total, 0) + + newclass.super = parent + + newclass.prototype = setmetatable(total, { + __index = parent.prototype, + __tostring = protostring, + }) + total = nil + + newclass.instancemeta = { + __index = newclass.prototype, + __tostring = classobjectstring, + __eq = classobjectequal, + __lt = classobjectlessthan, + __le = classobjectlessthanequal, + __add = classobjectadd, + __sub = classobjectsub, + __unm = classobjectunm, + __mul = classobjectmul, + __div = classobjectdiv, + __pow = classobjectpow, + __concat = classobjectconcat, + } + + setmetatable(newclass, classmeta) + + newclass.new = class_new + + if newclass.mixins then + -- Fold in the mixins + local err, msg + for mixin in pairs(newclass.mixins) do + local ret + autoEmbed = true + ret, msg = pcall(mixin.embed, mixin, newclass.prototype) + autoEmbed = false + if not ret then + err = true + break + end + end + + if err then + local pt = newclass.prototype + for k,v in pairs(pt) do + pt[k] = nil + end + + -- method conflict + AceOO:error(msg) + end + end + + newclass.prototype.class = newclass + + if newclass.interfaces then + for interface in pairs(newclass.interfaces) do + traverseInterfaces(interface, newclass.interfaces) + end + end + if newclass.mixins then + for mixin in pairs(newclass.mixins) do + if mixin.interfaces then + if not newclass.interfaces then + newclass.interfaces = {} + end + for interface in pairs(mixin.interfaces) do + newclass.interfaces[interface] = true + end + end + end + end + end + function Class:ToString() + if type(self.GetLibraryVersion) == "function" then + return (self:GetLibraryVersion()) + else + return "Class" + end + end + + local tmp + function Class.prototype:init() + if rawequal(self, initStatus) then + initStatus = nil + else + AceOO:error("Improper self passed to init. You must do MyClass.super.prototype.init(self, ...)", 2) + end + self.uid = getuid(self) + local current = self.class + while true do + if current == Class then + break + end + if current.mixins then + for mixin in pairs(current.mixins) do + if type(mixin.OnInstanceInit) == "function" then + mixin:OnInstanceInit(self) + end + end + end + current = current.super + end + end +end + + +-- @object ClassFactory +-- @brief A factory for creating classes. Rarely used directly. +local ClassFactory = Factory(Object, Class, Object) + +function Class:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20) + local x = ClassFactory:new(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20) + if AceOO.classes then + AceOO.classes[x] = true + end + return x +end +getmetatable(Class).__call = Class.new + +-- @class Mixin +-- @brief A class to create mixin objects, which contain methods that get +-- "mixed in" to class prototypes. +-- +-- @object Mixin prototype +-- @brief The prototype that mixin objects inherit their methods from. +-- +-- @method Mixin prototype embed +-- @brief Mix in the methods of our object which are listed in our interface +-- to the supplied target table. +-- +-- @method Mixin prototype init +-- @brief Initialize the mixin object. +-- @param newobj The new object we're initializing. +-- @param interface The interface we implement (the list of methods our +-- prototype provides which should be mixed into the target +-- table by embed). +do + Mixin = Class() + function Mixin:ToString() + if self.GetLibraryVersion then + return (self:GetLibraryVersion()) + else + return 'Mixin' + end + end + local function _Embed(state, field, target) + field = next(state.export, field) + if field == nil then + return + end + + if rawget(target, field) or (target[field] and target[field] ~= state[field]) then + AceOO:error("Method conflict in attempt to mixin. Field %q", field) + end + + target[field] = state[field] + + local ret,msg = pcall(_Embed, state, field, target) + if not ret then + -- Mix in the next method according to the defined interface. If that + -- fails due to a conflict, re-raise to back out the previous mixed + -- methods. + + target[field] = nil + AceOO:error(msg) + end + end + function Mixin.prototype:embed(target) + local mt = getmetatable(target) + setmetatable(target, nil) + local err, msg = pcall(_Embed, self, nil, target) + if not err then + setmetatable(target, mt) + AceOO:error(msg) + return + end + if type(self.embedList) == "table" then + self.embedList[target] = true + end + if type(target.class) ~= "table" then + target[self] = true + end + if not autoEmbed and type(self.OnManualEmbed) == "function" then + self:OnManualEmbed(target) + end + setmetatable(target, mt) + end + + function Mixin.prototype:activate(oldLib, oldDeactivate) + if oldLib and oldLib.embedList then + for target in pairs(oldLib.embedList) do + local mt = getmetatable(target) + setmetatable(target, nil) + for field in pairs(oldLib.export) do + target[field] = nil + end + setmetatable(target, mt) + end + self.embedList = oldLib.embedList + for target in pairs(self.embedList) do + self:embed(target) + end + else + self.embedList = setmetatable({}, {__mode="k"}) + end + end + + function Mixin.prototype:init(export, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, + a17, a18, a19, a20) + AceOO:argCheck(export, 2, "table") + for k,v in pairs(export) do + if type(k) ~= "number" then + AceOO:error("All keys to argument #2 must be numbers.") + elseif type(v) ~= "string" then + AceOO:error("All values to argument #2 must be strings.") + end + end + local num = table.getn(export) + for i = 1, num do + local v = export[i] + export[i] = nil + export[v] = true + end + table_setn(export, 0) + local interfaces + if a1 then + local l = getlibrary + interfaces = { l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), l(a8), + l(a9), l(a10), l(a11), l(a12), l(a13), l(a14), l(a15), l(a16), + l(a17), l(a18), l(a19), l(a20) } + for _,v in ipairs(interfaces) do + if not v.class or not inherits(v, Interface) then + AceOO:error("Mixins can inherit only from interfaces") + end + end + local num = table.getn(interfaces) + for i = 1, num do + local v = interfaces[i] + interfaces[i] = nil + interfaces[v] = true + end + table_setn(interfaces, 0) + for interface in pairs(interfaces) do + traverseInterfaces(interface, interfaces) + end + for interface in pairs(interfaces) do + for field,kind in pairs(interface.interface) do + if kind ~= "nil" then + local good = false + for bit in pairs(export) do + if bit == field then + good = true + break + end + end + if not good then + AceOO:error("Mixin does not fully accommodate field %q", field) + end + end + end + end + end + self.super = Mixin.prototype + Mixin.super.prototype.init(self) + self.export = export + self.interfaces = interfaces + end +end + +-- @class Interface +-- @brief A class to create interfaces, which contain contracts that classes +-- which inherit from this must comply with. +-- +-- @object Interface prototype +-- @brief The prototype that interface objects must adhere to. +-- +-- @method Interface prototype init +-- @brief Initialize the mixin object. +-- @param interface The interface we contract (the hash of fields forced). +-- @param (a1..a20) Superinterfaces +do + Interface = Class() + function Interface:ToString() + if self.GetLibraryVersion then + return (self:GetLibraryVersion()) + else + return 'Instance' + end + end + function Interface.prototype:init(interface, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + Interface.super.prototype.init(self) + AceOO:argCheck(interface, 2, "table") + for k,v in pairs(interface) do + if type(k) ~= "string" then + AceOO:error("All keys to argument #2 must be numbers.") + elseif type(v) ~= "string" then + AceOO:error("All values to argument #2 must be strings.") + elseif v ~= "nil" and v ~= "string" and v ~= "number" and v ~= "table" and v ~= "function" then + AceOO:error('All values to argument #2 must either be "nil", "string", "number", "table", or "function".') + end + end + local l = getlibrary + a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = l(a1), l(a2), l(a3), l(a4), l(a5), l(a6), l(a7), l(a8), l(a9), l(a10), l(a11), l(a12), l(a13), l(a14), l(a15), l(a16), l(a17), l(a18), l(a19), l(a20) + if a1 then + self.superinterfaces = {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20} + for k,v in ipairs(self.superinterfaces) do + if not inherits(v, Interface) or not v.class then + AceOO:error('Cannot provide a non-Interface to inherit from') + end + end + local num = table.getn(self.superinterfaces) + for i = 1, num do + local v = self.superinterfaces[i] + self.superinterfaces[i] = nil + self.superinterfaces[v] = true + end + table_setn(self.superinterfaces, 0) + end + self.interface = interface + end +end + +-- @function Classpool +-- @brief Obtain a read only class from our pool of classes, indexed by the +-- superclass and mixins. +-- @param sc The superclass of the class we want. +-- @param (m1..m20) Mixins of the class we want's objects. +-- @return A read only class from the class pool. +local Classpool +do + local pool = setmetatable({}, {__mode = 'v'}) + local function newindex(k, v) + AceOO:error('Attempt to modify a read-only class.') + end + local function protonewindex(k, v) + AceOO:error('Attempt to modify a read-only class prototype.') + end + local function ts(bit) + if type(bit) ~= "table" then + return tostring(bit) + elseif getmetatable(bit) and bit.__tostring then + return tostring(bit) + elseif type(bit.GetLibraryVersion) == "function" then + return bit:GetLibraryVersion() + else + return tostring(bit) + end + end + local t + local function getcomplexuid(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, + m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) + if not t then t = {} end + if sc then if sc.uid then table.insert(t, sc.uid) else AceOO:error("%s is not an appropriate class/mixin", ts(sc)) end + if m1 then if m1.uid then table.insert(t, m1.uid) else AceOO:error("%s is not an appropriate mixin", ts(m1)) end + if m2 then if m2.uid then table.insert(t, m2.uid) else AceOO:error("%s is not an appropriate mixin", ts(m2)) end + if m3 then if m3.uid then table.insert(t, m3.uid) else AceOO:error("%s is not an appropriate mixin", ts(m3)) end + if m4 then if m4.uid then table.insert(t, m4.uid) else AceOO:error("%s is not an appropriate mixin", ts(m4)) end + if m5 then if m5.uid then table.insert(t, m5.uid) else AceOO:error("%s is not an appropriate mixin", ts(m5)) end + if m6 then if m6.uid then table.insert(t, m6.uid) else AceOO:error("%s is not an appropriate mixin", ts(m6)) end + if m7 then if m7.uid then table.insert(t, m7.uid) else AceOO:error("%s is not an appropriate mixin", ts(m7)) end + if m8 then if m8.uid then table.insert(t, m8.uid) else AceOO:error("%s is not an appropriate mixin", ts(m8)) end + if m9 then if m9.uid then table.insert(t, m9.uid) else AceOO:error("%s is not an appropriate mixin", ts(m9)) end + if m10 then if m10.uid then table.insert(t, m10.uid) else AceOO:error("%s is not an appropriate mixin", ts(m10)) end + if m11 then if m11.uid then table.insert(t, m11.uid) else AceOO:error("%s is not an appropriate mixin", ts(m11)) end + if m12 then if m12.uid then table.insert(t, m12.uid) else AceOO:error("%s is not an appropriate mixin", ts(m12)) end + if m13 then if m13.uid then table.insert(t, m13.uid) else AceOO:error("%s is not an appropriate mixin", ts(m13)) end + if m14 then if m14.uid then table.insert(t, m14.uid) else AceOO:error("%s is not an appropriate mixin", ts(m14)) end + if m15 then if m15.uid then table.insert(t, m15.uid) else AceOO:error("%s is not an appropriate mixin", ts(m15)) end + if m16 then if m16.uid then table.insert(t, m16.uid) else AceOO:error("%s is not an appropriate mixin", ts(m16)) end + if m17 then if m17.uid then table.insert(t, m17.uid) else AceOO:error("%s is not an appropriate mixin", ts(m17)) end + if m18 then if m18.uid then table.insert(t, m18.uid) else AceOO:error("%s is not an appropriate mixin", ts(m18)) end + if m19 then if m19.uid then table.insert(t, m19.uid) else AceOO:error("%s is not an appropriate mixin", ts(m19)) end + if m20 then if m20.uid then table.insert(t, m20.uid) else AceOO:error("%s is not an appropriate mixin", ts(m20)) end + end end end end end end end end end end end end end end end end end end end end end + table.sort(t) + local uid = table.concat(t, '') + for k in pairs(t) do t[k] = nil end + table_setn(t, 0) + return uid + end + local classmeta + function Classpool(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, + m10, m11, m12, m13, m14, m15, m16, + m17, m18, m19, m20) + local l = getlibrary + sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20 = l(sc), l(m1), l(m2), l(m3), l(m4), l(m5), l(m6), l(m7), l(m8), l(m9), l(m10), l(m11), l(m12), l(m13), l(m14), l(m15), l(m16), l(m17), l(m18), l(m19), l(m20) + if sc and sc.class then + sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20 = Class, sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19 + end + sc = sc or Class + local key = getcomplexuid(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20) + if not pool[key] then + local class = Class(sc, m1, m2, m3, m4, m5, m6, m7, m8, m9, + m10, m11, m12, m13, m14, m15, m16, m17, + m18, m19, m20) + if not classmeta then + classmeta = {} + local mt = getmetatable(class) + for k,v in pairs(mt) do + classmeta[k] = v + end + classmeta.__newindex = newindex + end + -- Prevent the user from adding methods to this class. + -- NOTE: I'm not preventing modifications of existing class members, + -- but it's likely that only a truly malicious user will be doing so. + class.sealed = true + setmetatable(class, classmeta) + getmetatable(class.prototype).__newindex = protonewindex + pool[key] = class + end + return pool[key] + end +end + +AceOO.Factory = Factory +AceOO.Object = Object +AceOO.Class = Class +AceOO.Mixin = Mixin +AceOO.Interface = Interface +AceOO.Classpool = Classpool +AceOO.inherits = inherits + +-- Library handling bits + +local function activate(self, oldLib, oldDeactivate) + AceOO = self + Factory = self.Factory + Object = self.Object + Class = self.Class + ClassFactory.prototype = Class + Mixin = self.Mixin + Interface = self.Interface + Classpool = self.Classpool + + if oldLib then + self.classes = oldLib.classes + end + if not self.classes then + self.classes = setmetatable({}, {__mode="k"}) + else + for class in pairs(self.classes) do + class.new = class_new + end + end + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceOO, MAJOR_VERSION, MINOR_VERSION, activate) +AceOO = AceLibrary(MAJOR_VERSION) diff --git a/Libs/Babble-Spell-2.2/Babble-Spell-2.2.lua b/Libs/Babble-Spell-2.2/Babble-Spell-2.2.lua new file mode 100644 index 0000000..c6576ad --- /dev/null +++ b/Libs/Babble-Spell-2.2/Babble-Spell-2.2.lua @@ -0,0 +1,7839 @@ +--[[ +Name: Babble-Spell-2.2 +Revision: $Rev: 17235 $ +Author(s): ckknight (ckknight@gmail.com) +Website: http://ckknight.wowinterface.com/ +Documentation: http://wiki.wowace.com/index.php/Babble-Spell-2.2 +SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Spell-2.2 +Description: A library to provide localizations for spells. +Dependencies: AceLibrary, AceLocale-2.2 +]] + +local MAJOR_VERSION = "Babble-Spell-2.2" +local MINOR_VERSION = tonumber(string.sub("$Revision: 17235 $", 12, -3)) + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end +if not AceLibrary:HasInstance("AceLocale-2.2") then error(MAJOR_VERSION .. " requires AceLocale-2.2") end + +local _, x = AceLibrary("AceLocale-2.2"):GetLibraryVersion() +MINOR_VERSION = MINOR_VERSION * 100000 + x + +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +local BabbleSpell = AceLibrary("AceLocale-2.2"):new(MAJOR_VERSION) + +-- uncomment below for debug information +-- BabbleSpell:EnableDebugging() + +BabbleSpell:RegisterTranslations("enUS", function() + return { + ["Abolish Disease"] = true, + ["Abolish Poison Effect"] = true, + ["Abolish Poison"] = true, + ["Activate MG Turret"] = true, + ["Adrenaline Rush"] = true, + ["Aftermath"] = true, + ["Aggression"] = true, + ["Aimed Shot"] = true, + ["Alchemy"] = true, + ["Ambush"] = true, + ["Amplify Curse"] = true, + ["Amplify Magic"] = true, + ["Ancestral Fortitude"] = true, + ["Ancestral Healing"] = true, + ["Ancestral Knowledge"] = true, + ["Ancestral Spirit"] = true, + ["Anesthetic Poison"] = true, + ["Anger Management"] = true, + ["Anguish"] = true, + ["Anticipation"] = true, + ["Aquatic Form"] = true, + ["Arcane Blast"] = true, + ["Arcane Brilliance"] = true, + ["Arcane Concentration"] = true, + ["Arcane Explosion"] = true, + ["Arcane Focus"] = true, + ["Arcane Instability"] = true, + ["Arcane Intellect"] = true, + ["Arcane Meditation"] = true, + ["Arcane Mind"] = true, + ["Arcane Missiles"] = true, + ["Arcane Power"] = true, + ["Arcane Resistance"] = true, + ["Arcane Shot"] = true, + ["Arcane Subtlety"] = true, + ["Arctic Reach"] = true, + ["Armorsmith"] = true, + ["Aspect of the Beast"] = true, + ["Aspect of the Cheetah"] = true, + ["Aspect of the Hawk"] = true, + ["Aspect of the Monkey"] = true, + ["Aspect of the Pack"] = true, + ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = true, + ["Astral Recall"] = true, + ["Attack"] = true, + ["Attacking"] = true, + ["Auto Shot"] = true, + ["Avenger's Shield"] = true, + ["Avenging Wrath"] = true, + ["Avoidance"] = true, + ["Axe Specialization"] = true, + ["Backlash"] = true, + ["Backstab"] = true, + ["Bane"] = true, + ["Banish"] = true, + ["Barkskin Effect"] = true, + ["Barkskin"] = true, + ["Barrage"] = true, + ["Bash"] = true, + ["Basic Campfire"] = true, + ["Battle Shout"] = true, + ["Battle Stance Passive"] = true, + ["Battle Stance"] = true, + ["Bear Form"] = true, + ["Beast Lore"] = true, + ["Beast Slaying"] = true, + ["Beast Training"] = true, + ["Benediction"] = true, + ["Berserker Rage"] = true, + ["Berserker Stance Passive"] = true, + ["Berserker Stance"] = true, + ["Berserking"] = true, + ["Bestial Discipline"] = true, + ["Bestial Swiftness"] = true, + ["Bestial Wrath"] = true, + ["Binding Heal"] = true, + ["Bite"] = true, + ["Black Arrow"] = true, + ["Blackout"] = true, + ["Blacksmithing"] = true, + ["Blade Flurry"] = true, + ["Blast Wave"] = true, + ["Blazing Speed"] = true, + ["Blessed Recovery"] = true, + ["Blessing of Freedom"] = true, + ["Blessing of Kings"] = true, + ["Blessing of Light"] = true, + ["Blessing of Might"] = true, + ["Blessing of Protection"] = true, + ["Blessing of Sacrifice"] = true, + ["Blessing of Salvation"] = true, + ["Blessing of Sanctuary"] = true, + ["Blessing of Wisdom"] = true, + ["Blind"] = true, + ["Blinding Powder"] = true, + ["Blink"] = true, + ["Blizzard"] = true, + ["Block"] = true, + ["Blood Craze"] = true, + ["Blood Frenzy"] = true, + ["Blood Fury"] = true, + ["Blood Pact"] = true, + ["Bloodlust"] = true, + ["Bloodrage"] = true, + ["Bloodthirst"] = true, + ["Booming Voice"] = true, + ["Bow Specialization"] = true, + ["Bows"] = true, + ["Bright Campfire"] = true, + ["Brutal Impact"] = true, + ["Burning Soul"] = true, + ["Call Pet"] = true, + ["Call of Flame"] = true, + ["Call of Thunder"] = true, + ["Camouflage"] = true, + ["Cannibalize"] = true, + ["Cat Form"] = true, + ["Cataclysm"] = true, + ["Chain Heal"] = true, + ["Chain Lightning"] = true, + ["Challenging Roar"] = true, + ["Challenging Shout"] = true, + ["Charge Rage Bonus Effect"] = true, + ["Charge"] = true, + ["Charge Stun"] = true, + ["Cheap Shot"] = true, + ["Chilled"] = true, + ["Circle of Healing"] = true, + ["Claw"] = true, + ["Cleanse"] = true, + ["Clearcasting"] = true, + ["Cleave"] = true, + ["Clever Traps"] = true, + ["Cloak of Shadows"] = true, + ["Closing"] = true, + ["Cloth"] = true, + ["Coarse Sharpening Stone"] = true, + ["Cobra Reflexes"] = true, + ["Cold Blood"] = true, + ["Cold Snap"] = true, + ["Combat Endurance"] = true, + ["Combustion"] = true, + ["Command"] = true, + ["Commanding Shout"] = true, + ["Concentration Aura"] = true, + ["Concussion Blow"] = true, + ["Concussion"] = true, + ["Concussive Shot"] = true, + ["Cone of Cold"] = true, + ["Conflagrate"] = true, + ["Conjure Food"] = true, + ["Conjure Mana Agate"] = true, + ["Conjure Mana Citrine"] = true, + ["Conjure Mana Jade"] = true, + ["Conjure Mana Ruby"] = true, + ["Conjure Water"] = true, + ["Consecrated Sharpening Stone"] = true, + ["Consecration"] = true, +-- ["Consume Magic"] = true, + ["Consume Shadows"] = true, + ["Convection"] = true, + ["Conviction"] = true, + ["Cooking"] = true, + ["Corruption"] = true, + ["Counterattack"] = true, + ["Counterspell"] = true, + ["Counterspell - Silenced"] = true, + ["Cower"] = true, + ["Create Firestone"] = true, + ["Create Firestone (Major)"] = true, + ["Create Firestone (Greater)"] = true, + ["Create Firestone (Lesser)"] = true, + ["Create Healthstone"] = true, + ["Create Healthstone (Major)"] = true, + ["Create Healthstone (Greater)"] = true, + ["Create Healthstone (Lesser)"] = true, + ["Create Healthstone (Minor)"] = true, + ["Create Soulstone"] = true, + ["Create Soulstone (Major)"] = true, + ["Create Soulstone (Greater)"] = true, + ["Create Soulstone (Lesser)"] = true, + ["Create Soulstone (Minor)"] = true, + ["Create Spellstone"] = true, + ["Create Spellstone (Major)"] = true, + ["Create Spellstone (Greater)"] = true, + ["Crippling Poison II"] = true, + ["Crippling Poison"] = true, + ["Critical Mass"] = true, + ["Crossbows"] = true, + ["Cruelty"] = true, + ["Crusader Aura"] = true, + ["Crusader Strike"] = true, + ["Cultivation"] = true, + ["Cure Disease"] = true, + ["Cure Poison"] = true, + ["Curse of Agony"] = true, + ["Curse of Doom Effect"] = true, + ["Curse of Doom"] = true, + ["Curse of Exhaustion"] = true, + ["Curse of Idiocy"] = true, + ["Curse of Recklessness"] = true, + ["Curse of Shadow"] = true, + ["Curse of Tongues"] = true, + ["Curse of Weakness"] = true, + ["Curse of the Elements"] = true, + ["Cyclone"] = true, + ["Dagger Specialization"] = true, + ["Daggers"] = true, + ["Dampen Magic"] = true, + ["Dark Pact"] = true, + ["Darkness"] = true, + ["Dash"] = true, + ["Deadly Poison II"] = true, + ["Deadly Poison III"] = true, + ["Deadly Poison IV"] = true, + ["Deadly Poison V"] = true, + ["Deadly Poison"] = true, + ["Deadly Throw"] = true, + ["Death Coil"] = true, + ["Death Wish"] = true, + ["Deep Wounds"] = true, + ["Defense"] = true, + ["Defensive Stance Passive"] = true, + ["Defensive Stance"] = true, + ["Defensive State 2"] = true, + ["Defensive State"] = true, + ["Defiance"] = true, + ["Deflection"] = true, + ["Demon Armor"] = true, + ["Demon Skin"] = true, + ["Demonic Embrace"] = true, + ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = true, + ["Demoralizing Roar"] = true, + ["Demoralizing Shout"] = true, + ["Dense Sharpening Stone"] = true, + ["Desperate Prayer"] = true, + ["Destructive Reach"] = true, + ["Detect Greater Invisibility"] = true, + ["Detect Invisibility"] = true, + ["Detect Lesser Invisibility"] = true, + ["Detect Magic"] = true, + ["Detect Traps"] = true, + ["Detect"] = true, + ["Deterrence"] = true, + ["Devastate"] = true, + ["Devastation"] = true, + ["Devotion Aura"] = true, + ["Devour Magic Effect"] = true, + ["Devour Magic"] = true, + ["Devouring Plague"] = true, + ["Diplomacy"] = true, + ["Dire Bear Form"] = true, + ["Disarm Trap"] = true, + ["Disarm"] = true, + ["Disease Cleansing Totem"] = true, + ["Disenchant"] = true, + ["Disengage"] = true, + ["Dismiss Pet"] = true, + ["Dispel Magic"] = true, + ["Distract"] = true, + ["Distracting Shot"] = true, + ["Dive"] = true, + ["Divine Favor"] = true, + ["Divine Fury"] = true, + ["Divine Illumination"] = true, + ["Divine Intellect"] = true, + ["Divine Intervention"] = true, + ["Divine Protection"] = true, + ["Divine Shield"] = true, + ["Divine Spirit"] = true, + ["Divine Strength"] = true, + ["Dodge"] = true, + ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"] = true, + ["Drain Life"] = true, + ["Drain Mana"] = true, + ["Drain Soul"] = true, + ["Drink"] = true, + ["Dual Wield Specialization"] = true, + ["Dual Wield"] = true, + ["Duel"] = true, + ["Eagle Eye"] = true, + ["Earth Elemental Totem"] = true, + ["Earth Shield"] = true, + ["Earth Shock"] = true, + ["Earthbind Totem"] = true, + ["Efficiency"] = true, + ["Elemental Focus"] = true, + ["Elemental Fury"] = true, + ["Elemental Leatherworking"] = true, + ["Elemental Mastery"] = true, + ["Elemental Sharpening Stone"] = true, + ["Elune's Grace"] = true, + ["Elusiveness"] = true, + ["Emberstorm"] = true, + ["Enamored Water Spirit"] = true, + ["Enchanting"] = true, + ["Endurance Training"] = true, + ["Endurance"] = true, + ["Engineering Specialization"] = true, + ["Engineering"] = true, + ["Enrage"] = true, + ["Enriched Manna Biscuit"] = true, + ["Enslave Demon"] = true, + ["Entangling Roots"] = true, + ["Entrapment"] = true, + ["Envenom"] = true, + ["Escape Artist"] = true, + ["Evasion"] = true, + ["Eventide"] = true, + ["Eviscerate"] = true, + ["Evocation"] = true, + ["Execute"] = true, + ["Exorcism"] = true, + ["Expansive Mind"] = true, + ["Explosive Trap Effect"] = true, + ["Explosive Trap"] = true, + ["Expose Armor"] = true, + ["Eye for an Eye"] = true, + ["Eye of Kilrogg"] = true, + ["Eyes of the Beast"] = true, + ["Fade"] = true, + ["Faerie Fire"] = true, + ["Faerie Fire (Feral)"] = true, + ["Far Sight"] = true, + ["Fear Ward"] = true, + ["Fear"] = true, + ["Feed Pet"] = true, + ["Feedback"] = true, + ["Feign Death"] = true, + ["Feint"] = true, + ["Fel Armor"] = true, + ["Fel Concentration"] = true, + ["Fel Domination"] = true, + ["Fel Intellect"] = true, + ["Fel Stamina"] = true, + ["Felfire"] = true, + ["Feline Grace"] = true, + ["Feline Swiftness"] = true, + ["Feral Aggression"] = true, + ["Feral Charge"] = true, + ["Feral Instinct"] = true, + ["Ferocious Bite"] = true, + ["Ferocity"] = true, + ["Fetish"] = true, + ["Find Herbs"] = true, + ["Find Minerals"] = true, + ["Find Treasure"] = true, + ["Fire Blast"] = true, + ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = true, + ["Fire Power"] = true, + ["Fire Resistance Aura"] = true, + ["Fire Resistance Totem"] = true, + ["Fire Resistance"] = true, + ["Fire Shield"] = true, + ["Fire Vulnerability"] = true, + ["Fire Ward"] = true, + ["Fireball"] = true, + ["Firebolt"] = true, + ["First Aid"] = true, + ["Fishing Poles"] = true, + ["Fishing"] = true, + ["Fist Weapon Specialization"] = true, + ["Fist Weapons"] = true, + ["Flame Shock"] = true, + ["Flame Throwing"] = true, + ["Flamestrike"] = true, + ["Flamethrower"] = true, + ["Flametongue Totem"] = true, + ["Flametongue Weapon"] = true, + ["Flare"] = true, + ["Flash Heal"] = true, + ["Flash of Light"] = true, + ["Flight Form"] = true, + ["Flurry"] = true, + ["Focused Casting"] = true, + ["Food"] = true, + ["Forbearance"] = true, + ["Force of Nature"] = true, + ["Force of Will"] = true, + ["Freezing Trap Effect"] = true, + ["Freezing Trap"] = true, + ["Frenzied Regeneration"] = true, + ["Frenzy"] = true, + ["Frost Armor"] = true, + ["Frost Channeling"] = true, + ["Frost Nova"] = true, + ["Frost Resistance Aura"] = true, + ["Frost Resistance Totem"] = true, + ["Frost Resistance"] = true, + ["Frost Shock"] = true, + ["Frost Trap"] = true, + ["Frost Trap Aura"] = true, + ["Frost Ward"] = true, + ["Frostbite"] = true, + ["Frostbolt"] = true, + ["Frostbrand Weapon"] = true, + ["Furious Howl"] = true, + ["Furor"] = true, + ["Garrote"] = true, + ["Generic"] = true, + ["Ghost Wolf"] = true, + ["Ghostly Strike"] = true, + ["Gift of Life"] = true, + ["Gift of Nature"] = true, + ["Gift of the Wild"] = true, + ["Gouge"] = true, + ["Grace of Air Totem"] = true, + ["Great Stamina"] = true, + ["Greater Blessing of Kings"] = true, + ["Greater Blessing of Light"] = true, + ["Greater Blessing of Might"] = true, + ["Greater Blessing of Salvation"] = true, + ["Greater Blessing of Sanctuary"] = true, + ["Greater Blessing of Wisdom"] = true, + ["Greater Heal"] = true, + ["Grim Reach"] = true, + ["Grounding Totem"] = true, + ["Grovel"] = true, + ["Growl"] = true, + ["Guardian's Favor"] = true, + ["Gun Specialization"] = true, + ["Guns"] = true, + ["Hammer of Justice"] = true, + ["Hammer of Wrath"] = true, + ["Hamstring"] = true, + ["Harass"] = true, + ["Hardiness"] = true, + ["Hawk Eye"] = true, + ["Heal"] = true, + ["Healing Focus"] = true, + ["Healing Light"] = true, + ["Healing Stream Totem"] = true, + ["Healing Touch"] = true, + ["Healing Wave"] = true, + ["Healing Way"] = true, + ["Health Funnel"] = true, + ["Heart of the Wild"] = true, + ["Heavy Sharpening Stone"] = true, + ["Hellfire Effect"] = true, + ["Hellfire"] = true, + ["Hemorrhage"] = true, + ["Herb Gathering"] = true, + ["Herbalism"] = true, + ["Heroic Strike"] = true, + ["Heroism"] = true, + ["Hex of Weakness"] = true, + ["Hibernate"] = true, + ["Holy Fire"] = true, + ["Holy Light"] = true, + ["Holy Nova"] = true, + ["Holy Power"] = true, + ["Holy Reach"] = true, + ["Holy Shield"] = true, + ["Holy Shock"] = true, + ["Holy Specialization"] = true, + ["Holy Wrath"] = true, + ["Honorless Target"] = true, + ["Horse Riding"] = true, + ["Howl of Terror"] = true, + ["Humanoid Slaying"] = true, + ["Hunter's Mark"] = true, + ["Hurricane"] = true, + ["Ice Armor"] = true, + ["Ice Barrier"] = true, + ["Ice Block"] = true, + ["Ice Lance"] = true, + ["Ice Shards"] = true, + ["Ignite"] = true, + ["Illumination"] = true, + ["Immolate"] = true, + ["Immolation Trap Effect"] = true, + ["Immolation Trap"] = true, + ["Impact"] = true, + ["Impale"] = true, + ["Improved Ambush"] = true, + ["Improved Arcane Explosion"] = true, + ["Improved Arcane Missiles"] = true, + ["Improved Arcane Shot"] = true, + ["Improved Aspect of the Hawk"] = true, + ["Improved Aspect of the Monkey"] = true, + ["Improved Backstab"] = true, + ["Improved Battle Shout"] = true, + ["Improved Berserker Rage"] = true, + ["Improved Blessing of Might"] = true, + ["Improved Blessing of Wisdom"] = true, + ["Improved Blizzard"] = true, + ["Improved Bloodrage"] = true, + ["Improved Chain Heal"] = true, + ["Improved Chain Lightning"] = true, + ["Improved Challenging Shout"] = true, + ["Improved Charge"] = true, + ["Improved Cheap Shot"] = true, + ["Improved Cleave"] = true, + ["Improved Concentration Aura"] = true, + ["Improved Concussive Shot"] = true, + ["Improved Cone of Cold"] = true, + ["Improved Corruption"] = true, + ["Improved Counterspell"] = true, + ["Improved Curse of Agony"] = true, + ["Improved Curse of Exhaustion"] = true, + ["Improved Curse of Weakness"] = true, + ["Improved Dampen Magic"] = true, + ["Improved Deadly Poison"] = true, + ["Improved Demoralizing Shout"] = true, + ["Improved Devotion Aura"] = true, + ["Improved Disarm"] = true, + ["Improved Distract"] = true, + ["Improved Drain Life"] = true, + ["Improved Drain Mana"] = true, + ["Improved Drain Soul"] = true, + ["Improved Enrage"] = true, + ["Improved Enslave Demon"] = true, + ["Improved Entangling Roots"] = true, + ["Improved Evasion"] = true, + ["Improved Eviscerate"] = true, + ["Improved Execute"] = true, + ["Improved Expose Armor"] = true, + ["Improved Eyes of the Beast"] = true, + ["Improved Fade"] = true, + ["Improved Feign Death"] = true, + ["Improved Fire Blast"] = true, + ["Improved Fire Nova Totem"] = true, + ["Improved Fire Ward"] = true, + ["Improved Fireball"] = true, + ["Improved Firebolt"] = true, + ["Improved Firestone"] = true, + ["Improved Flamestrike"] = true, + ["Improved Flametongue Weapon"] = true, + ["Improved Flash of Light"] = true, + ["Improved Frost Nova"] = true, + ["Improved Frost Ward"] = true, + ["Improved Frostbolt"] = true, + ["Improved Frostbrand Weapon"] = true, + ["Improved Garrote"] = true, + ["Improved Ghost Wolf"] = true, + ["Improved Gouge"] = true, + ["Improved Grace of Air Totem"] = true, + ["Improved Grounding Totem"] = true, + ["Improved Hammer of Justice"] = true, + ["Improved Hamstring"] = true, + ["Improved Healing Stream Totem"] = true, + ["Improved Healing Touch"] = true, + ["Improved Healing Wave"] = true, + ["Improved Healing"] = true, + ["Improved Health Funnel"] = true, + ["Improved Healthstone"] = true, + ["Improved Heroic Strike"] = true, + ["Improved Hunter's Mark"] = true, + ["Improved Immolate"] = true, + ["Improved Imp"] = true, + ["Improved Inner Fire"] = true, + ["Improved Instant Poison"] = true, + ["Improved Intercept"] = true, + ["Improved Intimidating Shout"] = true, + ["Improved Judgement"] = true, + ["Improved Kick"] = true, + ["Improved Kidney Shot"] = true, + ["Improved Lash of Pain"] = true, + ["Improved Lay on Hands"] = true, + ["Improved Lesser Healing Wave"] = true, + ["Improved Life Tap"] = true, + ["Improved Lightning Bolt"] = true, + ["Improved Lightning Shield"] = true, + ["Improved Magma Totem"] = true, + ["Improved Mana Burn"] = true, + ["Improved Mana Shield"] = true, + ["Improved Mana Spring Totem"] = true, + ["Improved Mark of the Wild"] = true, + ["Improved Mend Pet"] = true, + ["Improved Mind Blast"] = true, + ["Improved Moonfire"] = true, + ["Improved Nature's Grasp"] = true, + ["Improved Overpower"] = true, + ["Improved Power Word: Fortitude"] = true, + ["Improved Power Word: Shield"] = true, + ["Improved Prayer of Healing"] = true, + ["Improved Psychic Scream"] = true, + ["Improved Pummel"] = true, + ["Improved Regrowth"] = true, + ["Improved Reincarnation"] = true, + ["Improved Rejuvenation"] = true, + ["Improved Rend"] = true, + ["Improved Renew"] = true, + ["Improved Retribution Aura"] = true, + ["Improved Revenge"] = true, + ["Improved Revive Pet"] = true, + ["Improved Righteous Fury"] = true, + ["Improved Rockbiter Weapon"] = true, + ["Improved Rupture"] = true, + ["Improved Sap"] = true, + ["Improved Scorch"] = true, + ["Improved Scorpid Sting"] = true, + ["Improved Seal of Righteousness"] = true, + ["Improved Seal of the Crusader"] = true, + ["Improved Searing Pain"] = true, + ["Improved Searing Totem"] = true, + ["Improved Serpent Sting"] = true, + ["Improved Shadow Bolt"] = true, + ["Improved Shadow Word: Pain"] = true, + ["Improved Shield Bash"] = true, + ["Improved Shield Block"] = true, + ["Improved Shield Wall"] = true, + ["Improved Shred"] = true, + ["Improved Sinister Strike"] = true, + ["Improved Slam"] = true, + ["Improved Slice and Dice"] = true, + ["Improved Spellstone"] = true, + ["Improved Sprint"] = true, + ["Improved Starfire"] = true, + ["Improved Stoneclaw Totem"] = true, + ["Improved Stoneskin Totem"] = true, + ["Improved Strength of Earth Totem"] = true, + ["Improved Succubus"] = true, + ["Improved Sunder Armor"] = true, + ["Improved Taunt"] = true, + ["Improved Thorns"] = true, + ["Improved Thunder Clap"] = true, + ["Improved Tranquility"] = true, + ["Improved Vampiric Embrace"] = true, + ["Improved Vanish"] = true, + ["Improved Voidwalker"] = true, + ["Improved Windfury Weapon"] = true, + ["Improved Wing Clip"] = true, + ["Improved Wrath"] = true, + ["Incinerate"] = true, + ["Inferno"] = true, + ["Initiative"] = true, + ["Inner Fire"] = true, + ["Inner Focus"] = true, + ["Innervate"] = true, + ["Insect Swarm"] = true, + ["Inspiration"] = true, + ["Instant Poison II"] = true, + ["Instant Poison III"] = true, + ["Instant Poison IV"] = true, + ["Instant Poison V"] = true, + ["Instant Poison VI"] = true, + ["Instant Poison"] = true, + ["Intensity"] = true, + ["Intercept"] = true, + ["Intercept Stun"] = true, + ["Intervene"] = true, + ["Intimidating Shout"] = true, + ["Intimidation"] = true, + ["Invisibility"] = true, + ["Iron Will"] = true, + ["Jewelcrafting"] = true, + ["Judgement of Command"] = true, + ["Judgement of Justice"] = true, + ["Judgement of Light"] = true, + ["Judgement of Righteousness"] = true, + ["Judgement of Wisdom"] = true, + ["Judgement of the Crusader"] = true, + ["Judgement"] = true, + ["Kick"] = true, + ["Kick - Silenced"] = true, + ["Kidney Shot"] = true, + ["Kill Command"] = true, + ["Killer Instinct"] = true, + ["Kodo Riding"] = true, + ["Lacerate"] = true, + ["Lash of Pain"] = true, + ["Last Stand"] = true, + ["Lasting Judgement"] = true, + ["Lay on Hands"] = true, + ["Leader of the Pack"] = true, + ["Leather"] = true, + ["Leatherworking"] = true, + ["Lesser Heal"] = true, + ["Lesser Healing Wave"] = true, + ["Lesser Invisibility"] = true, + ["Lethal Shots"] = true, + ["Lethality"] = true, + ["Levitate"] = true, + ["Libram"] = true, + ["Lifebloom"] = true, + ["Life Tap"] = true, + ["Lifegiving Gem"] = true, + ["Lightning Bolt"] = true, + ["Lightning Breath"] = true, + ["Lightning Mastery"] = true, + ["Lightning Reflexes"] = true, + ["Lightning Shield"] = true, + ["Lightwell Renew"] = true, + ["Lightwell"] = true, + ["Lockpicking"] = true, + ["Long Daze"] = true, + ["Mace Specialization"] = true, + ["Mace Stun Effect"] = true, + ["Mage Armor"] = true, + ["Magma Totem"] = true, + ["Mail"] = true, + ["Maim"] = true, + ["Malice"] = true, + ["Mana Burn"] = true, + ["Mana Shield"] = true, + ["Mana Spring Totem"] = true, + ["Mana Tide Totem"] = true, + ["Mangle"] = true, + ["Mangle (Cat)"] = true, + ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = true, + ["Martyrdom"] = true, + ["Mass Dispel"] = true, + ["Master Demonologist"] = true, + ["Master Summoner"] = true, + ["Master of Deception"] = true, + ["Maul"] = true, + ["Mechanostrider Piloting"] = true, + ["Meditation"] = true, + ["Melee Specialization"] = true, + ["Mend Pet"] = true, + ["Mental Agility"] = true, + ["Mental Strength"] = true, + ["Mind Blast"] = true, + ["Mind Control"] = true, + ["Mind Flay"] = true, + ["Mind Soothe"] = true, + ["Mind Vision"] = true, + ["Mind-numbing Poison II"] = true, + ["Mind-numbing Poison III"] = true, + ["Mind-numbing Poison"] = true, + ["Mining"] = true, + ["Misdirection"] = true, + ["Mocking Blow"] = true, + ["Molten Armor"] = true, + ["Mongoose Bite"] = true, + ["Monster Slaying"] = true, + ["Moonfire"] = true, + ["Moonfury"] = true, + ["Moonglow"] = true, + ["Moonkin Aura"] = true, + ["Moonkin Form"] = true, + ["Mortal Shots"] = true, + ["Mortal Strike"] = true, + ["Multi-Shot"] = true, + ["Murder"] = true, + ["Mutilate"] = true, + ["Natural Armor"] = true, + ["Natural Shapeshifter"] = true, + ["Natural Weapons"] = true, + ["Nature Resistance Totem"] = true, + ["Nature Resistance"] = true, + ["Nature's Focus"] = true, + ["Nature's Grace"] = true, + ["Nature's Grasp"] = true, + ["Nature's Reach"] = true, + ["Nature's Swiftness"] = true, + ["Nightfall"] = true, + ["Omen of Clarity"] = true, + ["One-Handed Axes"] = true, + ["One-Handed Maces"] = true, + ["One-Handed Swords"] = true, + ["One-Handed Weapon Specialization"] = true, + ["Opening - No Text"] = true, + ["Opening"] = true, + ["Opportunity"] = true, + ["Overpower"] = true, + ["Pain Suppression"] = true, + ["Paranoia"] = true, + ["Parry"] = true, + ["Pathfinding"] = true, + ["Perception"] = true, + ["Permafrost"] = true, + ["Pet Aggression"] = true, + ["Pet Hardiness"] = true, + ["Pet Recovery"] = true, + ["Pet Resistance"] = true, + ["Phase Shift"] = true, + ["Pick Lock"] = true, + ["Pick Pocket"] = true, + ["Piercing Howl"] = true, + ["Piercing Ice"] = true, + ["Plate Mail"] = true, + ["Poison Cleansing Totem"] = true, + ["Poisons"] = true, + ["Polearm Specialization"] = true, + ["Polearms"] = true, + ["Polymorph"] = true, + ["Polymorph: Pig"] = true, + ["Polymorph: Turtle"] = true, + ["Portal: Darnassus"] = true, + ["Portal: Ironforge"] = true, + ["Portal: Orgrimmar"] = true, + ["Portal: Stormwind"] = true, + ["Portal: Thunder Bluff"] = true, + ["Portal: Undercity"] = true, + ["Pounce Bleed"] = true, + ["Pounce"] = true, + ["Power Infusion"] = true, + ["Power Word: Fortitude"] = true, + ["Power Word: Shield"] = true, + ["Prayer of Fortitude"] = true, + ["Prayer of Healing"] = true, + ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"] = true, + ["Prayer of Spirit"] = true, + ["Precision"] = true, + ["Predatory Strikes"] = true, + ["Premeditation"] = true, + ["Preparation"] = true, + ["Presence of Mind"] = true, + ["Primal Fury"] = true, + ["Prowl"] = true, + ["Psychic Scream"] = true, + ["Pummel"] = true, + ["Purge"] = true, + ["Purification"] = true, + ["Purify"] = true, + ["Pursuit of Justice"] = true, + ["Pyroblast"] = true, + ["Pyroclasm"] = true, + ["Quick Shots"] = true, + ["Quickness"] = true, + ["Rain of Fire"] = true, + ["Rake"] = true, + ["Rampage"] = true, + ["Ram Riding"] = true, + ["Ranged Weapon Specialization"] = true, + ["Rapid Concealment"] = true, + ["Rapid Fire"] = true, + ["Raptor Riding"] = true, + ["Raptor Strike"] = true, + ["Ravage"] = true, + ["Readiness"] = true, + ["Rebirth"] = true, + ["Reckless Charge"] = true, + ["Recklessness"] = true, + ["Reckoning"] = true, + ["Redemption"] = true, + ["Redoubt"] = true, + ["Reflection"] = true, + ["Regeneration"] = true, + ["Regrowth"] = true, + ["Reincarnation"] = true, + ["Rejuvenation"] = true, + ["Relentless Strikes"] = true, + ["Remorseless"] = true, + ["Remorseless Attacks"] = true, + ["Remove Curse"] = true, + ["Remove Insignia"] = true, + ["Remove Lesser Curse"] = true, + ["Rend"] = true, + ["Renew"] = true, + ["Repentance"] = true, + ["Resurrection"] = true, + ["Retaliation"] = true, + ["Retribution Aura"] = true, + ["Revenge Stun"] = true, + ["Revenge"] = true, + ["Reverberation"] = true, + ["Revive Pet"] = true, + ["Righteous Defense"] = true, + ["Righteous Fury"] = true, + ["Rip"] = true, + ["Riposte"] = true, + ["Ritual of Doom Effect"] = true, + ["Ritual of Doom"] = true, + ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = true, + ["Rockbiter Weapon"] = true, + ["Rogue Passive"] = true, + ["Rough Sharpening Stone"] = true, + ["Ruin"] = true, + ["Rupture"] = true, + ["Ruthlessness"] = true, + ["Sacrifice"] = true, + ["Safe Fall"] = true, + ["Sanctity Aura"] = true, + ["Sap"] = true, + ["Savage Fury"] = true, + ["Savage Strikes"] = true, + ["Scare Beast"] = true, + ["Scatter Shot"] = true, + ["Scorch"] = true, + ["Scorpid Poison"] = true, + ["Scorpid Sting"] = true, + ["Screech"] = true, + ["Seal Fate"] = true, + ["Seal of Blood"] = true, + ["Seal of Command"] = true, + ["Seal of Justice"] = true, + ["Seal of Light"] = true, + ["Seal of Righteousness"] = true, + ["Seal of Wisdom"] = true, + ["Seal of the Crusader"] = true, + ["Seal of Vengeance"] = true, + ["Searing Light"] = true, + ["Searing Pain"] = true, + ["Searing Totem"] = true, + ["Second Wind"] = true, + ["Seduction"] = true, + ["Seed of Corruption"] = true, + ["Sense Demons"] = true, + ["Sense Undead"] = true, + ["Sentry Totem"] = true, + ["Serpent Sting"] = true, + ["Setup"] = true, + ["Shackle Undead"] = true, + ["Shadow Affinity"] = true, + ["Shadow Bolt"] = true, + ["Shadow Focus"] = true, + ["Shadow Mastery"] = true, + ["Shadow Protection"] = true, + ["Shadow Reach"] = true, + ["Shadow Resistance Aura"] = true, + ["Shadow Resistance"] = true, + ["Shadow Trance"] = true, + ["Shadow Vulnerability"] = true, + ["Shadow Ward"] = true, + ["Shadow Weaving"] = true, + ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = true, + ["Shadowburn"] = true, + ["Shadowfiend"] = true, + ["Shadowform"] = true, + ["Shadowfury"] = true, + ["Shadowguard"] = true, + ["Shadowmeld Passive"] = true, + ["Shadowmeld"] = true, + ["Shadowstep"] = true, + ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = true, + ["Shatter"] = true, + ["Sheep"] = true, + ["Shell Shield"] = true, + ["Shield Bash"] = true, + ["Shield Bash - Silenced"] = true, + ["Shield Block"] = true, + ["Shield Slam"] = true, + ["Shield Specialization"] = true, + ["Shield Wall"] = true, + ["Shield"] = true, + ["Shiv"] = true, + ["Shoot Bow"] = true, + ["Shoot Crossbow"] = true, + ["Shoot Gun"] = true, + ["Shoot"] = true, + ["Shred"] = true, + ["Silence"] = true, + ["Silencing Shot"] = true, + ["Silent Resolve"] = true, + ["Sinister Strike"] = true, + ["Siphon Life"] = true, + ["Skinning"] = true, + ["Slam"] = true, + ["Sleep"] = true, + ["Slice and Dice"] = true, + ["Slow"] = true, + ["Slow Fall"] = true, + ["Smelting"] = true, + ["Smite"] = true, + ["Snake Trap"] = true, + ["Solid Sharpening Stone"] = true, + ["Soothe Animal"] = true, + ["Soothing Kiss"] = true, + ["Soul Fire"] = true, + ["Soul Link"] = true, + ["Soul Siphon"] = true, + ["Soulshatter"] = true, + ["Soulstone Resurrection"] = true, + ["Spell Lock"] = true, + ["Spellsteal"] = true, + ["Spell Reflection"] = true, + ["Spell Warding"] = true, + ["Spirit Bond"] = true, + ["Spirit Tap"] = true, + ["Spirit of Redemption"] = true, + ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = true, + ["Spiritual Guidance"] = true, + ["Spiritual Healing"] = true, + ["Sprint"] = true, + ["Stance Mastery"] = true, + ["Starfire"] = true, + ["Starfire Stun"] = true, + ["Starshards"] = true, + ["Staves"] = true, + ["Steady Shot"] = true, + ["Stealth"] = true, + ["Stoneclaw Totem"] = true, + ["Stoneform"] = true, + ["Stoneskin Totem"] = true, + ["Stormstrike"] = true, + ["Strength of Earth Totem"] = true, + ["Stuck"] = true, + ["Subtlety"] = true, + ["Suffering"] = true, + ["Summon Charger"] = true, + ["Summon Dreadsteed"] = true, + ["Summon Felguard"] = true, + ["Summon Felhunter"] = true, + ["Summon Felsteed"] = true, + ["Summon Imp"] = true, + ["Summon Succubus"] = true, + ["Summon Voidwalker"] = true, + ["Summon Warhorse"] = true, + ["Summon Water Elemental"] = true, + ["Sunder Armor"] = true, + ["Suppression"] = true, + ["Surefooted"] = true, + ["Survivalist"] = true, + ["Sweeping Strikes"] = true, + ["Swiftmend"] = true, + ["Swipe"] = true, + ["Sword Specialization"] = true, + ["Tactical Mastery"] = true, + ["Tainted Blood"] = true, + ["Tailoring"] = true, + ["Tame Beast"] = true, + ["Tamed Pet Passive"] = true, + ["Taunt"] = true, + ["Teleport: Darnassus"] = true, + ["Teleport: Ironforge"] = true, + ["Teleport: Moonglade"] = true, + ["Teleport: Orgrimmar"] = true, + ["Teleport: Stormwind"] = true, + ["Teleport: Thunder Bluff"] = true, + ["Teleport: Undercity"] = true, + ["The Beast Within"] = true, + ["The Human Spirit"] = true, + ["Thick Hide"] = true, + ["Thorns"] = true, + ["Throw"] = true, + ["Throwing Specialization"] = true, + ["Throwing Weapon Specialization"] = true, + ["Thrown"] = true, + ["Thunder Clap"] = true, + ["Thundering Strikes"] = true, + ["Thunderstomp"] = true, + ["Tidal Focus"] = true, + ["Tidal Mastery"] = true, + ["Tiger Riding"] = true, + ["Tiger's Fury"] = true, + ["Torment"] = true, + ["Totem"] = true, + ["Totem of Wrath"] = true, + ["Totemic Focus"] = true, + ["Touch of Weakness"] = true, + ["Toughness"] = true, + ["Track Beasts"] = true, + ["Track Demons"] = true, + ["Track Dragonkin"] = true, + ["Track Elementals"] = true, + ["Track Giants"] = true, + ["Track Hidden"] = true, + ["Track Humanoids"] = true, + ["Track Undead"] = true, + ["Tranquil Air Totem"] = true, + ["Tranquil Spirit"] = true, + ["Tranquility"] = true, + ["Tranquilizing Shot"] = true, + ["Trap Mastery"] = true, + ["Travel Form"] = true, + ["Tree of Life"] = true, + ["Tremor Totem"] = true, + ["Tribal Leatherworking"] = true, + ["Trueshot Aura"] = true, + ["Turn Undead"] = true, + ["Two-Handed Axes and Maces"] = true, + ["Two-Handed Axes"] = true, + ["Two-Handed Maces"] = true, + ["Two-Handed Swords"] = true, + ["Two-Handed Weapon Specialization"] = true, + ["Unarmed"] = true, + ["Unbreakable Will"] = true, + ["Unbridled Wrath Effect"] = true, + ["Unbridled Wrath"] = true, + ["Undead Horsemanship"] = true, + ["Underwater Breathing"] = true, + ["Unending Breath"] = true, + ["Unholy Power"] = true, + ["Unleashed Fury"] = true, + ["Unleashed Rage"] = true, + ["Unstable Affliction"] = true, + ["Unyielding Faith"] = true, + ["Vampiric Embrace"] = true, + ["Vanish"] = true, + ["Vanished"] = true, + ["Vampiric Touch"] = true, + ["Vengeance"] = true, + ["Victory Rush"] = true, + ["Vigor"] = true, + ["Vile Poisons"] = true, + ["Vindication"] = true, + ["Viper Sting"] = true, + ["Volley"] = true, + ["Wand Specialization"] = true, + ["Wands"] = true, + ["War Stomp"] = true, + ["Water Breathing"] = true, + ["Water Shield"] = true, + ["Water Walking"] = true, + ["Waterbolt"] = true, + ["Weakened Soul"] = true, + ["Weaponsmith"] = true, + ["Whirlwind"] = true, + ["Will of the Forsaken"] = true, + ["Windfury Totem"] = true, + ["Windfury Weapon"] = true, + ["Windwall Totem"] = true, + ["Wing Clip"] = true, + ["Winter's Chill"] = true, + ["Wisp Spirit"] = true, + ["Wolf Riding"] = true, + ["Wound Poison II"] = true, + ["Wound Poison III"] = true, + ["Wound Poison IV"] = true, + ["Wound Poison"] = true, + ["Wrath"] = true, + ["Wrath of Air Totem"] = true, + ["Wyvern Sting"] = true, + } +end) + +BabbleSpell:RegisterTranslations("deDE", function() + return { + ["Abolish Disease"] = "Krankheit aufheben", + ["Abolish Poison Effect"] = "Vergiftung aufheben - Effekt", + ["Abolish Poison"] = "Vergiftung aufheben", + ["Activate MG Turret"] = "MG-Turm aktivieren", + ["Adrenaline Rush"] = "Adrenalinrausch", + ["Aftermath"] = "Nachwirkung", + ["Aggression"] = "Aggression", + ["Aimed Shot"] = "Gezielter Schuss", + ["Alchemy"] = "Alchimie", + ["Ambush"] = "Hinterhalt", + ["Amplify Curse"] = "Fluch verst\195\164rken", + ["Amplify Magic"] = "Magie verst\195\164rken", + ["Ancestral Fortitude"] = "Seelenstrke der Ahnen", + ["Ancestral Healing"] = "Heilung der Ahnen", + ["Ancestral Knowledge"] = "Wissen der Ahnen", + ["Ancestral Spirit"] = "Geist der Ahnen", +-- ["Anesthetic Poison"] = true, + ["Anger Management"] = "Aggressionskontrolle", +-- ["Anguish"] = true, + ["Anticipation"] = "Vorahnung", + ["Aquatic Form"] = "Wassergestalt", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"] = "Arkane Brillanz", + ["Arcane Concentration"] = "Arkane Konzentration", + ["Arcane Explosion"] = "Arkane Explosion", + ["Arcane Focus"] = "Arkaner Fokus", + ["Arcane Instability"] = "Arkane Instabilit\195\164t", + ["Arcane Intellect"] = "Arkane Intelligenz", + ["Arcane Meditation"] = "Arkane Meditation", + ["Arcane Mind"] = "Arkaner Geist", + ["Arcane Missiles"] = "Arkane Geschosse", + ["Arcane Power"] = "Arkane Macht", + ["Arcane Resistance"] = "Arkanwiderstand", + ["Arcane Shot"] = "Arkaner Schuss", + ["Arcane Subtlety"] = "Arkanes Feingef\195\188hl", + ["Arctic Reach"] = "Arktische Reichweite", + ["Armorsmith"] = "R\195\188stungsschmied", + ["Aspect of the Beast"] = "Aspekt des Wildtiers", + ["Aspect of the Cheetah"] = "Aspekt des Geparden", + ["Aspect of the Hawk"] = "Aspekt des Falken", + ["Aspect of the Monkey"] = "Aspekt des Affen", + ["Aspect of the Pack"] = "Aspekt des Rudels", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = "Aspekt der Wildnis", + ["Astral Recall"] = "Astraler R\195\188ckruf", + ["Attack"] = "Angreifen", + ["Attacking"] = "Angreifen", + ["Auto Shot"] = "Autom. Schuss", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"] = "Axt-Spezialisierung", +-- ["Backlash"] = true, + ["Backstab"] = "Meucheln", + ["Bane"] = "Dunkle Macht", + ["Banish"] = "Verbannen", + ["Barkskin Effect"] = "Baumrindeneffekt", + ["Barkskin"] = "Baumrinde", + ["Barrage"] = "Sperrfeuer", + ["Bash"] = "Hieb", + ["Basic Campfire"] = "Einfaches Lagerfeuer", + ["Battle Shout"] = "Schlachtruf", + ["Battle Stance Passive"] = "Kampfhaltung Passiv", + ["Battle Stance"] = "Kampfhaltung", + ["Bear Form"] = "B\195\164rengestalt", + ["Beast Lore"] = "Wildtierkunde", + ["Beast Slaying"] = "Wildtierschl\195\164chter", + ["Beast Training"] = "Wildtierausbildung", + ["Benediction"] = "Segnung", + ["Berserker Rage"] = "Berserkerwut", + ["Berserker Stance Passive"] = "Berserkerhaltung - Passiv", + ["Berserker Stance"] = "Berserkerhaltung", + ["Berserking"] = "Berserker", + ["Bestial Discipline"] = "Wildtierdisziplin", + ["Bestial Swiftness"] = "Erh\195\182hte Tiergeschwindigkeit", + ["Bestial Wrath"] = "Zorn des Wildtiers", +-- ["Binding Heal"] = true, + ["Bite"] = "Bei\195\159en", + ["Black Arrow"] = "Schwarzer Pfeil", + ["Blackout"] = "Verdunkelung", + ["Blacksmithing"] = "Schmiedekunst", + ["Blade Flurry"] = "Klingenwirbel", + ["Blast Wave"] = "Druckwelle", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"] = "Gesegnete Erholung", + ["Blessing of Freedom"] = "Segen der Freiheit", + ["Blessing of Kings"] = "Segen der K\195\182nige", + ["Blessing of Light"] = "Segen des Lichts", + ["Blessing of Might"] = "Segen der Macht", + ["Blessing of Protection"] = "Segen des Schutzes", + ["Blessing of Sacrifice"] = "Segen der Opferung", + ["Blessing of Salvation"] = "Segen der Rettung", + ["Blessing of Sanctuary"] = "Segen des Refugiums", + ["Blessing of Wisdom"] = "Segen der Weisheit", + ["Blind"] = "Blenden", + ["Blinding Powder"] = "Blendungspulver", + ["Blink"] = "Blinzeln", + ["Blizzard"] = "Blizzard", + ["Block"] = "Blocken", + ["Blood Craze"] = "Blutwahnsinn", + ["Blood Frenzy"] = "Blutraserei", + ["Blood Fury"] = "Kochendes Blut", + ["Blood Pact"] = "Blutpakt", +-- ["Bloodlust"] = true, + ["Bloodrage"] = "Blutrausch", + ["Bloodthirst"] = "Blutdurst", + ["Booming Voice"] = "Donnernde Stimme", + ["Bow Specialization"] = "Bogenspezialisierung", + ["Bows"] = "Bogen", + ["Bright Campfire"] = "Helles Lagerfeuer", + ["Brutal Impact"] = "Brutaler Hieb", + ["Burning Soul"] = "Brennende Seele", + ["Call Pet"] = "Tier rufen", + ["Call of Flame"] = "Ruf der Flamme", + ["Call of Thunder"] = "Ruf des Donners", + ["Camouflage"] = "Tarnung", + ["Cannibalize"] = "Kannibalismus", + ["Cat Form"] = "Katzengestalt", + ["Cataclysm"] = "Katastrophe", + ["Chain Heal"] = "Kettenheilung", + ["Chain Lightning"] = "Kettenblitzschlag", + ["Challenging Roar"] = "Herausforderndes Gebr\195\188ll", + ["Challenging Shout"] = "Herausforderungsruf", + ["Charge Rage Bonus Effect"] = "Wut-Aufladung-Bonus-Effekt", + ["Charge"] = "Sturmangriff", + ["Charge Stun"] = "Sturmangriffsbetubung", + ["Cheap Shot"] = "Fieser Trick", + ["Chilled"] = "K\195\164lte", +-- ["Circle of Healing"] = true, + ["Claw"] = "Klaue", + ["Cleanse"] = "Reinigung des Glaubens", + ["Clearcasting"] = "Freizaubern", + ["Cleave"] = "Spalten", + ["Clever Traps"] = "Falleneffizienz", +-- ["Cloak of Shadows"] = true, + ["Closing"] = "Schlie\195\159en", + ["Cloth"] = "Stoff", + ["Cobra Reflexes"] = "Kobrareflexe", + ["Cold Blood"] = "Kaltbl\195\188tigkeit", + ["Cold Snap"] = "K\195\164lteeinbruch", + ["Combat Endurance"] = "Durchhalteverm\195\182gen des K\195\164mpfers", + ["Combustion"] = "Verbrennung", + ["Command"] = "Befehlsgewalt", +-- ["Commanding Shout"] = true, + ["Concentration Aura"] = "Aura der Konzentration", + ["Concussion Blow"] = "Ersch\195\188tternder Schlag", + ["Concussion"] = "Ersch\195\188tterung", + ["Concussive Shot"] = "Ersch\195\188tternder Schuss", + ["Cone of Cold"] = "K\195\164ltekegel", + ["Conflagrate"] = "Feuersbrunst", + ["Conjure Food"] = "Essen herbeizaubern", + ["Conjure Mana Agate"] = "Mana-Achat herbeizaubern", + ["Conjure Mana Citrine"] = "Mana-Citrin herbeizaubern", + ["Conjure Mana Jade"] = "Mana-Jadestein herbeizaubern", + ["Conjure Mana Ruby"] = "Mana-Rubin herbeizaubern", + ["Conjure Water"] = "Wasser herbeizaubern", + ["Consecration"] = "Weihe", +-- ["Consume Magic"] = true, + ["Consume Shadows"] = "Schatten verzehren", + ["Convection"] = "Konvektion", + ["Conviction"] = "\195\156berzeugung", + ["Cooking"] = "Kochkunst", + ["Corruption"] = "Verderbnis", + ["Counterattack"] = "Gegenangriff", + ["Counterspell"] = "Gegenzauber", + ["Counterspell - Silenced"] = "Gegenzauber - zum Schweigen gebracht", + ["Cower"] = "Ducken", + ["Create Firestone"] = "Feuerstein herstellen", + ["Create Firestone (Major)"] = "Feuerstein herstellen (Gro\195\159er)", + ["Create Firestone (Greater)"] = "Feuerstein herstellen (Gr\195\182\sser)", + ["Create Firestone (Lesser)"] = "Feuerstein herstellen (Kleiner)", + ["Create Healthstone"] = "Gesundheitsstein herstellen", + ["Create Healthstone (Major)"] = "Gesundheitsstein herstellen (Gro\195\159er)", + ["Create Healthstone (Greater)"] = "Gesundheitsstein herstellen (Gr\195\182\sser)", + ["Create Healthstone (Lesser)"] = "Gesundheitsstein herstellen (Kleiner)", + ["Create Healthstone (Minor)"] = "Gesundheitsstein herstellen (Klein)", + ["Create Soulstone"] = "Seelenstein herstellen", + ["Create Soulstone (Major)"] = "Seelenstein herstellen (Gro\195\159er)", + ["Create Soulstone (Greater)"] = "Seelenstein herstellen (Gr\195\182\sser)", + ["Create Soulstone (Lesser)"] = "Seelenstein herstellen (Kleiner)", + ["Create Soulstone (Minor)"] = "Seelenstein herstellen (Klein)", + ["Create Spellstone"] = "Zauberstein herstellen", + ["Create Spellstone (Major)"] = "Zauberstein herstellen (Gro\195\159er)", + ["Create Spellstone (Greater)"] = "Zauberstein herstellen (Gr\195\182\sser)", + ["Crippling Poison II"] = "Verkr\195\188ppelndes Gift II", + ["Crippling Poison"] = "Verkr\195\188ppelndes Gift", + ["Critical Mass"] = "Kritische Masse", + ["Crossbows"] = "Armbr\195\188ste", + ["Cruelty"] = "Grausamkeit", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"] = "Gr\195\188ner Daumen", + ["Cure Disease"] = "Krankheit heilen", + ["Cure Poison"] = "Vergiftung heilen", + ["Curse of Agony"] = "Fluch der Pein", + ["Curse of Doom Effect"] = "Fluch der Verdammnis'-Effekt", + ["Curse of Doom"] = "Fluch der Verdammnis", + ["Curse of Exhaustion"] = "Fluch der Ersch\195\182pfung", + ["Curse of Idiocy"] = "Fluch der Torheit", + ["Curse of Recklessness"] = "Fluch der Tollk\195\188hnheit", + ["Curse of Shadow"] = "Fluch der Schatten", + ["Curse of Tongues"] = "Fluch der Sprachen", + ["Curse of Weakness"] = "Fluch der Schw\195\164che", + ["Curse of the Elements"] = "Fluch der Elemente", +-- ["Cyclone"] = true, + ["Dagger Specialization"] = "Dolch-Spezialisierung", + ["Daggers"] = "Dolche", + ["Dampen Magic"] = "Magie d\195\164mpfen", + ["Dark Pact"] = "Dunkler Pakt", + ["Darkness"] = "Dunkelheit", + ["Dash"] = "Spurt", + ["Deadly Poison II"] = "T\195\182dliches Gift II", + ["Deadly Poison III"] = "T\195\182dliches Gift III", + ["Deadly Poison IV"] = "T\195\182dliches Gift IV", + ["Deadly Poison V"] = "T\195\182dliches Gift V", + ["Deadly Poison"] = "T\195\182dliches Gift", +-- ["Deadly Throw"] = true, + ["Death Coil"] = "Todesmantel", + ["Death Wish"] = "Todeswunsch", + ["Deep Wounds"] = "Tiefe Wunden", + ["Defense"] = "Verteidigung", + ["Defensive Stance Passive"] = "Verteidigungshaltung - Passiv", + ["Defensive Stance"] = "Verteidigungshaltung", + ["Defensive State 2"] = "Verteidigungsstatus 2", + ["Defensive State"] = "Verteidigungsstatus", + ["Defiance"] = "Trotz", + ["Deflection"] = "Abwehr", + ["Demon Armor"] = "D\195\164monenr\195\188stung", + ["Demon Skin"] = "D\195\164monenhaut", + ["Demonic Embrace"] = "D\195\164monische Umarmung", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = "D\195\164monische Opferung", + ["Demoralizing Roar"] = "Demoralisierendes Gebr\195\188ll", + ["Demoralizing Shout"] = "Demoralisierungsruf", + ["Desperate Prayer"] = "Verzweifeltes Gebet", + ["Destructive Reach"] = "Zerst\195\182rerische Reichweite", + ["Detect Greater Invisibility"] = "Gro\195\159e Unsichtbarkeit entdecken", + ["Detect Invisibility"] = "Unsichtbarkeit entdecken", + ["Detect Lesser Invisibility"] = "Geringe Unsichtbarkeit entdecken", + ["Detect Magic"] = "Magie entdecken", + ["Detect Traps"] = "Fallen entdecken", + ["Detect"] = "Entdecken", + ["Deterrence"] = "Abschreckung", +-- ["Devastate"] = true, + ["Devastation"] = "Verw\195\188stung", + ["Devotion Aura"] = "Aura der Hingabe", + ["Devour Magic Effect"] = "Magie verschlingen' - Effekt", + ["Devour Magic"] = "Magie verschlingen", + ["Devouring Plague"] = "Verschlingende Seuche", + ["Diplomacy"] = "Diplomatie", + ["Dire Bear Form"] = "Terrorb\195\164rengestalt", + ["Disarm Trap"] = "Falle entsch\195\164rfen", + ["Disarm"] = "Entwaffnen", + ["Disease Cleansing Totem"] = "Totem der Krankheitsreinigung", + ["Disenchant"] = "Entzaubern", + ["Disengage"] = "R\195\188ckzug", + ["Dismiss Pet"] = "Tier freigeben", + ["Dispel Magic"] = "Magiebannung", + ["Distract"] = "Ablenken", + ["Distracting Shot"] = "Ablenkender Schuss", + ["Dive"] = "Sturzflug", + ["Divine Favor"] = "G\195\182ttliche Gunst", + ["Divine Fury"] = "G\195\182ttlicher Furor", +-- ["Divine Illumination"] = true, + ["Divine Intellect"] = "G\195\182ttliche Weisheit", + ["Divine Intervention"] = "G\195\182ttliches Eingreifen", + ["Divine Protection"] = "G\195\182ttlicher Schutz", + ["Divine Shield"] = "Gottesschild", + ["Divine Spirit"] = "G\195\182ttlicher Willen", + ["Divine Strength"] = "G\195\182ttliche St\195\164rke", + ["Dodge"] = "Ausweichen", +-- ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"] = "Drachenschuppenlederverarbeitung", + ["Drain Life"] = "Blutsauger", + ["Drain Mana"] = "Mana entziehen", + ["Drain Soul"] = "Seelendieb", + ["Drink"] = "Trinken", + ["Dual Wield Specialization"] = "Beidh\195\164ndigkeits-Spezialisierung", + ["Dual Wield"] = "Beidh\195\164ndigkeit", + ["Duel"] = "Duell", + ["Eagle Eye"] = "Adlerauge", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"] = "Erdschock", + ["Earthbind Totem"] = "Totem der Erdbindung", + ["Efficiency"] = "Effizienz", + ["Elemental Focus"] = "Elementarfokus", + ["Elemental Fury"] = "Elementarfuror", + ["Elemental Leatherworking"] = "Elementarlederverarbeitung", + ["Elemental Mastery"] = "Elementarbeherrschung", + ["Elune's Grace"] = "Elunes Anmut", + ["Elusiveness"] = "Fl\195\188chtigkeit", + ["Emberstorm"] = "Glutsturm", + ["Enamored Water Spirit"] = "Entzckter Wassergeist", + ["Enchanting"] = "Verzauberkunst", + ["Endurance Training"] = "Belastbarkeit-Ausbildung", + ["Endurance"] = "Durchhalteverm\195\182gen", + ["Engineering Specialization"] = "Technologist", + ["Engineering"] = "Ingenieurskunst", + ["Enrage"] = "Wutanfall", + ["Enriched Manna Biscuit"] = "Angereicherter Manakeks", + ["Enslave Demon"] = "D\195\164monensklave", + ["Entangling Roots"] = "Wucherwurzeln", + ["Entrapment"] = "Einfangen", +-- ["Envenom"] = true, + ["Escape Artist"] = "Entfesselungsk\195\188nstler", + ["Evasion"] = "Entrinnen", + ["Eventide"] = "Abendzeit", + ["Eviscerate"] = "Ausweiden", + ["Evocation"] = "Hervorrufung", + ["Execute"] = "Hinrichten", + ["Exorcism"] = "Exorzismus", + ["Expansive Mind"] = "Wacher Geist", + ["Explosive Trap Effect"] = "Sprengfalle'-Effekt", + ["Explosive Trap"] = "Sprengfalle", + ["Expose Armor"] = "R\195\188stung schw\195\164chen", + ["Eye for an Eye"] = "Auge um Auge", + ["Eye of Kilrogg"] = "Auge von Kilrogg", + ["Eyes of the Beast"] = "Augen des Wildtiers", + ["Fade"] = "Verblassen", + ["Faerie Fire"] = "Feenfeuer", + ["Faerie Fire (Feral)"] = "Feenfeuer (Tiergestalt)", + ["Far Sight"] = "Fernsicht", + ["Fear Ward"] = "Furchtzauberschutz", + ["Fear"] = "Furcht", + ["Feed Pet"] = "Tier f\195\188ttern", + ["Feedback"] = "R\195\188ckkopplung", + ["Feign Death"] = "Totstellen", + ["Feint"] = "Finte", +-- ["Fel Armor"] = true, + ["Fel Concentration"] = "Teufelskonzentration", + ["Fel Domination"] = "Teufelsbeherrschung", + ["Fel Intellect"] = "Teufelsintelligenz", + ["Fel Stamina"] = "Teufelsausdauer", + ["Felfire"] = "Teufelsfeuer", + ["Feline Grace"] = "Katzenhafte Anmut", + ["Feline Swiftness"] = "Katzenhafte Schnelligkeit", + ["Feral Aggression"] = "Wilde Aggression", + ["Feral Charge"] = "Wilde Attacke", + ["Feral Instinct"] = "Instinkt der Wildnis", + ["Ferocious Bite"] = "Wilder Biss", + ["Ferocity"] = "Wildheit", + ["Fetish"] = "Fetisch", + ["Find Herbs"] = "Kr\195\164utersuche", + ["Find Minerals"] = "Mineraliensuche", + ["Find Treasure"] = "Schatzsucher", + ["Fire Blast"] = "Feuerschlag", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = "Totem der Feuernova", + ["Fire Power"] = "Feuermacht", + ["Fire Resistance Aura"] = "Aura des Feuerwiderstands", + ["Fire Resistance Totem"] = "Totem des Feuerwiderstands", + ["Fire Resistance"] = "Feuerwiderstand", + ["Fire Shield"] = "Feuerschild", + ["Fire Vulnerability"] = "Feuerverwundbarkeit", + ["Fire Ward"] = "Feuerzauberschutz", + ["Fireball"] = "Feuerball", + ["Firebolt"] = "Feuerblitz", + ["First Aid"] = "Erste Hilfe", + ["Fishing Poles"] = "Angeln", + ["Fishing"] = "Angeln", + ["Fist Weapon Specialization"] = "Faustwaffen-Spezialisierung", + ["Fist Weapons"] = "Faustwaffen", + ["Flame Shock"] = "Flammenschock", + ["Flame Throwing"] = "Flammenwerfen", + ["Flamestrike"] = "Flammensto\195\159", + ["Flamethrower"] = "Flammenwerfer", + ["Flametongue Totem"] = "Totem der Flammenzunge", + ["Flametongue Weapon"] = "Waffe der Flammenzunge", + ["Flare"] = "Leuchtfeuer", + ["Flash Heal"] = "Blitzheilung", + ["Flash of Light"] = "Lichtblitz", +-- ["Flight Form"] = true, + ["Flurry"] = "Schlaghagel", + ["Focused Casting"] = "Fokussiertes Zauberwirken", + ["Food"] = "Essen", + ["Forbearance"] = "Vorahnung", +-- ["Force of Nature"] = true, + ["Force of Will"] = "Macht des Willens", + ["Freezing Trap Effect"] = "Eisk?tefalle", + ["Freezing Trap"] = "Eisk\195\164ltefalle", + ["Frenzied Regeneration"] = "Rasende Regeneration", + ["Frenzy"] = "Raserei", + ["Frost Armor"] = "Frostr\195\188stung", + ["Frost Channeling"] = "Frost-Kanalisierung", + ["Frost Nova"] = "Frostnova", + ["Frost Resistance Aura"] = "Aura des Frostwiderstands", + ["Frost Resistance Totem"] = "Totem des Frostwiderstands", + ["Frost Resistance"] = "Frostwiderstand", + ["Frost Shock"] = "Frostschock", + ["Frost Trap"] = "Frostfalle", + ["Frost Trap Aura"] = "Frostfalle-Aura", + ["Frost Ward"] = "Frostzauberschutz", + ["Frostbite"] = "Erfrierung", + ["Frostbolt"] = "Frostblitz", + ["Frostbrand Weapon"] = "Waffe des Frostbrands", + ["Furious Howl"] = "Wutgeheul", + ["Furor"] = "Furor", + ["Garrote"] = "Erdrosseln", + ["Generic"] = "Allgemein", + ["Ghost Wolf"] = "Geisterwolf", + ["Ghostly Strike"] = "Geisterhafter Sto\195\159", + ["Gift of Life"] = "Geschenk des Lebens", + ["Gift of Nature"] = "Geschenk der Natur", + ["Gift of the Wild"] = "Gabe der Wildnis", + ["Gouge"] = "Solarplexus", + ["Grace of Air Totem"] = "Totem der luftgleichen Anmut", + ["Great Stamina"] = "Gro\195\159e Ausdauer", + ["Greater Blessing of Kings"] = "Gro\195\159er Segen der K\195\182nige", + ["Greater Blessing of Light"] = "Gro\195\159er Segen des Lichts", + ["Greater Blessing of Might"] = "Gro\195\159er Segen der Macht", + ["Greater Blessing of Salvation"] = "Gro\195\159er Segen der Rettung", + ["Greater Blessing of Sanctuary"] = "Gro\195\159er Segen des Refugiums", + ["Greater Blessing of Wisdom"] = "Gro\195\159er Segen der Weisheit", + ["Greater Heal"] = "Gro\195\159e Heilung", + ["Grim Reach"] = "Grimmige Reichweite", + ["Grounding Totem"] = "Totem der Erdung", + ["Grovel"] = "Kriechen", + ["Growl"] = "Knurren", + ["Guardian's Favor"] = "Gunst des H\195\188ters", + ["Gun Specialization"] = "Schusswaffenspezialisierung", + ["Guns"] = "Schusswaffen", + ["Hammer of Justice"] = "Hammer der Gerechtigkeit", + ["Hammer of Wrath"] = "Hammer des Zorns", + ["Hamstring"] = "Kniesehne", + ["Harass"] = "Bel\195\164stigen", + ["Hardiness"] = "Z\195\164higkeit", + ["Hawk Eye"] = "Falkenauge", + ["Heal"] = "Heilen", + ["Healing Focus"] = "Heilfokus", + ["Healing Light"] = "Heilendes Licht", + ["Healing Stream Totem"] = "Totem des heilenden Flusses", + ["Healing Touch"] = "Heilende Ber\195\188hrung", + ["Healing Wave"] = "Welle der Heilung", +-- ["Healing Way"] = true, + ["Health Funnel"] = "Lebenslinie", + ["Heart of the Wild"] = "Herz der Wildnis", + ["Hellfire Effect"] = "H\195\182llenfeuer - Effekt", + ["Hellfire"] = "H\195\182llenfeuer", + ["Hemorrhage"] = "Blutsturz", + ["Herbalism"] = "Kr\195\164utersammeln", + ["Heroic Strike"] = "Heldenhafter Sto\195\159", +-- ["Heroism"] = true, + ["Hex of Weakness"] = "Verhexung der Schw\195\164che", + ["Hibernate"] = "Winterschlaf", + ["Holy Fire"] = "Heiliges Feuer", + ["Holy Light"] = "Heiliges Licht", + ["Holy Nova"] = "Heilige Nova", + ["Holy Power"] = "Heilige Macht", + ["Holy Reach"] = "Heilige Reichweite", + ["Holy Shield"] = "Heiliger Schild", + ["Holy Shock"] = "Heiliger Schock", + ["Holy Specialization"] = "Macht des Glaubens", + ["Holy Wrath"] = "Heiliger Zorn", + ["Honorless Target"] = "Ehrenloses Ziel", + ["Horse Riding"] = "Pferdreiten", + ["Howl of Terror"] = "Schreckgeheul", + ["Humanoid Slaying"] = "Humanoident\195\182ten", + ["Hunter's Mark"] = "Mal des J\195\164gers", + ["Hurricane"] = "Hurrikan", + ["Ice Armor"] = "Eisr\195\188stung", + ["Ice Barrier"] = "Eis-Barriere", + ["Ice Block"] = "Eisblock", +-- ["Ice Lance"] = true, + ["Ice Shards"] = "Eissplitter", + ["Ignite"] = "Entz\195\188nden", + ["Illumination"] = "Illumination", + ["Immolate"] = "Feuerbrand", + ["Immolation Trap Effect"] = "Feuerbrandfalle", + ["Immolation Trap"] = "Feuerbrandfalle", + ["Impact"] = "Einschlag", + ["Impale"] = "Durchbohren", + ["Improved Ambush"] = "Verbesserter Hinterhalt", + ["Improved Arcane Explosion"] = "Verbesserte Arkane Explosion", + ["Improved Arcane Missiles"] = "Verbesserte arkane Geschosse", + ["Improved Arcane Shot"] = "Verbesserter Arkaner Schuss", + ["Improved Aspect of the Hawk"] = "Verbesserter Aspekt des Falken", + ["Improved Aspect of the Monkey"] = "Verbesserter Aspekt des Affen", + ["Improved Backstab"] = "Verbessertes Meucheln", + ["Improved Battle Shout"] = "Verbesserter Schlachtruf", + ["Improved Berserker Rage"] = "Verbesserte Berserkerwut", + ["Improved Blessing of Might"] = "Verbesserter Segen der Macht", + ["Improved Blessing of Wisdom"] = "Verbesserter Segen der Weisheit", + ["Improved Blizzard"] = "Verbesserter Blizzard", + ["Improved Bloodrage"] = "Verbesserter Blutrausch", + ["Improved Chain Heal"] = "Verbesserte Kettenheilung", + ["Improved Chain Lightning"] = "Verbesserter Kettenblitzschlag", + ["Improved Challenging Shout"] = "Verbesserter Herausforderungsruf", + ["Improved Charge"] = "Verbesserter Sturmangriff", + ["Improved Cheap Shot"] = "Verbesserter Fieser Trick", + ["Improved Cleave"] = "Verbessertes Spalten", + ["Improved Concentration Aura"] = "Verbesserte Aura der Konzentration", + ["Improved Concussive Shot"] = "Verbesserter Ersch\195\188tternder Schuss", + ["Improved Cone of Cold"] = "Verbesserter K\195\164ltekegel", + ["Improved Corruption"] = "Verbesserte Verderbnis", + ["Improved Counterspell"] = "Verbesserter Gegenzauber", + ["Improved Curse of Agony"] = "Verbesserter Fluch der Pein", + ["Improved Curse of Exhaustion"] = "Verbesserter Fluch der Ersch\195\182pfung", + ["Improved Curse of Weakness"] = "Verbesserter Fluch der Schw\195\164che", + ["Improved Dampen Magic"] = "Verbesserter Magied\195\164mpfer", + ["Improved Deadly Poison"] = "Verbessertes t\195\182dliches Gift", + ["Improved Demoralizing Shout"] = "Verbesserter Demoralisierender Ruf", + ["Improved Devotion Aura"] = "Verbesserte Aura der Hingabe", + ["Improved Disarm"] = "Verbessertes Entwaffnen", + ["Improved Distract"] = "Verbessertes Ablenken", + ["Improved Drain Life"] = "Verbesserter Blutsauger", + ["Improved Drain Mana"] = "Verbessertes Mana entziehen", + ["Improved Drain Soul"] = "Verbesserter Seelendieb", + ["Improved Enrage"] = "Verbesserter Wutanfall", + ["Improved Enslave Demon"] = "Verbesserter D\195\164monensklave", + ["Improved Entangling Roots"] = "Verbesserte Wucherwurzeln", + ["Improved Evasion"] = "Verbessertes Entrinnen", + ["Improved Eviscerate"] = "Verbessertes Ausweiden", + ["Improved Execute"] = "Verbessertes Hinrichten", + ["Improved Expose Armor"] = "Verbessertes R\195\188stung schw\195\164chen", + ["Improved Eyes of the Beast"] = "Verbesserte Augen des Wildtiers", + ["Improved Fade"] = "Verbessertes Verblassen", + ["Improved Feign Death"] = "Verbessertes Totstellen", + ["Improved Fire Blast"] = "Verbesserter Feuerschlag", + ["Improved Fire Nova Totem"] = "Verbessertes Totem der Feuernova", + ["Improved Fire Ward"] = "Verbesserter Feuerzauberschutz", + ["Improved Fireball"] = "Verbesserter Feuerball", + ["Improved Firebolt"] = "Verbesserter Feuerblitz", + ["Improved Firestone"] = "Verbesserter Feuerstein", + ["Improved Flamestrike"] = "Verbesserter Flammensto\195\159", + ["Improved Flametongue Weapon"] = "Verbesserte Waffe der Flammenzunge", + ["Improved Flash of Light"] = "Verbesserter Lichtblitz", + ["Improved Frost Nova"] = "Verbesserte Frostnova", + ["Improved Frost Ward"] = "Verbesserter Frostzauberschutz", + ["Improved Frostbolt"] = "Verbesserter Frostblitz", + ["Improved Frostbrand Weapon"] = "Verbesserte Waffe des Frostbrands", + ["Improved Garrote"] = "Verbessertes Erdrosseln", + ["Improved Ghost Wolf"] = "Verbesserter Geisterwolf", + ["Improved Gouge"] = "Verbesserter Solarplexus", + ["Improved Grace of Air Totem"] = "Verbessertes Totem der luftgleichen Anmut", + ["Improved Grounding Totem"] = "Verbessertes Totem der Erdung", + ["Improved Hammer of Justice"] = "Verbesserter Hammer der Gerechtigkeit", + ["Improved Hamstring"] = "Verbesserte Kniesehne", + ["Improved Healing Stream Totem"] = "Verbessertes Totem des heilenden Flusses", + ["Improved Healing Touch"] = "Verbesserte Heilende Ber\195\188hrung", + ["Improved Healing Wave"] = "Verbesserte Welle der Heilung", + ["Improved Healing"] = "Verbesserte Heilung", + ["Improved Health Funnel"] = "Verbesserte Lebenslinie", + ["Improved Healthstone"] = "Verbesserter Gesundheitsstein", + ["Improved Heroic Strike"] = "Verbesserter Heldenhafter Sto\195\159", + ["Improved Hunter's Mark"] = "Verbessertes Mal des J\195\164gers", + ["Improved Immolate"] = "Verbesserter Feuerbrand", + ["Improved Imp"] = "Verbesserter Wichtel", + ["Improved Inner Fire"] = "Verbessertes Inneres Feuer", + ["Improved Instant Poison"] = "Verbessertes sofort wirkendes Gift", + ["Improved Intercept"] = "Verbessertes Abfangen", + ["Improved Intimidating Shout"] = "Verbesserter Drohruf", + ["Improved Judgement"] = "Verbessertes Richturteil", + ["Improved Kick"] = "Verbesserter Tritt", + ["Improved Kidney Shot"] = "Verbesserter Nierenhieb", + ["Improved Lash of Pain"] = "Verbesserte Schmerzenspeitsche", + ["Improved Lay on Hands"] = "Verbesserte Handauflegung", + ["Improved Lesser Healing Wave"] = "Verbesserte Geringe Welle der Heilung", + ["Improved Life Tap"] = "Verbesserter Aderlass", + ["Improved Lightning Bolt"] = "Verbesserter Blitzschlag", + ["Improved Lightning Shield"] = "Verbesserter Blitzschlag-Schild", + ["Improved Magma Totem"] = "Verbessertes Totem der gl\195\188henden Magma", + ["Improved Mana Burn"] = "Verbesserter Manabrand", + ["Improved Mana Shield"] = "Verbesserter Manaschild", + ["Improved Mana Spring Totem"] = "Verbessertes Totem der Manaquelle", + ["Improved Mark of the Wild"] = "Verbessertes Mal der Wildnis", + ["Improved Mend Pet"] = "Verbessertes Tier heilen", + ["Improved Mind Blast"] = "Verbesserter Gedankenschlag", + ["Improved Moonfire"] = "Verbessertes Mondfeuer", + ["Improved Nature's Grasp"] = "Verbesserter Griff der Natur", + ["Improved Overpower"] = "Verbessertes \195\156berw\195\164ltigen", + ["Improved Power Word: Fortitude"] = "Verbessertes Machtwort: Seelenst\195\164rke", + ["Improved Power Word: Shield"] = "Verbessertes Machtwort: Schild", + ["Improved Prayer of Healing"] = "Verbessertes Gebet der Heilung", + ["Improved Psychic Scream"] = "Verbesserter Psychischer Schrei", + ["Improved Pummel"] = "Verbessertes Zuschlagen", + ["Improved Regrowth"] = "Verbessertes Nachwachsen", + ["Improved Reincarnation"] = "Verbesserte Reinkarnation", + ["Improved Rejuvenation"] = "Verbesserte Verj\195\188ngung", + ["Improved Rend"] = "Verbessertes Verwunden", + ["Improved Renew"] = "Verbesserte Erneuerung", + ["Improved Retribution Aura"] = "Verbesserte Aura der Vergeltung", + ["Improved Revenge"] = "Verbesserte Rache", + ["Improved Revive Pet"] = "Verbessertes Tier wiederbeleben", + ["Improved Righteous Fury"] = "Verbesserter Zorn der Gerechtigkeit", + ["Improved Rockbiter Weapon"] = "Verbesserte Felsbei\195\159erwaffe", + ["Improved Rupture"] = "Verbesserte Blutung", + ["Improved Sap"] = "Verbesserte Kopfnuss", + ["Improved Scorch"] = "Verbessertes Versengen", + ["Improved Scorpid Sting"] = "Verbesserter Skorpidstich", + ["Improved Seal of Righteousness"] = "Verbessertes Siegel der Rechtschaffenheit", + ["Improved Seal of the Crusader"] = "Verbessertes Siegel des Kreuzfahrers", + ["Improved Searing Pain"] = "Verbesserter Sengender Schmerz", + ["Improved Searing Totem"] = "Verbessertes Totem der Verbrennung", + ["Improved Serpent Sting"] = "Verbesserter Schlangenbiss", + ["Improved Shadow Bolt"] = "Verbesserter Schattenblitz", + ["Improved Shadow Word: Pain"] = "Verbessertes Schattenwort: Schmerz", + ["Improved Shield Bash"] = "Verbesserter Schildhieb", + ["Improved Shield Block"] = "Verbesserter Schildblock", + ["Improved Shield Wall"] = "Verbesserter Schildwall", + ["Improved Shred"] = "Verbessertes Schreddern", + ["Improved Sinister Strike"] = "Verbesserter Finsterer Sto\195\159", + ["Improved Slam"] = "Verbessertes Zerschmettern", + ["Improved Slice and Dice"] = "Verbessertes Zerh\195\164ckseln", + ["Improved Spellstone"] = "Verbesserter Zauberstein", + ["Improved Sprint"] = "Verbessertes Sprinten", + ["Improved Starfire"] = "Verbessertes Sternenfeuer", + ["Improved Stoneclaw Totem"] = "Verbessertes Totem der Steinklaue", + ["Improved Stoneskin Totem"] = "Verbessertes Totem der Steinhaut", + ["Improved Strength of Earth Totem"] = "Verbessertes Totem der Erdst\195\164rke", + ["Improved Succubus"] = "Verbesserter Sukkubus", + ["Improved Sunder Armor"] = "Verbessertes R\195\188stung zerrei\195\159en", + ["Improved Taunt"] = "Verbesserter Spott", + ["Improved Thorns"] = "Verbesserte Dornen", + ["Improved Thunder Clap"] = "Verbesserter Donnerknall", + ["Improved Tranquility"] = "Verbesserte Gelassenheit", + ["Improved Vampiric Embrace"] = "Verbesserte Vampirumarmung", + ["Improved Vanish"] = "Verbessertes Verschwinden", + ["Improved Voidwalker"] = "Verbesserter Leerwandler", + ["Improved Windfury Weapon"] = "Verbesserte Waffe des Windfurors", + ["Improved Wing Clip"] = "Verbessertes Zurechtstutzen", + ["Improved Wrath"] = "Verbesserter Zorn", + ["Incinerate"] = "Verbrennen", + ["Inferno"] = "Inferno", + ["Initiative"] = "Initiative", + ["Inner Fire"] = "Inneres Feuer", + ["Inner Focus"] = "Innerer Fokus", + ["Innervate"] = "Anregen", + ["Insect Swarm"] = "Insektenschwarm", + ["Inspiration"] = "Inspiration", + ["Instant Poison II"] = "Sofort wirkendes Gift II", + ["Instant Poison III"] = "Sofort wirkendes Gift III", + ["Instant Poison IV"] = "Sofort wirkendes Gift IV", + ["Instant Poison V"] = "Sofort wirkendes Gift V", + ["Instant Poison VI"] = "Sofort wirkendes Gift VI", + ["Instant Poison"] = "Sofort wirkendes Gift", + ["Intensity"] = "Intensit\195\164t", + ["Intercept"] = "Abfangen", + ["Intercept Stun"] = "Betubung abfangen", +-- ["Intervene"] = true, + ["Intimidating Shout"] = "Drohruf", + ["Intimidation"] = "Einsch\195\188chterung", +-- ["Invisibility"] = true, + ["Iron Will"] = "Eiserner Wille", + ["Judgement of Command"] = "Richturteil des Befehls", + ["Judgement of Justice"] = "Richturteil der Gerechtigkeit", + ["Judgement of Light"] = "Richturteil des Lichts", + ["Judgement of Righteousness"] = "Richturteil der Rechtschaffenheit", + ["Judgement of Wisdom"] = "Richturteil der Weisheit", + ["Judgement of the Crusader"] = "Richturteil des Kreuzfahrers", + ["Judgement"] = "Richturteil", + ["Kick"] = "Tritt", + ["Kick - Silenced"] = "Tritt - zum Schweigen gebracht", + ["Kidney Shot"] = "Nierenhieb", +-- ["Kill Command"] = true, + ["Killer Instinct"] = "T\195\182tungstrieb", + ["Kodo Riding"] = "Kodoreiten", +-- ["Lacerate"] = true, + ["Lash of Pain"] = "Schmerzenspeitsche", + ["Last Stand"] = "Letztes Gefecht", + ["Lasting Judgement"] = "Dauerhaftes Richturteil", + ["Lay on Hands"] = "Handauflegung", + ["Leader of the Pack"] = "Rudelf\195\188hrer", + ["Leather"] = "Leder", + ["Leatherworking"] = "Lederverarbeitung", + ["Lesser Heal"] = "Geringes Heilen", + ["Lesser Healing Wave"] = "Geringe Welle der Heilung", + ["Lesser Invisibility"] = "Geringe Unsichtbarkeit", + ["Lethal Shots"] = "T\195\182dliche Sch\195\188sse", + ["Lethality"] = "T\195\182dlichkeit", + ["Levitate"] = "Levitieren", + ["Libram"] = "Buchband", +-- ["Lifebloom"] = true, + ["Life Tap"] = "Aderlass", + ["Lifegiving Gem"] = "Lebensspendender Edelstein", + ["Lightning Bolt"] = "Blitzschlag", + ["Lightning Breath"] = "Blitzschlagatem", + ["Lightning Mastery"] = "Blitzschlagbeherrschung", + ["Lightning Reflexes"] = "Blitzartige Reflexe", + ["Lightning Shield"] = "Blitzschlagschild", + ["Lightwell Renew"] = "Erneuerung des Lichtbrunnens", + ["Lightwell"] = "Brunnen des Lichts", + ["Lockpicking"] = "Schlossknacken", + ["Long Daze"] = "Lange Benommenheit", + ["Mace Specialization"] = "Streitkolben-Spezialisierung", + ["Mace Stun Effect"] = "Streitkolbenbet\195\164ubung-Effekt", + ["Mage Armor"] = "Magische R\195\188stung", + ["Magma Totem"] = "Totem der gl\195\188henden Magma", + ["Mail"] = "Panzer", +-- ["Maim"] = true, + ["Malice"] = "T\195\188cke", + ["Mana Burn"] = "Manabrand", + ["Mana Shield"] = "Manaschild", + ["Mana Spring Totem"] = "Totem der Manaquelle", + ["Mana Tide Totem"] = "Totem der Manaflut", + ["Mangle"] = "Fleddern", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = "Mal der Wildnis", + ["Martyrdom"] = "M\195\164rtyrertum", +-- ["Mass Dispel"] = true, + ["Master Demonologist"] = "Meister der D\195\164monologie", + ["Master Summoner"] = "Meister der Beschw\195\182rung", + ["Master of Deception"] = "Meister der T\195\164uschung", + ["Maul"] = "Zermalmen", + ["Mechanostrider Piloting"] = "Roboschreiter-Lenken", + ["Meditation"] = "Meditation", + ["Melee Specialization"] = "Nahkampf-Spezialisierung", + ["Mend Pet"] = "Tier heilen", + ["Mental Agility"] = "Mentale Beweglichkeit", + ["Mental Strength"] = "Mentale St\195\164rke", + ["Mind Blast"] = "Gedankenschlag", + ["Mind Control"] = "Gedankenkontrolle", + ["Mind Flay"] = "Gedankenschinden", + ["Mind Soothe"] = "Gedankenbes\195\164nftigung", + ["Mind Vision"] = "Gedankensicht", + ["Mind-numbing Poison II"] = "Gedankenbenebelndes Gift II", + ["Mind-numbing Poison III"] = "Gedankenbenebelndes Gift III", + ["Mind-numbing Poison"] = "Gedankenbenebelndes Gift", + ["Mining"] = "Bergbau", +-- ["Misdirection"] = true, + ["Mocking Blow"] = "Sp\195\182ttischer Schlag", +-- ["Molten Armor"] = true, + ["Mongoose Bite"] = "Mungobiss", + ["Monster Slaying"] = "Monstert\195\182ten", + ["Moonfire"] = "Mondfeuer", + ["Moonfury"] = "Mondfuror", + ["Moonglow"] = "Mondschein", + ["Moonkin Aura"] = "Aura des Moonkin", + ["Moonkin Form"] = "Moonkingestalt", + ["Mortal Shots"] = "Todbringende Sch\195\188sse", + ["Mortal Strike"] = "T\195\182dlicher Sto\195\159", + ["Multi-Shot"] = "Mehrfachschuss", + ["Murder"] = "Mord", +-- ["Mutilate"] = true, + ["Natural Armor"] = "Nat\195\188rliche R\195\188stung", + ["Natural Shapeshifter"] = "Schnellwandlung", + ["Natural Weapons"] = "Waffenbalance", + ["Nature Resistance Totem"] = "Totem des Naturwiderstands", + ["Nature Resistance"] = "Naturwiderstand", + ["Nature's Focus"] = "Naturfokus", + ["Nature's Grace"] = "Anmut der Natur", + ["Nature's Grasp"] = "Griff der Natur", + ["Nature's Reach"] = "Reichweite der Natur", + ["Nature's Swiftness"] = "Schnelligkeit der Natur", + ["Nightfall"] = "Einbruch der Nacht", + ["Omen of Clarity"] = "Omen der Klarsicht", + ["One-Handed Axes"] = "Einhand\195\164xte", + ["One-Handed Maces"] = "Einhandstreitkolben", + ["One-Handed Swords"] = "Einhandschwerter", + ["One-Handed Weapon Specialization"] = "Einhandwaffen-Spezialisierung", + ["Opening - No Text"] = "\195\150ffnen - Kein Text", + ["Opening"] = "\195\150ffnen", + ["Opportunity"] = "G\195\188nstige Gelegenheit", + ["Overpower"] = "\195\156berw\195\164ltigen", +-- ["Pain Suppression"] = true, + ["Paranoia"] = "Paranoia", + ["Parry"] = "Parieren", + ["Pathfinding"] = "Orientierung", + ["Perception"] = "Wachsamkeit", + ["Permafrost"] = "Dauerfrost", + ["Pet Aggression"] = "Tieraggression", + ["Pet Hardiness"] = "Tier-Widerstandskraft", + ["Pet Recovery"] = "Tiererholung", + ["Pet Resistance"] = "Tier-Widerstand", + ["Phase Shift"] = "Phasenverschiebung", + ["Pick Lock"] = "Schloss knacken", + ["Pick Pocket"] = "Taschendiebstahl", + ["Piercing Howl"] = "Durchdringendes Heulen", + ["Piercing Ice"] = "Stechendes Eis", + ["Plate Mail"] = "Plattenpanzer", + ["Poison Cleansing Totem"] = "Totem der Giftreinigung", + ["Poisons"] = "Gifte", + ["Polearm Specialization"] = "Stangenwaffen-Spezialisierung", + ["Polearms"] = "Stangenwaffen", + ["Polymorph"] = "Verwandlung", + ["Polymorph: Pig"] = "Verwandlung: Schwein", + ["Polymorph: Turtle"] = "Verwandlung: Schildkr\195\182te", + ["Portal: Darnassus"] = "Portal: Darnassus", + ["Portal: Ironforge"] = "Portal: Ironforge", + ["Portal: Orgrimmar"] = "Portal: Orgrimmar", + ["Portal: Stormwind"] = "Portal: Stormwind", + ["Portal: Thunder Bluff"] = "Portal: Thunder Bluff", + ["Portal: Undercity"] = "Portal: Undercity", + ["Pounce Bleed"] = "Anspringblutung", + ["Pounce"] = "Anspringen", + ["Power Infusion"] = "Seele der Macht", + ["Power Word: Fortitude"] = "Machtwort: Seelenst\195\164rke", + ["Power Word: Shield"] = "Machtwort: Schild", + ["Prayer of Fortitude"] = "Gebet der Seelenst\195\164rke", + ["Prayer of Healing"] = "Gebet der Heilung", +-- ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"] = "Gebet des Schattenschutzes", + ["Prayer of Spirit"] = "Gebet der Willenskraft", + ["Precision"] = "Pr\195\164zision", + ["Predatory Strikes"] = "Raubtierschl\195\164ge", + ["Premeditation"] = "Konzentration", + ["Preparation"] = "Vorbereitung", + ["Presence of Mind"] = "Geistesgegenwart", + ["Primal Fury"] = "Urfuror", + ["Prowl"] = "Schleichen", + ["Psychic Scream"] = "Psychischer Schrei", + ["Pummel"] = "Zuschlagen", + ["Purge"] = "Reinigen", + ["Purification"] = "L\195\164uterung", + ["Purify"] = "L\195\164utern", + ["Pursuit of Justice"] = "Streben nach Gerechtigkeit", + ["Pyroblast"] = "Pyroschlag", + ["Pyroclasm"] = "Feuerschwall", + ["Quick Shots"] = "Schnelle Schรƒยผsse", + ["Quickness"] = "Schnelligkeit", + ["Rain of Fire"] = "Feuerregen", + ["Rake"] = "Krallenhieb", +-- ["Rampage"] = true, + ["Ram Riding"] = "Widderreiten", + ["Ranged Weapon Specialization"] = "Distanzwaffen-Spezialisierung", + ["Rapid Concealment"] = "Schnelles Verstecken", + ["Rapid Fire"] = "Schnellfeuer", + ["Raptor Riding"] = "Raptorreiten", + ["Raptor Strike"] = "Raptorsto\195\159", + ["Ravage"] = "Verheeren", + ["Readiness"] = "Bereitschaft", + ["Rebirth"] = "Wiedergeburt", + ["Reckless Charge"] = "Tollk?nes St?men", + ["Recklessness"] = "Tollk\195\188hnheit", + ["Reckoning"] = "Abrechnung", + ["Redemption"] = "Erl\195\182sung", + ["Redoubt"] = "Verschanzen", + ["Reflection"] = "Reflexion", + ["Regeneration"] = "Regeneration", + ["Regrowth"] = "Nachwachsen", + ["Reincarnation"] = "Reinkarnation", + ["Rejuvenation"] = "Verj\195\188ngung", + ["Relentless Strikes"] = "Unerbittliche St\195\182\195\159e", + ["Remorseless"] = "Gnadenlos", + ["Remorseless Attacks"] = "Gnadenlose Angriffe", + ["Remove Curse"] = "Fluch aufheben", + ["Remove Insignia"] = "Abzeichen entfernen", + ["Remove Lesser Curse"] = "Geringen Fluch aufheben", + ["Rend"] = "Verwunden", + ["Renew"] = "Erneuerung", + ["Repentance"] = "Bu\195\159e", + ["Resurrection"] = "Auferstehung", + ["Retaliation"] = "Gegenschlag", + ["Retribution Aura"] = "Aura der Vergeltung", + ["Revenge Stun"] = "Rachebet\195\164ubung", + ["Revenge"] = "Rache", + ["Reverberation"] = "Nachklingen", + ["Revive Pet"] = "Tier wiederbeleben", +-- ["Righteous Defense"] = true, + ["Righteous Fury"] = "Zorn der Gerechtigkeit", + ["Rip"] = "Zerfetzen", + ["Riposte"] = "Riposte", + ["Ritual of Doom Effect"] = "Ritual der Verdammnis'-Effekt", + ["Ritual of Doom"] = "Ritual der Verdammnis", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = "Ritual der Beschw\195\182rung", + ["Rockbiter Weapon"] = "Felsbei\195\159erwaffe", + ["Rogue Passive"] = "Schurke Passiv", + ["Ruin"] = "Verderben", + ["Rupture"] = "Blutung", + ["Ruthlessness"] = "Skrupellosigkeit", + ["Sacrifice"] = "Opferung", + ["Safe Fall"] = "Sicheres Fallen", + ["Sanctity Aura"] = "Aura der Heiligkeit", + ["Sap"] = "Kopfnuss", + ["Savage Fury"] = "Ungez\195\164hmte Wut", + ["Savage Strikes"] = "Wilde Schl\195\164ge", + ["Scare Beast"] = "Wildtier \195\164ngstigen", + ["Scatter Shot"] = "Streuschuss", + ["Scorch"] = "Versengen", + ["Scorpid Poison"] = "Skorpidgift", + ["Scorpid Sting"] = "Skorpidstich", + ["Screech"] = "Schrei", + ["Seal Fate"] = "Schicksal besiegeln", +-- ["Seal of Blood"] = true, + ["Seal of Command"] = "Siegel des Befehls", + ["Seal of Justice"] = "Siegel der Gerechtigkeit", + ["Seal of Light"] = "Siegel des Lichts", + ["Seal of Righteousness"] = "Siegel der Rechtschaffenheit", + ["Seal of Wisdom"] = "Siegel der Weisheit", + ["Seal of the Crusader"] = "Siegel des Kreuzfahrers", +-- ["Seal of Vengeance"] = true, + ["Searing Light"] = "Sengendes Licht", + ["Searing Pain"] = "Sengender Schmerz", + ["Searing Totem"] = "Totem der Verbrennung", +-- ["Second Wind"] = true, + ["Seduction"] = "Verf\195\188hrung", +-- ["Seed of Corruption"] = true, + ["Sense Demons"] = "D\195\164monen sp\195\188ren", + ["Sense Undead"] = "Untote sp\195\188ren", + ["Sentry Totem"] = "Totem des Wachens", + ["Serpent Sting"] = "Schlangenbiss", + ["Setup"] = "Reinlegen", + ["Shackle Undead"] = "Untote fesseln", + ["Shadow Affinity"] = "Schattenaffinit\195\164t", + ["Shadow Bolt"] = "Schattenblitz", + ["Shadow Focus"] = "Schattenfokus", + ["Shadow Mastery"] = "Schattenbeherrschung", + ["Shadow Protection"] = "Schattenschutz", + ["Shadow Reach"] = "Schattenreichweite", + ["Shadow Resistance Aura"] = "Aura des Schattenwiderstands", + ["Shadow Resistance"] = "Schattenwiderstand", + ["Shadow Trance"] = "Schattentrance", + ["Shadow Vulnerability"] = "Schattenverwundbarkeit", + ["Shadow Ward"] = "Schattenzauberschutz", + ["Shadow Weaving"] = "Schattenwirken", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = "Schattenwort: Schmerz", + ["Shadowburn"] = "Schattenbrand", +-- ["Shadowfiend"] = true, + ["Shadowform"] = "Schattengestalt", +-- ["Shadowfury"] = true, + ["Shadowguard"] = "Schattenschild", + ["Shadowmeld Passive"] = "Schattenmimik Passiv", + ["Shadowmeld"] = "Schattenhaftigkeit", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = "Gesch\195\164rfte Klauen", + ["Shatter"] = "Zertr\195\188mmern", + ["Shell Shield"] = "Panzerschild", + ["Shield Bash"] = "Schildhieb", + ["Shield Bash - Silenced"] = "Schildhieb - zum Schweigen gebracht", + ["Shield Block"] = "Schildblock", + ["Shield Slam"] = "Schildschlag", + ["Shield Specialization"] = "Schild-Spezialisierung", + ["Shield Wall"] = "Schildwall", + ["Shield"] = "Schild", +-- ["Shiv"] = true, + ["Shoot Bow"] = "Bogenschuss", + ["Shoot Crossbow"] = "Armbrust abschie\195\159en", + ["Shoot Gun"] = "Schusswaffe abfeuern", + ["Shoot"] = "Schie\195\159en", + ["Shred"] = "Schreddern", + ["Silence"] = "Stille", +-- ["Silencing Shot"] = true, + ["Silent Resolve"] = "Schweigsame Entschlossenheit", + ["Sinister Strike"] = "Finsterer Sto\195\159", + ["Siphon Life"] = "Lebensentzug", + ["Skinning"] = "K\195\188rschnerei", + ["Slam"] = "Zerschmettern", + ["Sleep"] = "Schlaf", + ["Slice and Dice"] = "Zerh\195\164ckseln", +-- ["Slow"] = true, + ["Slow Fall"] = "Langsamer Fall", + ["Smelting"] = "Verh\195\188ttung", + ["Smite"] = "G\195\182ttliche Pein", +-- ["Snake Trap"] = true, +-- ["Solid Sharpening Stone"] = true, + ["Soothe Animal"] = "Tier bes\195\164nftigen", + ["Soothing Kiss"] = "Bes\195\164nftigender Kuss", + ["Soul Fire"] = "Seelenfeuer", + ["Soul Link"] = "Seelenverbindung", + ["Soul Siphon"] = "Seelen-Siphon", +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"] = "Seelenstein-Auferstehung", + ["Spell Lock"] = "Zaubersperre", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"] = "Zauberschutz", + ["Spirit Bond"] = "Geistbande", + ["Spirit Tap"] = "Willensentzug", + ["Spirit of Redemption"] = "Geist der Erl\195\182sung", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = "Spiritueller Fokus", + ["Spiritual Guidance"] = "Geistige F\195\188hrung", + ["Spiritual Healing"] = "Spirituelle Heilung", + ["Sprint"] = "Sprinten", +-- ["Stance Mastery"] = true, + ["Starfire"] = "Sternenfeuer", + ["Starfire Stun"] = "Sternenfeuer-Betubung", + ["Starshards"] = "Sternensplitter", + ["Staves"] = "St\195\164be", +-- ["Steady Shot"] = true, + ["Stealth"] = "Verstohlenheit", + ["Stoneclaw Totem"] = "Totem der Steinklaue", + ["Stoneform"] = "Steingestalt", + ["Stoneskin Totem"] = "Totem der Steinhaut", + ["Stormstrike"] = "Sturmschlag", + ["Strength of Earth Totem"] = "Totem der Erdst\195\164rke", + ["Stuck"] = "Feststecken", + ["Subtlety"] = "Feingef\195\188hl", + ["Suffering"] = "Leiden", + ["Summon Charger"] = "Streitross beschw\195\182ren", + ["Summon Dreadsteed"] = "Schreckensross herbeirufen", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"] = "Teufelsj\195\164ger beschw\195\182ren", + ["Summon Felsteed"] = "Teufelsross beschw\195\182ren", + ["Summon Imp"] = "Wichtel beschw\195\182ren", + ["Summon Succubus"] = "Sukkubus beschw\195\182ren", + ["Summon Voidwalker"] = "Leerwandler beschw\195\182ren", + ["Summon Warhorse"] = "Schlachtross beschw\195\182ren", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"] = "R\195\188stung zerrei\195\159en", + ["Suppression"] = "Unterdr\195\188ckung", + ["Surefooted"] = "Sicherer Stand", + ["Survivalist"] = "\195\156berlebensk\195\188nstler", + ["Sweeping Strikes"] = "Weitreichende St\195\182\195\159e", +-- ["Swiftmend"] = true, + ["Swipe"] = "Prankenhieb", + ["Sword Specialization"] = "Schwert-Spezialisierung", + ["Tactical Mastery"] = "Taktiker", + ["Tainted Blood"] = "Besudeltes Blut", + ["Tailoring"] = "Schneiderei", + ["Tame Beast"] = "Wildtier z\195\164hmen", + ["Tamed Pet Passive"] = "Gez\195\164hmtes Tier - Passiv", + ["Taunt"] = "Spott", + ["Teleport: Darnassus"] = "Teleportieren: Darnassus", + ["Teleport: Ironforge"] = "Teleportieren: Ironforge", + ["Teleport: Moonglade"] = "Teleportieren: Moonglade", + ["Teleport: Orgrimmar"] = "Teleportieren: Orgrimmar", + ["Teleport: Stormwind"] = "Teleportieren: Stormwind", + ["Teleport: Thunder Bluff"] = "Teleportieren: Thunder Bluff", + ["Teleport: Undercity"] = "Teleportieren: Undercity", +-- ["The Beast Within"] = true, + ["The Human Spirit"] = "Unbeugsamkeit", + ["Thick Hide"] = "Dickes Fell", + ["Thorns"] = "Dornen", + ["Throw"] = "Werfen", + ["Throwing Specialization"] = "Wurfwaffen-Spezialisierung", + ["Throwing Weapon Specialization"] = "Wurfwaffen-Spezialisierung", + ["Thrown"] = "Wurfwaffe", + ["Thunder Clap"] = "Donnerknall", + ["Thundering Strikes"] = "Donnernde St\195\182\195\159e", + ["Thunderstomp"] = "Donnerstampfer", + ["Tidal Focus"] = "Gezeitenfokus", + ["Tidal Mastery"] = "Gezeitenbeherrschung", + ["Tiger Riding"] = "Tigerreiten", + ["Tiger's Fury"] = "Tigerfuror", + ["Torment"] = "Qual", + ["Totem"] = "Totem", + ["Totem of Wrath"] = "Totem des Ingrimms", + ["Totemic Focus"] = "Totemfokus", + ["Touch of Weakness"] = "Ber\195\188hrung der Schw\195\164che", + ["Toughness"] = "Z\195\164higkeit", + ["Track Beasts"] = "Wildtiere aufsp\195\188ren", + ["Track Demons"] = "D\195\164monen aufsp\195\188ren", + ["Track Dragonkin"] = "Drachkin aufsp\195\188ren", + ["Track Elementals"] = "Elementare aufsp\195\188ren", + ["Track Giants"] = "Riesen aufsp\195\188ren", + ["Track Hidden"] = "Verborgenes aufsp\195\188ren", + ["Track Humanoids"] = "Humanoide aufsp\195\188ren", + ["Track Undead"] = "Untote aufsp\195\188ren", + ["Tranquil Air Totem"] = "Totem der beruhigenden Winde", + ["Tranquil Spirit"] = "Gelassener Geist", + ["Tranquility"] = "Gelassenheit", + ["Tranquilizing Shot"] = "Einlullender Schuss", + ["Trap Mastery"] = "Fallenbeherrschung", + ["Travel Form"] = "Reisegestalt", +-- ["Tree of Life"] = true, + ["Tremor Totem"] = "Totem des Erdsto\195\159es", + ["Tribal Leatherworking"] = "Stammeslederverarbeitung", + ["Trueshot Aura"] = "Aura des Volltreffers", + ["Turn Undead"] = "Untote vertreiben", + ["Two-Handed Axes and Maces"] = "Zweihand\195\164xte und -Streitkolben", + ["Two-Handed Axes"] = "Zweihand\195\164xte", + ["Two-Handed Maces"] = "Zweihandstreitkolben", + ["Two-Handed Swords"] = "Zweihandschwerter", + ["Two-Handed Weapon Specialization"] = "Zweihandwaffen-Spezialisierung", + ["Unarmed"] = "Unbewaffnet", + ["Unbreakable Will"] = "Unbezwingbarer Wille", + ["Unbridled Wrath Effect"] = "Entfesselter Zorn'-Effekt", + ["Unbridled Wrath"] = "Entfesselter Zorn", + ["Undead Horsemanship"] = "Untotenreitkunst", + ["Underwater Breathing"] = "Unterwasseratmung", + ["Unending Breath"] = "Unendlicher Atem", + ["Unholy Power"] = "Unheilige Macht", + ["Unleashed Fury"] = "Entfesselter Zorn", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"] = "Unumst\195\182\195\159licher Glaube", + ["Vampiric Embrace"] = "Vampirumarmung", + ["Vanish"] = "Verschwinden", + ["Vanished"] = "Verschwunden", +-- ["Vampiric Touch"] = true, + ["Vengeance"] = "Rache", +-- ["Victory Rush"] = true, + ["Vigor"] = "Lebenskraft", + ["Vile Poisons"] = "\195\156ble Gifte", + ["Vindication"] = "Rechtschaffene Schw\195\164chung", + ["Viper Sting"] = "Vipernbiss", + ["Volley"] = "Salve", + ["Wand Specialization"] = "Zauberstab-Spezialisierung", + ["Wands"] = "Zauberst\195\164be", + ["War Stomp"] = "Kriegsdonner", + ["Water Breathing"] = "Wasseratmung", +-- ["Water Shield"] = true, + ["Water Walking"] = "Wasserwandeln", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "Geschwรƒยคchte Seele", + ["Weaponsmith"] = "Waffenschmied", + ["Whirlwind"] = "Wirbelwind", + ["Will of the Forsaken"] = "Wille der Verlassenen", + ["Windfury Totem"] = "Totem des Windzorns", + ["Windfury Weapon"] = "Waffe des Windfurors", + ["Windwall Totem"] = "Totem der Windmauer", + ["Wing Clip"] = "Zurechtstutzen", + ["Winter's Chill"] = "Winterk\195\164lte", + ["Wisp Spirit"] = "Irrwisch-Geist", + ["Wolf Riding"] = "Wolfreiten", + ["Wound Poison II"] = "Wundgift II", + ["Wound Poison III"] = "Wundgift III", + ["Wound Poison IV"] = "Wundgift IV", + ["Wound Poison"] = "Wundgift", + ["Wrath"] = "Zorn", + ["Wrath of Air Totem"] = "Totem des st\195\188rmischen Zorns", + ["Wyvern Sting"] = "Stich des Fl\195\188geldrachen", + } +end) + +BabbleSpell:RegisterTranslations("frFR", function() + return { + ["Abolish Disease"] = "Abolir maladie", + ["Abolish Poison Effect"] = "Effet Abolir le poison", + ["Abolish Poison"] = "Abolir le poison", + ["Activate MG Turret"] = "Activation de la tourelle de mitrailleuse", + ["Adrenaline Rush"] = "Pouss\195\169e d'adr\195\169naline", + ["Aftermath"] = "Cons\195\169quences", + ["Aggression"] = "Agressivit\195\169", + ["Aimed Shot"] = "Vis\195\169e", + ["Alchemy"] = "Alchimie", + ["Ambush"] = "Embuscade", + ["Amplify Curse"] = "Mal\195\169diction amplifi\195\169e", + ["Amplify Magic"] = "Amplification de la magie", + ["Ancestral Fortitude"] = "Robustesse des anciens", + ["Ancestral Healing"] = "Gu\195\169rison des anciens", + ["Ancestral Knowledge"] = "Connaissance ancestrale", + ["Ancestral Spirit"] = "Esprit ancestral", +-- ["Anesthetic Poison"] = true, + ["Anger Management"] = "Ma\195\174trise de la Rage", +-- ["Anguish"] = true, + ["Anticipation"] = "Anticipation", + ["Aquatic Form"] = "Forme aquatique", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"] = "Illumination des arcanes", + ["Arcane Concentration"] = "Concentration des arcanes", + ["Arcane Explosion"] = "Explosion des arcanes", + ["Arcane Focus"] = "Focalisation des arcanes", + ["Arcane Instability"] = "Instabilit\195\169 des arcanes", + ["Arcane Intellect"] = "Intelligence des arcanes", + ["Arcane Meditation"] = "M\195\169ditation des arcanes", + ["Arcane Mind"] = "Esprit des arcanes", + ["Arcane Missiles"] = "Projectiles des arcanes", + ["Arcane Power"] = "Pouvoir des arcanes", + ["Arcane Resistance"] = "R\195\169sistance aux Arcanes", + ["Arcane Shot"] = "Tir des arcanes", + ["Arcane Subtlety"] = "Subtilit\195\169 des arcanes", + ["Arctic Reach"] = "Allonge arctique", + ["Armorsmith"] = "Fabricant d'armures", + ["Aspect of the Beast"] = "Aspect de la b\195\170te", + ["Aspect of the Cheetah"] = "Aspect du gu\195\169pard", + ["Aspect of the Hawk"] = "Aspect du faucon", + ["Aspect of the Monkey"] = "Aspect du singe", + ["Aspect of the Pack"] = "Aspect de la meute", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = "Aspect de la nature", + ["Astral Recall"] = "Rappel astral", + ["Attack"] = "Attaque", + ["Attacking"] = "Attaque", + ["Auto Shot"] = "Tir automatique", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"] = "Sp\195\169cialisation Hache", +-- ["Backlash"] = true, + ["Backstab"] = "Attaque sournoise", + ["Bane"] = "Fl\195\169au", + ["Banish"] = "Bannir", + ["Barkskin Effect"] = "Effet Ecorce", + ["Barkskin"] = "Ecorce", + ["Barrage"] = "Barrage", + ["Bash"] = "Sonner", + ["Basic Campfire"] = "Feu de camp basique", + ["Battle Shout"] = "Cri de guerre", + ["Battle Stance Passive"] = "Posture de combat", + ["Battle Stance"] = "Posture de combat", + ["Bear Form"] = "Forme d'ours", + ["Beast Lore"] = "Connaissance des b\195\170tes", + ["Beast Slaying"] = "Tueur de b\195\170tes", + ["Beast Training"] = "Apprivoisement", + ["Benediction"] = "B\195\169n\195\169diction", + ["Berserker Rage"] = "Rage berserker", + ["Berserker Stance Passive"] = "Posture berserker", + ["Berserker Stance"] = "Posture berserker", + ["Berserking"] = "Berserker", + ["Bestial Discipline"] = "Discipline bestiale", + ["Bestial Swiftness"] = "Rapidit\195\169 bestiale", + ["Bestial Wrath"] = "Courroux bestial", +-- ["Binding Heal"] = true, + ["Bite"] = "Morsure", + ["Black Arrow"] = "Fl\195\168che noire", + ["Blackout"] = "Aveuglement", + ["Blacksmithing"] = "Forge", + ["Blade Flurry"] = "D\195\169luge de lames", + ["Blast Wave"] = "Vague explosive", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"] = "R\195\169tablissement b\195\169ni", + ["Blessing of Freedom"] = "B\195\169n\195\169diction de libert\195\169", + ["Blessing of Kings"] = "B\195\169n\195\169diction des rois", + ["Blessing of Light"] = "B\195\169n\195\169diction de lumi\195\168re", + ["Blessing of Might"] = "B\195\169n\195\169diction de puissance", + ["Blessing of Protection"] = "B\195\169n\195\169diction de protection", + ["Blessing of Sacrifice"] = "B\195\169n\195\169diction de sacrifice", + ["Blessing of Salvation"] = "B\195\169n\195\169diction de salut", + ["Blessing of Sanctuary"] = "B\195\169n\195\169diction du sanctuaire", + ["Blessing of Wisdom"] = "B\195\169n\195\169diction de sagesse", + ["Blind"] = "C\195\169cit\195\169", + ["Blinding Powder"] = "Poudre aveuglante", + ["Blink"] = "Transfert", + ["Blizzard"] = "Blizzard", + ["Block"] = "Bloquer", + ["Blood Craze"] = "Folie sanguinaire", + ["Blood Frenzy"] = "Fr\195\169n\195\169sie sanglante", + ["Blood Fury"] = "Fureur sanguinaire", + ["Blood Pact"] = "Pacte de sang", +-- ["Bloodlust"] = true, + ["Bloodrage"] = "Rage sanguinaire", + ["Bloodthirst"] = "Sanguinaire", + ["Booming Voice"] = "Voix tonitruante", + ["Bow Specialization"] = "Sp\195\169cialisation Arc", + ["Bows"] = "Arcs", + ["Bright Campfire"] = "Feu de camp \195\169clatant", + ["Brutal Impact"] = "Impact brutal", + ["Burning Soul"] = "Ame ardente", + ["Call Pet"] = "Appel du familier", + ["Call of Flame"] = "Appel des flammes", + ["Call of Thunder"] = "Appel de la foudre", + ["Camouflage"] = "Dissimulation", + ["Cannibalize"] = "Cannibalisme", + ["Cat Form"] = "Forme de f\195\169lin", + ["Cataclysm"] = "Cataclysme", + ["Chain Heal"] = "Salve de gu\195\169rison", + ["Chain Lightning"] = "Cha\195\174ne d'\195\169clairs", + ["Challenging Roar"] = "Rugissement provocateur", + ["Challenging Shout"] = "Cri de d\195\169fi", + ["Charge Rage Bonus Effect"] = "Effet Bonus de Rage de la Charge", + ["Charge"] = "Charge", + ["Charge Stun"] = "Charge \195\169tourdissante", + ["Cheap Shot"] = "Coup bas", + ["Chilled"] = "Transi", +-- ["Circle of Healing"] = true, + ["Claw"] = "Griffe", + ["Cleanse"] = "Epuration", + ["Clearcasting"] = "Id\195\169es claires", + ["Cleave"] = "Encha\195\174nement", + ["Clever Traps"] = "Pi\195\168ges astucieux", +-- ["Cloak of Shadows"] = true, + ["Closing"] = "Fermeture", + ["Cloth"] = "Tissu", + ["Coarse Sharpening Stone"] = "Pierre \195\160 aiguiser grossi\195\168re", + ["Cobra Reflexes"] = "R\195\169flexes du cobra", + ["Cold Blood"] = "Sang froid", + ["Cold Snap"] = "Morsure de glace", + ["Combat Endurance"] = "Endurance de combat", + ["Combustion"] = "Combustion", + ["Command"] = "Commande", +-- ["Commanding Shout"] = true, + ["Concentration Aura"] = "Aura de concentration", + ["Concussion Blow"] = "Bourrasque", + ["Concussion"] = "Commotion", + ["Concussive Shot"] = "Trait de choc", + ["Cone of Cold"] = "C\195\180ne de froid", + ["Conflagrate"] = "Conflagration", + ["Conjure Food"] = "Invocation de nourriture", + ["Conjure Mana Agate"] = "Invocation d'une agate de mana", + ["Conjure Mana Citrine"] = "Invocation d'une citrine de mana", + ["Conjure Mana Jade"] = "Invocation d'une jade de mana", + ["Conjure Mana Ruby"] = "Invocation d'un rubis de mana", + ["Conjure Water"] = "Invocation d'eau", + ["Consecrated Sharpening Stone"] = "Pierre \195\160 aiguiser consacr\195\169e", + ["Consecration"] = "Cons\195\169cration", +-- ["Consume Magic"] = true, + ["Consume Shadows"] = "Consumer les ombres", + ["Convection"] = "Convection", + ["Conviction"] = "Conviction", + ["Cooking"] = "Cuisine", + ["Corruption"] = "Corruption", + ["Counterattack"] = "Contre-attaque", + ["Counterspell"] = "Contresort", + ["Counterspell - Silenced"] = "Contresort - Silencieux", + ["Cower"] = "D\195\169robade", + ["Create Firestone"] = "Cr\195\169ation de Pierre de feu", + ["Create Firestone (Major)"] = "Cr\195\169ation de Pierre de feu (Majeure)", + ["Create Firestone (Greater)"] = "Cr\195\169ation de Pierre de feu (Sup\195\169rieure)", + ["Create Firestone (Lesser)"] = "Cr\195\169ation de Pierre de feu (Inf\195\169rieure)", + ["Create Healthstone"] = "Cr\195\169ation de Pierre de soins", + ["Create Healthstone (Major)"] = "Cr\195\169ation de Pierre de soins (Majeure)", + ["Create Healthstone (Greater)"] = "Cr\195\169ation de Pierre de soins (Sup\195\169rieure)", + ["Create Healthstone (Lesser)"] = "Cr\195\169ation de Pierre de soins (Inf\195\169rieure)", + ["Create Healthstone (Minor)"] = "Cr\195\169ation de Pierre de soins (Mineure)", + ["Create Soulstone"] = "Cr\195\169ation de Pierre d'\195\162me", + ["Create Soulstone (Major)"] = "Cr\195\169ation de Pierre d'\195\162me (Majeure)", + ["Create Soulstone (Greater)"] = "Cr\195\169ation de Pierre d'\195\162me (Sup\195\169rieure)", + ["Create Soulstone (Lesser)"] = "Cr\195\169ation de Pierre d'\195\162me (Inf\195\169rieure)", + ["Create Soulstone (Minor)"] = "Cr\195\169ation de Pierre d'\195\162me (Mineure)", + ["Create Spellstone"] = "Cr\195\169ation de Pierre de sort", + ["Create Spellstone (Major)"] = "Cr\195\169ation de Pierre de sort (Majeure)", + ["Create Spellstone (Greater)"] = "Cr\195\169ation de Pierre de sort (Sup\195\169rieure)", + ["Crippling Poison II"] = "Poison affaiblissant II", + ["Crippling Poison"] = "Poison affaiblissant", + ["Critical Mass"] = "Masse critique", + ["Crossbows"] = "Arbal\195\168tes", + ["Cruelty"] = "Cruaut\195\169", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"] = "Culture", + ["Cure Disease"] = "Gu\195\169rison des maladies", + ["Cure Poison"] = "Gu\195\169rison du poison", + ["Curse of Agony"] = "Mal\195\169diction d'agonie", + ["Curse of Doom Effect"] = "Effet Mal\195\169diction funeste", + ["Curse of Doom"] = "Mal\195\169diction funeste", + ["Curse of Exhaustion"] = "Mal\195\169diction de fatigue", + ["Curse of Idiocy"] = "Mal\195\169diction d'idiotie", + ["Curse of Recklessness"] = "Mal\195\169diction de t\195\169m\195\169rit\195\169", + ["Curse of Shadow"] = "Mal\195\169diction de l'ombre", + ["Curse of Tongues"] = "Mal\195\169diction des langages", + ["Curse of Weakness"] = "Mal\195\169diction de faiblesse", + ["Curse of the Elements"] = "Mal\195\169diction des \195\169l\195\169ments", +-- ["Cyclone"] = true, + ["Dagger Specialization"] = "Sp\195\169cialisation Dague", + ["Daggers"] = "Dagues", + ["Dampen Magic"] = "Att\195\169nuation de la magie", + ["Dark Pact"] = "Pacte noir", + ["Darkness"] = "T\195\169n\195\168bres", + ["Dash"] = "C\195\169l\195\169rit\195\169", + ["Deadly Poison II"] = "Poison mortel II", + ["Deadly Poison III"] = "Poison mortel III", + ["Deadly Poison IV"] = "Poison mortel IV", + ["Deadly Poison V"] = "Poison mortel V", + ["Deadly Poison"] = "Poison mortel", +-- ["Deadly Throw"] = true, + ["Death Coil"] = "Voile mortel", + ["Death Wish"] = "Souhait mortel", + ["Deep Wounds"] = "Blessures profondes", + ["Defense"] = "D\195\169fense", + ["Defensive Stance Passive"] = "Posture d\195\169fensive", + ["Defensive Stance"] = "Posture d\195\169fensive", + ["Defensive State 2"] = "Posture d\195\169fensive 2", + ["Defensive State"] = "Posture d\195\169fensive", + ["Defiance"] = "D\195\169fi", + ["Deflection"] = "D\195\169viation", + ["Demon Armor"] = "Armure d\195\169moniaque", + ["Demon Skin"] = "Peau de d\195\169mon", + ["Demonic Embrace"] = "Baiser d\195\169moniaque", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = "Sacrifice d\195\169moniaque", + ["Demoralizing Roar"] = "Rugissement d\195\169moralisant", + ["Demoralizing Shout"] = "Cri d\195\169moralisant", + ["Dense Sharpening Stone"] = "Pierre \195\160 aiguiser dense", + ["Desperate Prayer"] = "Pri\195\168re du d\195\169sespoir", + ["Destructive Reach"] = "Allonge de destruction", + ["Detect Greater Invisibility"] = "D\195\169tection de l'invisibilit\195\169 sup\195\169rieure", + ["Detect Invisibility"] = "D\195\169tection de l'invisibilit\195\169", + ["Detect Lesser Invisibility"] = "D\195\169tection de l'invisibilit\195\169 inf\195\169rieure", + ["Detect Magic"] = "D\195\169tection de la magie", + ["Detect Traps"] = "D\195\169tection des pi\195\168ges", + ["Detect"] = "D\195\169tection", + ["Deterrence"] = "Dissuasion", +-- ["Devastate"] = true, + ["Devastation"] = "D\195\169vastation", + ["Devotion Aura"] = "Aura de d\195\169votion", + ["Devour Magic Effect"] = "Effet festin magique", + ["Devour Magic"] = "Festin magique", + ["Devouring Plague"] = "Peste d\195\169vorante", + ["Diplomacy"] = "Diplomatie", + ["Dire Bear Form"] = "Forme d'ours redoutable", + ["Disarm Trap"] = "D\195\169sarmement de pi\195\168ge", + ["Disarm"] = "D\195\169sarmement", + ["Disease Cleansing Totem"] = "Totem de Purification des maladies", + ["Disenchant"] = "D\195\169senchanter", + ["Disengage"] = "D\195\169sengagement", + ["Dismiss Pet"] = "Renvoyer le familier", + ["Dispel Magic"] = "Dissipation de la magie", + ["Distract"] = "Distraction", + ["Distracting Shot"] = "Trait provocateur", + ["Dive"] = "Plongeon", + ["Divine Favor"] = "Faveur divine", + ["Divine Fury"] = "Fureur divine", +-- ["Divine Illumination"] = true, + ["Divine Intellect"] = "Intelligence divine", + ["Divine Intervention"] = "Intervention divine", + ["Divine Protection"] = "Protection divine", + ["Divine Shield"] = "Bouclier divin", + ["Divine Spirit"] = "Esprit divin", + ["Divine Strength"] = "Force divine", + ["Dodge"] = "Esquiver", +-- ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"] = "Travail du cuir d'\195\169cailles de dragon", + ["Drain Life"] = "Drain de vie", + ["Drain Mana"] = "Drain de mana", + ["Drain Soul"] = "Siphon d'\195\162me", + ["Drink"] = "Boisson", + ["Dual Wield Specialization"] = "Sp\195\169cialisation Ambidextrie", + ["Dual Wield"] = "Ambidextrie", + ["Duel"] = "Duel", + ["Eagle Eye"] = "Oeil d'aigle", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"] = "Horion de terre", + ["Earthbind Totem"] = "Totem de lien terrestre", + ["Efficiency"] = "Efficacit\195\169", + ["Elemental Focus"] = "Focalisation \195\169l\195\169mentaire", + ["Elemental Fury"] = "Fureur \195\169l\195\169mentaire", + ["Elemental Leatherworking"] = "Travail du cuir \195\169l\195\169mentaire", + ["Elemental Mastery"] = "Ma\195\174trise \195\169l\195\169mentaire", + ["Elemental Sharpening Stone"] = "Pierre \195\160 aiguiser \195\169l\195\169mentaire", + ["Elune's Grace"] = "Gr\195\162ce d'Elune", + ["Elusiveness"] = "Insaisissable", + ["Emberstorm"] = "Temp\195\170te ardente", + ["Enamored Water Spirit"] = "Esprit de l'eau amoureux", + ["Enchanting"] = "Enchantement", + ["Endurance Training"] = "Entra\195\174nement \195\160 l'Endurance", + ["Endurance"] = "Endurance", + ["Engineering Specialization"] = "Sp\195\169cialisation", + ["Engineering"] = "Ing\195\169nieur", + ["Enrage"] = "Enrager", + ["Enriched Manna Biscuit"] = "Biscuit enrichi en manne", + ["Enslave Demon"] = "Asservir d\195\169mon", + ["Entangling Roots"] = "Sarments", + ["Entrapment"] = "Pi\195\168ge", +-- ["Envenom"] = true, + ["Escape Artist"] = "Ma\195\174tre de l'\195\169vasion", + ["Evasion"] = "Evasion", + ["Eventide"] = "Tomb\195\169e du jour", + ["Eviscerate"] = "Evisc\195\169ration", + ["Evocation"] = "Evocation", + ["Execute"] = "Ex\195\169cution", + ["Exorcism"] = "Exorcisme", + ["Expansive Mind"] = "Pens\195\169e expansive", + ["Explosive Trap Effect"] = "Effet Pi\195\168ge explosif", + ["Explosive Trap"] = "Pi\195\168ge explosif", + ["Expose Armor"] = "Exposer l'armure", + ["Eye for an Eye"] = "Oeil pour oeil", + ["Eye of Kilrogg"] = "Oeil de Kilrogg", + ["Eyes of the Beast"] = "Oeil de la b\195\170te", + ["Fade"] = "Oubli", + ["Faerie Fire"] = "Lucioles", + ["Faerie Fire (Feral)"] = "Lucioles (farouche)", + ["Far Sight"] = "Double vue", + ["Fear Ward"] = "Gardien de peur", + ["Fear"] = "Peur", + ["Feed Pet"] = "Nourrir le familier", + ["Feedback"] = "R\195\169action", + ["Feign Death"] = "Feindre la mort", + ["Feint"] = "Feinte", +-- ["Fel Armor"] = true, + ["Fel Concentration"] = "Concentration corrompue", + ["Fel Domination"] = "Domination corrompue", + ["Fel Intellect"] = "Intelligence corrompue", + ["Fel Stamina"] = "Endurance corrompue", + ["Felfire"] = "Gangrefeu", + ["Feline Grace"] = "Gr\195\162ce f\195\169line", + ["Feline Swiftness"] = "C\195\169l\195\169rit\195\169 f\195\169line", + ["Feral Aggression"] = "Agressivit\195\169 farouche", + ["Feral Charge"] = "Charge farouche", + ["Feral Instinct"] = "Instinct farouche", + ["Ferocious Bite"] = "Morsure f\195\169roce", + ["Ferocity"] = "Ferocit\195\169", + ["Fetish"] = "F\195\169tiche", + ["Find Herbs"] = "D\195\169couverte d'herbes", + ["Find Minerals"] = "D\195\169couverte de gisements", + ["Find Treasure"] = "D\195\169couverte de tr\195\169sors", + ["Fire Blast"] = "Trait de feu", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = "Totem Nova de feu", + ["Fire Power"] = "Puissance du feu", + ["Fire Resistance Aura"] = "Aura de r\195\169sistance au Feu", + ["Fire Resistance Totem"] = "Totem de r\195\169sistance au feu", + ["Fire Resistance"] = "R\195\169sistance au Feu", + ["Fire Shield"] = "Bouclier de feu", + ["Fire Vulnerability"] = "Vuln\195\169rabilit\195\169 au Feu", + ["Fire Ward"] = "Gardien de feu", + ["Fireball"] = "Boule de feu", + ["Firebolt"] = "Eclair de feu", + ["First Aid"] = "Premiers soins", + ["Fishing Poles"] = "Cannes \195\160 p\195\170che", + ["Fishing"] = "P\195\170che", + ["Fist Weapon Specialization"] = "Sp\195\169cialisation Arme de pugilat", + ["Fist Weapons"] = "Armes de pugilat", + ["Flame Shock"] = "Horion de flammes", + ["Flame Throwing"] = "Jet de flammes", + ["Flamestrike"] = "Choc de flammes", + ["Flamethrower"] = "Lance-flammes", + ["Flametongue Totem"] = "Totem Langue de feu", + ["Flametongue Weapon"] = "Arme Langue de feu", + ["Flare"] = "Fus\195\169e \195\169clairante", + ["Flash Heal"] = "Soins rapides", + ["Flash of Light"] = "Eclair lumineux", +-- ["Flight Form"] = true, + ["Flurry"] = "Rafale", + ["Focused Casting"] = "Incantation focalis\195\169e", + ["Food"] = "Nourriture", + ["Forbearance"] = "Longanimit\195\169", +-- ["Force of Nature"] = true, + ["Force of Will"] = "Force de volont\195\169", + ["Freezing Trap Effect"] = "Effet Pi?e givrant", + ["Freezing Trap"] = "Pi\195\168ge givrant", + ["Frenzied Regeneration"] = "R\195\169g\195\169n\195\169ration fr\195\169n\195\169tique", + ["Frenzy"] = "Fr\195\169n\195\169sie", + ["Frost Armor"] = "Armure de givre", + ["Frost Channeling"] = "Canalisation du givre", + ["Frost Nova"] = "Nova de givre", + ["Frost Resistance Aura"] = "Aura de r\195\169sistance au Givre", + ["Frost Resistance Totem"] = "Totem de r\195\169sistance au Givre", + ["Frost Resistance"] = "R\195\169sistance au Givre", + ["Frost Shock"] = "Horion de givre", + ["Frost Trap"] = "Pi\195\168ge de givre", + ["Frost Trap Aura"] = "Effet Pi\195\168ge de givre", + ["Frost Ward"] = "Gardien de givre", + ["Frostbite"] = "Morsure du givre", + ["Frostbolt"] = "Eclair de givre", + ["Frostbrand Weapon"] = "Arme de givre", + ["Furious Howl"] = "Hurlement furieux", + ["Furor"] = "Fureur", + ["Garrote"] = "Garrot", + ["Generic"] = "G\195\169n\195\169rique", + ["Ghost Wolf"] = "Loup fant\195\180me", + ["Ghostly Strike"] = "Frappe fantomatique", + ["Gift of Life"] = "Don de vie", + ["Gift of Nature"] = "Don de la Nature", + ["Gift of the Wild"] = "Don du fauve", + ["Gouge"] = "Suriner", + ["Grace of Air Totem"] = "Totem de Gr\195\162ce a\195\169rienne", + ["Great Stamina"] = "Endurance sup\195\169rieure", + ["Greater Blessing of Kings"] = "B\195\169n\195\169diction des rois sup\195\169rieure", + ["Greater Blessing of Light"] = "B\195\169n\195\169diction de lumi\195\168re sup\195\169rieure", + ["Greater Blessing of Might"] = "B\195\169n\195\169diction de puissance sup\195\169rieure", + ["Greater Blessing of Salvation"] = "B\195\169n\195\169diction de salut sup\195\169rieure", + ["Greater Blessing of Sanctuary"] = "B\195\169n\195\169diction du sanctuaire sup\195\169rieure", + ["Greater Blessing of Wisdom"] = "B\195\169n\195\169diction de sagesse sup\195\169rieure", + ["Greater Heal"] = "Soins sup\195\169rieurs", + ["Grim Reach"] = "Allonge sinistre", + ["Grounding Totem"] = "Totem de Gl\195\168be", + ["Grovel"] = "Ramper", + ["Growl"] = "Grondement", + ["Guardian's Favor"] = "Faveur du Gardien", + ["Gun Specialization"] = "Sp\195\169cialisation Armes \195\160 feu", + ["Guns"] = "Armes \195\160 feu", + ["Hammer of Justice"] = "Marteau de la justice", + ["Hammer of Wrath"] = "Marteau de courroux", + ["Hamstring"] = "Brise-genou", + ["Harass"] = "Harc\195\168lement", + ["Hardiness"] = "Solidit\195\169", + ["Hawk Eye"] = "Oeil de faucon", + ["Heal"] = "Soins", + ["Healing Focus"] = "Focalisation des soins", + ["Healing Light"] = "Lumi\195\168re gu\195\169risseuse", + ["Healing Stream Totem"] = "Totem gu\195\169risseur", + ["Healing Touch"] = "Toucher gu\195\169risseur", + ["Healing Wave"] = "Vague de soins", + ["Healing Way"] = "Flots de soins", + ["Health Funnel"] = "Captation de vie", + ["Heart of the Wild"] = "C\197\147ur de fauve", + ["Heavy Sharpening Stone"] = "Pierre \195\160 aiguiser lourde", + ["Hellfire Effect"] = "Effet Flammes infernales", + ["Hellfire"] = "Flammes infernales", + ["Hemorrhage"] = "H\195\169morragie", + ["Herb Gathering"] = "Cueillette", + ["Herbalism"] = "Herboristerie", + ["Heroic Strike"] = "Frappe h\195\169ro\195\175que", +-- ["Heroism"] = true, + ["Hex of Weakness"] = "Mal\195\169fice de faiblesse", + ["Hibernate"] = "Hibernation", + ["Holy Fire"] = "Flammes sacr\195\169es", + ["Holy Light"] = "Lumi\195\168re sacr\195\169e", + ["Holy Nova"] = "Nova sacr\195\169e", + ["Holy Power"] = "Puissance sacr\195\169e", + ["Holy Reach"] = "Allonge du Sacr\195\169", + ["Holy Shield"] = "Bouclier sacr\195\169", + ["Holy Shock"] = "Horion sacr\195\169", + ["Holy Specialization"] = "Sp\195\169cialisation", + ["Holy Wrath"] = "Col\195\168re divine", + ["Honorless Target"] = "Cible sans honneur", + ["Horse Riding"] = "Equitation", + ["Howl of Terror"] = "Hurlement de terreur", + ["Humanoid Slaying"] = "Tueur d'humano\195\175des", + ["Hunter's Mark"] = "Marque du chasseur", + ["Hurricane"] = "Ouragan", + ["Ice Armor"] = "Armure de glace", + ["Ice Barrier"] = "Barri\195\168re de glace", + ["Ice Block"] = "Parade de glace", +-- ["Ice Lance"] = true, + ["Ice Shards"] = "Eclats de glace", + ["Ignite"] = "Enflammer", + ["Illumination"] = "Illumination", + ["Immolate"] = "Immolation", + ["Immolation Trap Effect"] = "Effet Pi\195\168ge immolation", + ["Immolation Trap"] = "Pi\195\168ge d'Immolation", + ["Impact"] = "Impact", + ["Impale"] = "Empaler", + ["Improved Ambush"] = "Embuscade am\195\169lior\195\169e", + ["Improved Arcane Explosion"] = "Explosion des arcanes am\195\169lior\195\169e", + ["Improved Arcane Missiles"] = "Projectiles des arcanes am\195\169lior\195\169s", + ["Improved Arcane Shot"] = "Tir des arcanes am\195\169lior\195\169", + ["Improved Aspect of the Hawk"] = "Aspect du faucon am\195\169lior\195\169", + ["Improved Aspect of the Monkey"] = "Aspect du singe am\195\169lior\195\169", + ["Improved Backstab"] = "Attaque sournoise am\195\169lior\195\169e", + ["Improved Battle Shout"] = "Cri de guerre am\195\169lior\195\169", + ["Improved Berserker Rage"] = "Rage berserker am\195\169lior\195\169e", + ["Improved Blessing of Might"] = "B\195\169n\195\169diction de puissance am\195\169lior\195\169e", + ["Improved Blessing of Wisdom"] = "B\195\169n\195\169diction de sagesse am\195\169lior\195\169e", + ["Improved Blizzard"] = "Blizzard am\195\169lior\195\169", + ["Improved Bloodrage"] = "Rage sanguinaire am\195\169lior\195\169e", + ["Improved Chain Heal"] = "Salve de gu\195\169rison am\195\169lior\195\169e", + ["Improved Chain Lightning"] = "Cha\195\174ne d'\195\169clairs am\195\169lior\195\169e", + ["Improved Challenging Shout"] = "Cri de d\195\169fi am\195\169lior\195\169", + ["Improved Charge"] = "Charge am\195\169lior\195\169e", + ["Improved Cheap Shot"] = "Coup bas am\195\169lior\195\169", + ["Improved Cleave"] = "Encha\195\174nement am\195\169lior\195\169", + ["Improved Concentration Aura"] = "Aura de concentration am\195\169lior\195\169e", + ["Improved Concussive Shot"] = "Trait de choc am\195\169lior\195\169", + ["Improved Cone of Cold"] = "C\195\180ne de froid am\195\169lior\195\169", + ["Improved Corruption"] = "Corruption am\195\169lior\195\169e", + ["Improved Counterspell"] = "Contresort am\195\169lior\195\169", + ["Improved Curse of Agony"] = "Mal\195\169diction d'agonie am\195\169lior\195\169e", + ["Improved Curse of Exhaustion"] = "Mal\195\169diction de fatigue am\195\169lior\195\169e", + ["Improved Curse of Weakness"] = "Mal\195\169diction de faiblesse am\195\169lior\195\169e", + ["Improved Dampen Magic"] = "Att\195\169nuation de la magie am\195\169lior\195\169e", + ["Improved Deadly Poison"] = "Poison mortel am\195\169lior\195\169", + ["Improved Demoralizing Shout"] = "Cri d\195\169moralisant am\195\169lior\195\169", + ["Improved Devotion Aura"] = "Aura de d\195\169votion am\195\169lior\195\169e", + ["Improved Disarm"] = "D\195\169sarmement am\195\169lior\195\169", + ["Improved Distract"] = "Distraction am\195\169lior\195\169e", + ["Improved Drain Life"] = "Drain de vie am\195\169lior\195\169", + ["Improved Drain Mana"] = "Drain de mana am\195\169lior\195\169", + ["Improved Drain Soul"] = "Siphon d'\195\162me am\195\169lior\195\169", + ["Improved Enrage"] = "Enrager am\195\169lior\195\169", + ["Improved Enslave Demon"] = "Asservir d\195\169mon am\195\169lior\195\169", + ["Improved Entangling Roots"] = "Sarments am\195\169lior\195\169s", + ["Improved Evasion"] = "Evasion am\195\169lior\195\169e", + ["Improved Eviscerate"] = "Evisc\195\169ration am\195\169lior\195\169e", + ["Improved Execute"] = "Ex\195\169cution am\195\169lior\195\169e", + ["Improved Expose Armor"] = "Exposer l'armure am\195\169lior\195\169", + ["Improved Eyes of the Beast"] = "Oeil de la b\195\170te am\195\169lior\195\169", + ["Improved Fade"] = "Oubli am\195\169lior\195\169", + ["Improved Feign Death"] = "Feindre la mort am\195\169lior\195\169", + ["Improved Fire Blast"] = "Trait de feu am\195\169lior\195\169", + ["Improved Fire Nova Totem"] = "Totem Nova de feu am\195\169lior\195\169", + ["Improved Fire Ward"] = "Gardien de feu am\195\169lior\195\169", + ["Improved Fireball"] = "Boule de feu am\195\169lior\195\169e", + ["Improved Firebolt"] = "Eclair de feu am\195\169lior\195\169", + ["Improved Firestone"] = "Pierre de feu am\195\169lior\195\169e", + ["Improved Flamestrike"] = "Choc de flammes am\195\169lior\195\169", + ["Improved Flametongue Weapon"] = "Arme Langue de feu am\195\169lior\195\169e", + ["Improved Flash of Light"] = "Eclair lumineux am\195\169lior\195\169", + ["Improved Frost Nova"] = "Nova de givre am\195\169lior\195\169e", + ["Improved Frost Ward"] = "Gardien de givre am\195\169lior\195\169", + ["Improved Frostbolt"] = "Eclair de givre am\195\169lior\195\169", + ["Improved Frostbrand Weapon"] = "Arme de givre am\195\169lior\195\169e", + ["Improved Garrote"] = "Garrot am\195\169lior\195\169", + ["Improved Ghost Wolf"] = "Loup fant\195\180me am\195\169lior\195\169", + ["Improved Gouge"] = "Suriner am\195\169lior\195\169", + ["Improved Grace of Air Totem"] = "Totem de Gr\195\162ce a\195\169rienne am\195\169lior\195\169", + ["Improved Grounding Totem"] = "Totem de Gl\195\168be am\195\169lior\195\169", + ["Improved Hammer of Justice"] = "Marteau de la justice am\195\169lior\195\169", + ["Improved Hamstring"] = "Brise-genou am\195\169lior\195\169", + ["Improved Healing Stream Totem"] = "Totem gu\195\169risseur am\195\169lior\195\169", + ["Improved Healing Touch"] = "Toucher gu\195\169risseur am\195\169lior\195\169", + ["Improved Healing Wave"] = "Vague de soins am\195\169lior\195\169e", + ["Improved Healing"] = "Soin am\195\169lior\195\169", + ["Improved Health Funnel"] = "Captation de vie am\195\169lior\195\169e", + ["Improved Healthstone"] = "Pierre de soins am\195\169lior\195\169e", + ["Improved Heroic Strike"] = "Frappe h\195\169ro\195\175que am\195\169lior\195\169e", + ["Improved Hunter's Mark"] = "Marque du chasseur am\195\169lior\195\169e", + ["Improved Immolate"] = "Immolation am\195\169lior\195\169e", + ["Improved Imp"] = "Diablotin am\195\169lior\195\169", + ["Improved Inner Fire"] = "Feu int\195\169rieur am\195\169lior\195\169", + ["Improved Instant Poison"] = "Poison instantan\195\169 am\195\169lior\195\169", + ["Improved Intercept"] = "Interception am\195\169lior\195\169e", + ["Improved Intimidating Shout"] = "Cri d\226\128\153intimidation am\195\169lior\195\169", + ["Improved Judgement"] = "Jugement am\195\169lior\195\169", + ["Improved Kick"] = "Coup de pied am\195\169lior\195\169", + ["Improved Kidney Shot"] = "Aiguillon perfide am\195\169lior\195\169", + ["Improved Lash of Pain"] = "Fouet de la douleur am\195\169lior\195\169", + ["Improved Lay on Hands"] = "Imposition des mains am\195\169lior\195\169e", + ["Improved Lesser Healing Wave"] = "Vague de soins inf\195\169rieurs am\195\169lior\195\169e", + ["Improved Life Tap"] = "Connexion am\195\169lior\195\169e", + ["Improved Lightning Bolt"] = "Eclair am\195\169lior\195\169", + ["Improved Lightning Shield"] = "Bouclier de foudre am\195\169lior\195\169", + ["Improved Magma Totem"] = "Totem de Magma am\195\169lior\195\169", + ["Improved Mana Burn"] = "Br\195\187lure de mana am\195\169lior\195\169e", + ["Improved Mana Shield"] = "Bouclier de mana am\195\169lior\195\169", + ["Improved Mana Spring Totem"] = "Totem Fontaine de mana am\195\169lior\195\169", + ["Improved Mark of the Wild"] = "Marque du fauve am\195\169lior\195\169e", + ["Improved Mend Pet"] = "Gu\195\169rison du familier am\195\169lior\195\169e", + ["Improved Mind Blast"] = "Attaque mentale am\195\169lior\195\169e", + ["Improved Moonfire"] = "Eclat lunaire am\195\169lior\195\169", + ["Improved Nature's Grasp"] = "Emprise de la nature am\195\169lior\195\169e", + ["Improved Overpower"] = "Fulgurance am\195\169lior\195\169e", + ["Improved Power Word: Fortitude"] = "Mot de pouvoir : Robustesse am\195\169lior\195\169", + ["Improved Power Word: Shield"] = "Mot de pouvoir : Bouclier am\195\169lior\195\169", + ["Improved Prayer of Healing"] = "Pri\195\168re de soins am\195\169lior\195\169e", + ["Improved Psychic Scream"] = "Cri psychique am\195\169lior\195\169", + ["Improved Pummel"] = "Vol\195\169e de coups am\195\169lior\195\169e", + ["Improved Regrowth"] = "R\195\169tablissement am\195\169lior\195\169", + ["Improved Reincarnation"] = "R\195\169incarnation am\195\169lior\195\169e", + ["Improved Rejuvenation"] = "R\195\169cup\195\169ration am\195\169lior\195\169e", + ["Improved Rend"] = "Pourfendre am\195\169lior\195\169", + ["Improved Renew"] = "R\195\169novation am\195\169lior\195\169e", + ["Improved Retribution Aura"] = "Aura de vindicte am\195\169lior\195\169e", + ["Improved Revenge"] = "Vengeance am\195\169lior\195\169e", + ["Improved Revive Pet"] = "Ressusciter le familier am\195\169lior\195\169", + ["Improved Righteous Fury"] = "Fureur vertueuse am\195\169lior\195\169e", + ["Improved Rockbiter Weapon"] = "Arme Croque-roc am\195\169lior\195\169e", + ["Improved Rupture"] = "Rupture am\195\169lior\195\169e", + ["Improved Sap"] = "Assommer am\195\169lior\195\169", + ["Improved Scorch"] = "Br\195\187lure am\195\169lior\195\169e", + ["Improved Scorpid Sting"] = "Piq\195\187re de scorpide am\195\169lior\195\169e", + ["Improved Seal of Righteousness"] = "Sceau de pi\195\169t\195\169 am\195\169lior\195\169", + ["Improved Seal of the Crusader"] = "Sceau du Crois\195\169 am\195\169lior\195\169", + ["Improved Searing Pain"] = "Douleur br\195\187lante am\195\169lior\195\169e", + ["Improved Searing Totem"] = "Totem incendiaire am\195\169lior\195\169", + ["Improved Serpent Sting"] = "Morsure de serpent am\195\169lior\195\169e", + ["Improved Shadow Bolt"] = "Trait de l'ombre am\195\169lior\195\169", + ["Improved Shadow Word: Pain"] = "Mot de l'ombre : Douleur am\195\169lior\195\169", + ["Improved Shield Bash"] = "Coup de bouclier am\195\169lior\195\169", + ["Improved Shield Block"] = "Ma\195\174trise du blocage am\195\169lior\195\169e", + ["Improved Shield Wall"] = "Mur protecteur am\195\169lior\195\169", + ["Improved Shred"] = "Lambeau am\195\169lior\195\169", + ["Improved Sinister Strike"] = "Attaque pernicieuse am\195\169lior\195\169e", + ["Improved Slam"] = "Heurtoir am\195\169lior\195\169", + ["Improved Slice and Dice"] = "D\195\169biter am\195\169lior\195\169", + ["Improved Spellstone"] = "Pierre de sort am\195\169lior\195\169e", + ["Improved Sprint"] = "Sprint am\195\169lior\195\169", + ["Improved Starfire"] = "Feu stellaire am\195\169lior\195\169", + ["Improved Stoneclaw Totem"] = "Totem de Griffes de pierre am\195\169lior\195\169", + ["Improved Stoneskin Totem"] = "Totem de Peau de pierre am\195\169lior\195\169", + ["Improved Strength of Earth Totem"] = "Totem de Force de la Terre am\195\169lior\195\169", + ["Improved Succubus"] = "Succube am\195\169lior\195\169e", + ["Improved Sunder Armor"] = "Fracasser armure am\195\169lior\195\169", + ["Improved Taunt"] = "Provocation am\195\169lior\195\169e", + ["Improved Thorns"] = "Epines am\195\169lior\195\169es", + ["Improved Thunder Clap"] = "Coup de tonnerre am\195\169lior\195\169", + ["Improved Tranquility"] = "Tranquillit\195\169 am\195\169lior\195\169e", + ["Improved Vampiric Embrace"] = "Etreinte vampirique am\195\169lior\195\169e", + ["Improved Vanish"] = "Disparition am\195\169lior\195\169e", + ["Improved Voidwalker"] = "Marcheur du Vide am\195\169lior\195\169", + ["Improved Windfury Weapon"] = "Arme Furie-des-vents am\195\169lior\195\169e", + ["Improved Wing Clip"] = "Coupure d'ailes am\195\169lior\195\169e", + ["Improved Wrath"] = "Col\195\168re am\195\169lior\195\169e", + ["Incinerate"] = "Incin\195\169rer", + ["Inferno"] = "Inferno", + ["Initiative"] = "Initiative", + ["Inner Fire"] = "Feu int\195\169rieur", + ["Inner Focus"] = "Focalisation am\195\169lior\195\169e", + ["Innervate"] = "Innervation", + ["Insect Swarm"] = "Essaim d'insectes", + ["Inspiration"] = "Inspiration", + ["Instant Poison II"] = "Poison instantan\195\169 II", + ["Instant Poison III"] = "Poison instantan\195\169 III", + ["Instant Poison IV"] = "Poison instantan\195\169 IV", + ["Instant Poison V"] = "Poison instantan\195\169 V", + ["Instant Poison VI"] = "Poison instantan\195\169 VI", + ["Instant Poison"] = "Poison instantan\195\169", + ["Intensity"] = "Intensit\195\169", + ["Intercept"] = "Interception", + ["Intercept Stun"] = "Interception \195\169tourdissante", +-- ["Intervene"] = true, + ["Intimidating Shout"] = "Cri d\226\128\153intimidation", + ["Intimidation"] = "Intimidation", +-- ["Invisibility"] = true, + ["Iron Will"] = "Volont\195\169 de fer", + ["Jewelcrafting"] = "Joaillerie", + ["Judgement of Command"] = "Jugement d'autorit\195\169", + ["Judgement of Justice"] = "Jugement de justice", + ["Judgement of Light"] = "Jugement de lumi\195\168re", + ["Judgement of Righteousness"] = "Jugement de pi\195\169t\195\169", + ["Judgement of Wisdom"] = "Jugement de sagesse", + ["Judgement of the Crusader"] = "Jugement du Crois\195\169", + ["Judgement"] = "Jugement", + ["Kick"] = "Coup de pied", + ["Kick - Silenced"] = "Coup de pied - Silencieux", + ["Kidney Shot"] = "Aiguillon perfide", +-- ["Kill Command"] = true, + ["Killer Instinct"] = "Instinct du tueur", + ["Kodo Riding"] = "Monte de kodo", +-- ["Lacerate"] = true, + ["Lash of Pain"] = "Fouet de la douleur", + ["Last Stand"] = "Dernier rempart", + ["Lasting Judgement"] = "Jugement durable", + ["Lay on Hands"] = "Imposition des mains", + ["Leader of the Pack"] = "Chef de la meute", + ["Leather"] = "Cuir", + ["Leatherworking"] = "Travail du cuir", + ["Lesser Heal"] = "Soins inf\195\169rieurs", + ["Lesser Healing Wave"] = "Vague de soins inf\195\169rieurs", + ["Lesser Invisibility"] = "Invisibilit\195\169 inf\195\169rieure", + ["Lethal Shots"] = "Coups fatals", + ["Lethality"] = "Mortalit\195\169", + ["Levitate"] = "L\195\169vitation", + ["Libram"] = "Libram", +-- ["Lifebloom"] = true, + ["Life Tap"] = "Connexion", + ["Lifegiving Gem"] = "Gemme donneuse de vie", + ["Lightning Bolt"] = "Eclair", + ["Lightning Breath"] = "Souffle de foudre", + ["Lightning Mastery"] = "Ma\195\174trise de la foudre", + ["Lightning Reflexes"] = "R\195\169flexes \195\169clairs", + ["Lightning Shield"] = "Bouclier de foudre", + ["Lightwell Renew"] = "R\195\169novation du Puits de lumi\195\168re", + ["Lightwell"] = "Puits de lumi\195\168re", + ["Lockpicking"] = "Crochetage", + ["Long Daze"] = "H\195\169b\195\169tement prolong\195\169", + ["Mace Specialization"] = "Sp\195\169cialisation Masse", + ["Mace Stun Effect"] = "Effet \195\169tourdissant de la masse", + ["Mage Armor"] = "Armure du mage", + ["Magma Totem"] = "Totem de Magma", + ["Mail"] = "Mailles", +-- ["Maim"] = true, + ["Malice"] = "Malice", + ["Mana Burn"] = "Br\195\187lure de mana", + ["Mana Shield"] = "Bouclier de mana", + ["Mana Spring Totem"] = "Totem Fontaine de mana", + ["Mana Tide Totem"] = "Totem de Vague de mana", + ["Mangle"] = "Mutilation", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = "Marque du fauve", + ["Martyrdom"] = "Martyre", +-- ["Mass Dispel"] = true, + ["Master Demonologist"] = "Ma\195\174tre d\195\169monologue", + ["Master Summoner"] = "Ma\195\174tre invocateur", + ["Master of Deception"] = "Ma\195\174tre des illusions", + ["Maul"] = "Mutiler", + ["Mechanostrider Piloting"] = "Pilotage de m\195\169canotrotteur", + ["Meditation"] = "M\195\169ditation", + ["Melee Specialization"] = "Sp\195\169cialisation M\195\170l\195\169e", + ["Mend Pet"] = "Gu\195\169rison du familier", + ["Mental Agility"] = "Sagacit\195\169", + ["Mental Strength"] = "Force mentale", + ["Mind Blast"] = "Attaque mentale", + ["Mind Control"] = "Contr\195\180le mental", + ["Mind Flay"] = "Fouet mental", + ["Mind Soothe"] = "Apaisement", + ["Mind Vision"] = "Vision t\195\169l\195\169pathique", + ["Mind-numbing Poison II"] = "Poison de distraction mentale II", + ["Mind-numbing Poison III"] = "Poison de distraction mentale III", + ["Mind-numbing Poison"] = "Poison de distraction mentale", + ["Mining"] = "Minage", +-- ["Misdirection"] = true, + ["Mocking Blow"] = "Coup railleur", +-- ["Molten Armor"] = true, + ["Mongoose Bite"] = "Morsure de la mangouste", + ["Monster Slaying"] = "Tueur de monstres", + ["Moonfire"] = "Eclat lunaire", + ["Moonfury"] = "Fureur lunaire", + ["Moonglow"] = "Lueur de la lune", + ["Moonkin Aura"] = "Aura de s\195\169l\195\169nien", + ["Moonkin Form"] = "Forme de s\195\169l\195\169nien", + ["Mortal Shots"] = "Coups mortels", + ["Mortal Strike"] = "Frappe mortelle", + ["Multi-Shot"] = "Fl\195\168ches multiples", + ["Murder"] = "Meurtre", +-- ["Mutilate"] = true, + ["Natural Armor"] = "Armure naturelle", + ["Natural Shapeshifter"] = "Changeforme naturel", + ["Natural Weapons"] = "Armes naturelles", + ["Nature Resistance Totem"] = "Totem de r\195\169sistance \195\160 la Nature", + ["Nature Resistance"] = "R\195\169sistance \195\160 la Nature", + ["Nature's Focus"] = "Focalisation de la nature", + ["Nature's Grace"] = "Gr\195\162ce de la nature", + ["Nature's Grasp"] = "Emprise de la nature", + ["Nature's Reach"] = "Allonge de la Nature", + ["Nature's Swiftness"] = "Rapidit\195\169 de la nature", + ["Nightfall"] = "Cr\195\169puscule", + ["Omen of Clarity"] = "Augure de clart\195\169", + ["One-Handed Axes"] = "Haches \195\160 une main", + ["One-Handed Maces"] = "Masses \195\160 une main", + ["One-Handed Swords"] = "Ep\195\169es \195\160 une main", + ["One-Handed Weapon Specialization"] = "Sp\195\169cialisation Arme 1M", + ["Opening - No Text"] = "Ouverture - pas de texte", + ["Opening"] = "Ouverture", + ["Opportunity"] = "Opportunit\195\169", + ["Overpower"] = "Fulgurance", +-- ["Pain Suppression"] = true, + ["Paranoia"] = "Parano\195\175a", + ["Parry"] = "Parade", + ["Pathfinding"] = "Science des chemins", + ["Perception"] = "Perception", + ["Permafrost"] = "Gel prolong\195\169", + ["Pet Aggression"] = "Agressivit\195\169 du familier", + ["Pet Hardiness"] = "Robustesse du familier", + ["Pet Recovery"] = "R\195\169tablissement du familier", + ["Pet Resistance"] = "R\195\169sistance du familier", + ["Phase Shift"] = "Changement de phase", + ["Pick Lock"] = "Crochetage", + ["Pick Pocket"] = "Vol \195\160 la tire", + ["Piercing Howl"] = "Hurlement per\195\167ant", + ["Piercing Ice"] = "Glace per\195\167ante", + ["Plate Mail"] = "Armure en plaques", + ["Poison Cleansing Totem"] = "Totem de Purification du poison", + ["Poisons"] = "Poisons", + ["Polearm Specialization"] = "Sp\195\169cialisation Arme d'hast", + ["Polearms"] = "Armes d'hast", + ["Polymorph"] = "M\195\169tamorphose", + ["Polymorph: Pig"] = "M\195\169tamorphose: cochon", + ["Polymorph: Turtle"] = "M\195\169tamorphose: Tortue", -- all other polymorph spells don't have a capital letter before the animal name, to test + ["Portal: Darnassus"] = "Portail : Darnassus", + ["Portal: Ironforge"] = "Portail : Ironforge", + ["Portal: Orgrimmar"] = "Portail : Orgrimmar", + ["Portal: Stormwind"] = "Portail : Stormwind", + ["Portal: Thunder Bluff"] = "Portail : Thunder Bluff", + ["Portal: Undercity"] = "Portail : Undercity", + ["Pounce Bleed"] = "Traquenard sanglant", + ["Pounce"] = "Traquenard", + ["Power Infusion"] = "Infusion de puissance", + ["Power Word: Fortitude"] = "Mot de pouvoir : Robustesse", + ["Power Word: Shield"] = "Mot de pouvoir : Bouclier", + ["Prayer of Fortitude"] = "Pri\195\168re de robustesse", + ["Prayer of Healing"] = "Pri\195\168re de soins", +-- ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"] = "Pri\195\168re de protection contre l'Ombre", + ["Prayer of Spirit"] = "Pri\195\168re d'Esprit", + ["Precision"] = "Pr\195\169cision", + ["Predatory Strikes"] = "Frappes de pr\195\169dateur", + ["Premeditation"] = "Pr\195\169m\195\169ditation", + ["Preparation"] = "Pr\195\169paration", + ["Presence of Mind"] = "Pr\195\169sence spirituelle", + ["Primal Fury"] = "Fureur primitive", + ["Prowl"] = "R\195\180der", + ["Psychic Scream"] = "Cri psychique", + ["Pummel"] = "Vol\195\169e de coups", + ["Purge"] = "Expiation", + ["Purification"] = "Purification", + ["Purify"] = "Purification", + ["Pursuit of Justice"] = "Poursuite de la justice", + ["Pyroblast"] = "Explosion pyrotechnique", + ["Pyroclasm"] = "Pyroclasme", + ["Quick Shots"] = "Tir rapide", + ["Quickness"] = "Rapidit\195\169", + ["Rain of Fire"] = "Pluie de feu", + ["Rake"] = "Griffure", +-- ["Rampage"] = true, + ["Ram Riding"] = "Monte de b\195\169lier", + ["Ranged Weapon Specialization"] = "Sp\195\169cialisation Armes \195\160 distance", + ["Rapid Concealment"] = "Dissimulation rapide", + ["Rapid Fire"] = "Tir rapide", + ["Raptor Riding"] = "Monte de raptor", + ["Raptor Strike"] = "Attaque du raptor", + ["Ravage"] = "Ravage", + ["Readiness"] = "Promptitude", + ["Rebirth"] = "Renaissance", + ["Reckless Charge"] = "Charge furieuse", + ["Recklessness"] = "T\195\169m\195\169rit\195\169", + ["Reckoning"] = "R\195\169tribution", + ["Redemption"] = "R\195\169demption", + ["Redoubt"] = "Redoute", + ["Reflection"] = "Renvoi", + ["Regeneration"] = "R\195\169g\195\169n\195\169ration", + ["Regrowth"] = "R\195\169tablissement", + ["Reincarnation"] = "R\195\169incarnation", + ["Rejuvenation"] = "R\195\169cup\195\169ration", + ["Relentless Strikes"] = "Frappes implacables", + ["Remorseless"] = "Impitoyable", + ["Remorseless Attacks"] = "Attaques impitoyables", + ["Remove Curse"] = "D\195\169livrance de la mal\195\169diction", + ["Remove Insignia"] = "Enlever l'insigne", + ["Remove Lesser Curse"] = "D\195\169livrance de la mal\195\169diction mineure", + ["Rend"] = "Pourfendre", + ["Renew"] = "R\195\169novation", + ["Repentance"] = "Repentir", + ["Resurrection"] = "R\195\169surrection", + ["Retaliation"] = "Repr\195\169sailles", + ["Retribution Aura"] = "Aura de vindicte", + ["Revenge Stun"] = "Etourdissement vengeur", + ["Revenge"] = "Vengeance", + ["Reverberation"] = "R\195\169verb\195\169ration", + ["Revive Pet"] = "Ressusciter le familier", +-- ["Righteous Defense"] = true, + ["Righteous Fury"] = "Fureur vertueuse", + ["Rip"] = "D\195\169chirure", + ["Riposte"] = "Riposte", + ["Ritual of Doom Effect"] = "Effet Rituel de mal\195\169diction", + ["Ritual of Doom"] = "Rituel de mal\195\169diction", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = "Rituel d'invocation", + ["Rockbiter Weapon"] = "Arme Croque-roc", + ["Rogue Passive"] = "Voleur", + ["Rough Sharpening Stone"] = "Pierre \195\160 aiguiser brute", + ["Ruin"] = "Ruine", + ["Rupture"] = "Rupture", + ["Ruthlessness"] = "N\195\169m\195\169sis", + ["Sacrifice"] = "Sacrifice", + ["Safe Fall"] = "Chute amortie", + ["Sanctity Aura"] = "Aura de saintet\195\169", + ["Sap"] = "Assommer", + ["Savage Fury"] = "Furie sauvage", + ["Savage Strikes"] = "Frappes sauvages", + ["Scare Beast"] = "Effrayer une b\195\170te", + ["Scatter Shot"] = "Fl\195\168che de dispersion", + ["Scorch"] = "Br\195\187lure", + ["Scorpid Poison"] = "Poison de scorpide", + ["Scorpid Sting"] = "Piq\195\187re de scorpide", + ["Screech"] = "Hurlement", + ["Seal Fate"] = "Scelle le destin", +-- ["Seal of Blood"] = true, + ["Seal of Command"] = "Sceau d'autorit\195\169", + ["Seal of Justice"] = "Sceau de justice", + ["Seal of Light"] = "Sceau de lumi\195\168re", + ["Seal of Righteousness"] = "Sceau de pi\195\169t\195\169", + ["Seal of Wisdom"] = "Sceau de sagesse", + ["Seal of the Crusader"] = "Sceau du Crois\195\169", +-- ["Seal of Vengeance"] = true, + ["Searing Light"] = "Lumi\195\168re incendiaire", + ["Searing Pain"] = "Douleur br\195\187lante", + ["Searing Totem"] = "Totem incendiaire", +-- ["Second Wind"] = true, + ["Seduction"] = "S\195\169duction", +-- ["Seed of Corruption"] = true, + ["Sense Demons"] = "D\195\169tection des d\195\169mons", + ["Sense Undead"] = "D\195\169tection des morts-vivants", + ["Sentry Totem"] = "Totem Sentinelle", + ["Serpent Sting"] = "Morsure de serpent", + ["Setup"] = "Pr\195\169paratifs", + ["Shackle Undead"] = "Entraves des morts-vivants", + ["Shadow Affinity"] = "Affinit\195\169 avec l'ombre", + ["Shadow Bolt"] = "Trait de l'ombre", + ["Shadow Focus"] = "Focalisation de l'ombre", + ["Shadow Mastery"] = "Ma\195\174trise de l'ombre", + ["Shadow Protection"] = "Protection contre l'Ombre", + ["Shadow Reach"] = "Allonge de l'Ombre", + ["Shadow Resistance Aura"] = "Aura de r\195\169sistance \195\160 l'Ombre", + ["Shadow Resistance"] = "R\195\169sistance \195\160 l'Ombre", + ["Shadow Trance"] = "Transe de l'ombre", + ["Shadow Vulnerability"] = "Vuln\195\169rabilit\195\169 \195\160 l'ombre", + ["Shadow Ward"] = "Gardien de l'ombre", + ["Shadow Weaving"] = "Tissage de l'ombre", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = "Mot de l'ombre\194\160: Douleur", + ["Shadowburn"] = "Br\195\187lure de l'ombre", +-- ["Shadowfiend"] = true, + ["Shadowform"] = "Forme d'Ombre", +-- ["Shadowfury"] = true, + ["Shadowguard"] = "Garde de l'ombre", + ["Shadowmeld Passive"] = "Camouflage dans l'ombre", + ["Shadowmeld"] = "Camouflage dans l'ombre", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = "Griffes aiguis\195\169es", + ["Shatter"] = "Fracasser", + ["Sheep"] = "Mouton", + ["Shell Shield"] = "Carapace bouclier", + ["Shield Bash"] = "Coup de bouclier", + ["Shield Bash - Silenced"] = "Coup de bouclier - silencieux", -- seems to be the only "- Silenced" not having a Cap letter, will try to test! + ["Shield Block"] = "Ma\195\174trise du blocage", + ["Shield Slam"] = "Heurt de bouclier", + ["Shield Specialization"] = "Sp\195\169cialisation Bouclier", + ["Shield Wall"] = "Mur protecteur", + ["Shield"] = "Bouclier", +-- ["Shiv"] = true, + ["Shoot Bow"] = "Tir \195\160 l'arc", + ["Shoot Crossbow"] = "Tir \195\160 l\226\128\153arbal\195\168te", + ["Shoot Gun"] = "Tir avec une arme \195\160 feu", + ["Shoot"] = "Tir", + ["Shred"] = "Lambeau", + ["Silence"] = "Silence", +-- ["Silencing Shot"] = true, + ["Silent Resolve"] = "R\195\169solution silencieuse", + ["Sinister Strike"] = "Attaque pernicieuse", + ["Siphon Life"] = "Siphon de vie", + ["Skinning"] = "D\195\169pe\195\167age", + ["Slam"] = "Heurtoir", + ["Sleep"] = "Sommeil", + ["Slice and Dice"] = "D\195\169biter", +-- ["Slow"] = true, + ["Slow Fall"] = "Chute lente", + ["Smelting"] = "Fondre", + ["Smite"] = "Ch\195\162timent", + ["Solid Sharpening Stone"] = "Pierre \195\160 aiguiser solide", +-- ["Snake Trap"] = true, + ["Soothe Animal"] = "Apaiser les animaux", + ["Soothing Kiss"] = "Baiser apaisant", + ["Soul Fire"] = "Feu de l'\195\162me", + ["Soul Link"] = "Lien spirituel", + ["Soul Siphon"] = "Siphon d'\195\162me", +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"] = "R\195\169surrection de Pierre d'\195\162me", + ["Spell Lock"] = "Verrou magique", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"] = "Protection contre les sorts", + ["Spirit Bond"] = "Engagement spirituel", + ["Spirit Tap"] = "Connexion spirituelle", + ["Spirit of Redemption"] = "Esprit de r\195\169demption", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = "Focalisation spirituelle", + ["Spiritual Guidance"] = "Direction spirituelle", + ["Spiritual Healing"] = "Soins spirituels", + ["Sprint"] = "Sprint", +-- ["Stance Mastery"] = true, + ["Starfire"] = "Feu stellaire", + ["Starfire Stun"] = "Feu stellaire \195\169tourdissant", + ["Starshards"] = "Eclats stellaires", + ["Staves"] = "B\195\162tons", +-- ["Steady Shot"] = true, + ["Stealth"] = "Camouflage", + ["Stoneclaw Totem"] = "Totem de Griffes de pierre", + ["Stoneform"] = "Forme de pierre", + ["Stoneskin Totem"] = "Totem de Peau de pierre", + ["Stormstrike"] = "Courroux naturel", + ["Strength of Earth Totem"] = "Totem de Force de la Terre", + ["Stuck"] = "Bloqu\195\169", + ["Subtlety"] = "Discr\195\169tion", + ["Suffering"] = "Souffrance", + ["Summon Charger"] = "Invocation de destrier", + ["Summon Dreadsteed"] = "Invocation d'un Destrier de l'Effroi", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"] = "Invocation d'un chasseur corrompu", + ["Summon Felsteed"] = "Invocation d'un palefroi corrompu", + ["Summon Imp"] = "Invocation d'un diablotin", + ["Summon Succubus"] = "Invocation d'une succube", + ["Summon Voidwalker"] = "Invocation d'un marcheur du Vide", + ["Summon Warhorse"] = "Invocation d'un cheval de guerre", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"] = "Fracasser armure", + ["Suppression"] = "Suppression", + ["Surefooted"] = "Pied s\195\187r", + ["Survivalist"] = "Survivant", + ["Sweeping Strikes"] = "Attaques circulaires", + ["Swiftmend"] = "Prompte Gu\195\169rison", + ["Swipe"] = "Balayage", + ["Sword Specialization"] = "Sp\195\169cialisation Ep\195\169e", + ["Tactical Mastery"] = "Ma\195\174trise tactique", + ["Tailoring"] = "Couture", + ["Tainted Blood"] = "Corruption sanguine", + ["Tame Beast"] = "Dompte une b\195\170te", + ["Tamed Pet Passive"] = "Familier dompt\195\169", + ["Taunt"] = "Provocation", + ["Teleport: Darnassus"] = "T\195\169l\195\169portation : Darnassus", + ["Teleport: Ironforge"] = "T\195\169l\195\169portation : Ironforge", + ["Teleport: Moonglade"] = "T\195\169l\195\169portation : Reflet-de-Lune", + ["Teleport: Orgrimmar"] = "T\195\169l\195\169portation : Orgrimmar", + ["Teleport: Stormwind"] = "T\195\169l\195\169portation : Stormwind", + ["Teleport: Thunder Bluff"] = "T\195\169l\195\169portation : Thunder Bluff", + ["Teleport: Undercity"] = "T\195\169l\195\169portation : Undercity", +-- ["The Beast Within"] = true, + ["The Human Spirit"] = "L'esprit humain", + ["Thick Hide"] = "Peau \195\169paisse", + ["Thorns"] = "Epines", + ["Throw"] = "Lancer", + ["Throwing Specialization"] = "Sp\195\169cialisation Armes de jet", + ["Throwing Weapon Specialization"] = "Sp\195\169cialisation Armes de jet", + ["Thrown"] = "Armes de jet", + ["Thunder Clap"] = "Coup de tonnerre", + ["Thundering Strikes"] = "Frappe foudroyante", + ["Thunderstomp"] = "Grondeterre", + ["Tidal Focus"] = "Focalisation des flots", + ["Tidal Mastery"] = "Ma\195\174trise des flots", + ["Tiger Riding"] = "Monte de tigre", + ["Tiger's Fury"] = "Fureur du tigre", + ["Torment"] = "Tourment", + ["Totem"] = "Totem", + ["Totem of Wrath"] = "Totem de courroux", + ["Totemic Focus"] = "Focalisation tot\195\169mique", + ["Touch of Weakness"] = "Toucher de faiblesse", + ["Toughness"] = "R\195\169sistance", + ["Track Beasts"] = "Pistage des b\195\170tes", + ["Track Demons"] = "Pistage des d\195\169mons", + ["Track Dragonkin"] = "Pistage des draconiens", + ["Track Elementals"] = "Pistage des \195\169l\195\169mentaires", + ["Track Giants"] = "Pistage des g\195\169ants", + ["Track Hidden"] = "Pistage des camoufl\195\169s", + ["Track Humanoids"] = "Pistage des humano\195\175des", + ["Track Undead"] = "Pistage des morts-vivants", + ["Tranquil Air Totem"] = "Totem de Tranquillit\195\169 de l'air", + ["Tranquil Spirit"] = "Tranquillit\195\169 de l'esprit", + ["Tranquility"] = "Tranquillit\195\169", + ["Tranquilizing Shot"] = "Tir tranquillisant", + ["Trap Mastery"] = "Ma\195\174trise des pi\195\168ges", + ["Travel Form"] = "Forme de voyage", +-- ["Tree of Life"] = true, + ["Tremor Totem"] = "Totem de S\195\169isme", + ["Tribal Leatherworking"] = "Travail du cuir tribal", + ["Trueshot Aura"] = "Aura de pr\195\169cision", + ["Turn Undead"] = "Renvoi des morts-vivants", + ["Two-Handed Axes and Maces"] = "Haches et masses \195\160 deux mains", + ["Two-Handed Axes"] = "Haches \195\160 deux mains", + ["Two-Handed Maces"] = "Masses \195\160 deux mains", + ["Two-Handed Swords"] = "Ep\195\169es \195\160 deux mains", + ["Two-Handed Weapon Specialization"] = "Sp\195\169cialisation Arme 2M", + ["Unarmed"] = "Mains nues", + ["Unbreakable Will"] = "Volont\195\169 inflexible", + ["Unbridled Wrath Effect"] = "Effet Col\195\168re d\195\169cha\195\174n\195\169e", + ["Unbridled Wrath"] = "Col\195\168re d\195\169cha\195\174n\195\169e", + ["Undead Horsemanship"] = "Monte de cheval squelette", + ["Underwater Breathing"] = "Respiration aquatique", + ["Unending Breath"] = "Respiration interminable", + ["Unholy Power"] = "Puissance impie", + ["Unleashed Fury"] = "Fureur lib\195\169r\195\169e", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"] = "Foi inflexible", + ["Vampiric Embrace"] = "Etreinte vampirique", + ["Vanish"] = "Disparition", + ["Vanished"] = "Invisible", +-- ["Vampiric Touch"] = true, + ["Vengeance"] = "Vengeance", +-- ["Victory Rush"] = true, + ["Vigor"] = "Vigueur", + ["Vile Poisons"] = "Poisons abominables", + ["Vindication"] = "Justification", + ["Viper Sting"] = "Morsure de vip\195\168re", + ["Volley"] = "Salve", + ["Wand Specialization"] = "Sp\195\169cialisation Baguette", + ["Wands"] = "Baguettes", + ["War Stomp"] = "Choc martial", + ["Water Breathing"] = "Respiration aquatique", +-- ["Water Shield"] = true, + ["Water Walking"] = "Marcher sur l\226\128\153eau", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "Ame affaiblie", + ["Weaponsmith"] = "Fabricant d'armes", + ["Whirlwind"] = "Tourbillon", + ["Will of the Forsaken"] = "Volont\195\169 des R\195\169prouv\195\169s", + ["Windfury Totem"] = "Totem Furie-des-vents", + ["Windfury Weapon"] = "Arme Furie-des-vents", + ["Windwall Totem"] = "Totem de Mur des vents", + ["Wing Clip"] = "Coupure d'ailes", + ["Winter's Chill"] = "Froid hivernal", + ["Wisp Spirit"] = "Esprit feu follet", + ["Wolf Riding"] = "Monte de loup", + ["Wound Poison II"] = "Poison douloureux II", + ["Wound Poison III"] = "Poison douloureux III", + ["Wound Poison IV"] = "Poison douloureux IV", + ["Wound Poison"] = "Poison douloureux", + ["Wrath"] = "Col\195\168re", + ["Wrath of Air Totem"] = "Totem de courroux de l'air", + ["Wyvern Sting"] = "Piq\195\187re de wyverne", + } +end) + +BabbleSpell:RegisterTranslations("zhCN", function() + return { + ["Abolish Disease"] = "รฉยฉยฑรฉโ„ขยครงโ€“ยพรงโ€”โ€ฆ", + ["Abolish Poison Effect"] = "รฉยฉยฑรฆยฏโ€™รฆล“ยฏรฆโ€ขห†รฆลพล“", + ["Abolish Poison"] = "รฉยฉยฑรฆยฏโ€™รฆล“ยฏ", + ["Activate MG Turret"] = "รฉโ‚ฌลธรฅยฐโ€žรงโ€šยฎรฅยยฐ", + ["Adrenaline Rush"] = "รฅโ€ ยฒรฅล ยจ", + ["Aftermath"] = "รฆยธโ€ฆรงยฎโ€”", + ["Aggression"] = "รคยพยตรงโ€ขยฅ", + ["Aimed Shot"] = "รงลพโ€žรฅโ€กโ€ รฅยฐโ€žรฅโ€กยป", + ["Alchemy"] = "รงโ€šยผรฉโ€กโ€˜รฆล“ยฏ", + ["Ambush"] = "รคยผยรฅโ€กยป", + ["Amplify Curse"] = "รจยฏโ€ฆรฅโ€™โ€™รฅยขลพรฅยนโ€ฆ", + ["Amplify Magic"] = "รฉยญโ€รฆยณโ€ขรฅยขลพรฆโ€ขห†", + ["Ancestral Fortitude"] = "รฅโ€ฆห†รงยฅโ€“รฅยลกรฉลธยง", + ["Ancestral Healing"] = "รฅโ€ฆห†รงยฅโ€“รฆยฒยปรงโ€“โ€”", + ["Ancestral Knowledge"] = "รฅโ€ฆห†รงยฅโ€“รงลธยฅรจยฏโ€ ", + ["Ancestral Spirit"] = "รฅโ€ฆห†รงยฅโ€“รคยนโ€นรฉยญโ€š", +-- ["Anesthetic Poison"] = true, + ["Anger Management"] = "รฆโ€žยครฆโ‚ฌโ€™รฆลฝล’รฆลฝยง", +-- ["Anguish"] = true, + ["Anticipation"] = "รฉยขโ€žรงลธยฅ", + ["Aquatic Form"] = "รฆยฐยดรฆย โ€“รฅยฝยขรฆโ‚ฌย", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"] = "รฅยฅยฅรฆล“ยฏรฅโ€ฆโ€ฐรจยพโ€ฐ", + ["Arcane Concentration"] = "รฅยฅยฅรฆล“ยฏรคยธโ€œรฆยณยจ", + ["Arcane Explosion"] = "รฉยญโ€รงห†โ€ รฆล“ยฏ", + ["Arcane Focus"] = "รฅยฅยฅรฆล“ยฏรฉโ€บโ€ รคยธยญ", + ["Arcane Instability"] = "รฅยฅยฅรฆล“ยฏรฅยขลพรฆโ€ขห†", + ["Arcane Intellect"] = "รฅยฅยฅรฆล“ยฏรฆโ„ขยบรฆโ€ฆยง", + ["Arcane Meditation"] = "รฅยฅยฅรฆล“ยฏรฅโ€ ยฅรฆฦ’ยณ", + ["Arcane Mind"] = "รฅยฅยฅรฆล“ยฏรฅยฟฦ’รฆโ„ขยบ", + ["Arcane Missiles"] = "รฅยฅยฅรฆล“ยฏรฉยฃลพรฅยผยน", + ["Arcane Power"] = "รฅยฅยฅรฆล“ยฏรฅยผยบรฅล’โ€“", + ["Arcane Resistance"] = "รฅยฅยฅรฆล“ยฏรฆล โ€”รฆโ‚ฌยง", + ["Arcane Shot"] = "รฅยฅยฅรฆล“ยฏรฅยฐโ€žรฅโ€กยป", + ["Arcane Subtlety"] = "รฅยฅยฅรฆล“ยฏรงยฒยพรฅยฆโ„ข", + ["Arctic Reach"] = "รฆลพยรฅยฏโ€™รฅยปยถรคยผยธ", + ["Armorsmith"] = "รฆล ยครงโ€ยฒรฉโ€ยปรฉโ‚ฌย รฅยธห†", + ["Aspect of the Beast"] = "รฉโ€กลฝรฅโ€ฆยฝรฅยฎห†รฆล ยค", + ["Aspect of the Cheetah"] = "รงล’ลฝรจยฑยนรฅยฎห†รฆล ยค", + ["Aspect of the Hawk"] = "รฉโ€บโ€žรฉยนยฐรฅยฎห†รฆล ยค", + ["Aspect of the Monkey"] = "รงยยตรงล’ยดรฅยฎห†รฆล ยค", + ["Aspect of the Pack"] = "รจยฑยนรงยพยครฅยฎห†รฆล ยค", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = "รฉโ€กลฝรฆโ‚ฌยงรฅยฎห†รฆล ยค", + ["Astral Recall"] = "รฆหœลธรงโ€ขล’รคยผย รฉโ‚ฌย", + ["Attack"] = "รฆโ€ยปรฅโ€กยป", + ["Attacking"] = "รฆโ€ยปรฅโ€กยป", + ["Auto Shot"] = "รจโ€กยชรฅล ยจรฅยฐโ€žรฅโ€กยป", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"] = "รฆโ€“ยงรคยธโ€œรงยฒยพ", +-- ["Backlash"] = true, + ["Backstab"] = "รจฦ’ล’รฅห†ยบ", + ["Bane"] = "รงยยพรงยฅยธ", + ["Banish"] = "รฆโ€ยพรฉโ‚ฌยรฆล“ยฏ", + ["Barkskin Effect"] = "รฆย โ€˜รงลกยฎรฆล“ยฏรฆโ€ขห†รฆลพล“", + ["Barkskin"] = "รฆย โ€˜รงลกยฎรฆล“ยฏ", + ["Barrage"] = "รฅยผยนรฅยนโ€ข", + ["Bash"] = "รฉโ€กยรฅโ€กยป", + ["Basic Campfire"] = "รฅลธยบรงยกโ‚ฌรจยยฅรงยยซ", + ["Battle Shout"] = "รฆห†หœรฆโ€“โ€”รฆโ‚ฌโ€™รฅยยผ", + ["Battle Stance Passive"] = "รฆห†หœรฆโ€“โ€”รฅยงยฟรฆโ‚ฌยรฏยผห†รจยขยซรฅล ยจรฏยผโ€ฐ", + ["Battle Stance"] = "รฆห†หœรฆโ€“โ€”รฅยงยฟรฆโ‚ฌย", + ["Bear Form"] = "รงโ€ ล รฅยฝยขรฆโ‚ฌย", + ["Beast Lore"] = "รฉโ€กลฝรฅโ€ฆยฝรงลธยฅรจยฏโ€ ", + ["Beast Slaying"] = "รฉโ€กลฝรฅโ€ฆยฝรฆยโ‚ฌรฆโ€ฐโ€น", + ["Beast Training"] = "รจยฎยญรงยปฦ’รฉโ€กลฝรฅโ€ฆยฝ", + ["Benediction"] = "รงยฅห†รงยฆย", + ["Berserker Rage"] = "รงโ€นโ€šรฆลกยดรคยนโ€นรฆโ‚ฌโ€™", + ["Berserker Stance Passive"] = "รงโ€นโ€šรฆลกยดรฅยงยฟรฆโ‚ฌยรฏยผห†รจยขยซรฅล ยจรฏยผโ€ฐ", + ["Berserker Stance"] = "รงโ€นโ€šรฆลกยดรฅยงยฟรฆโ‚ฌย", + ["Berserking"] = "รงโ€นโ€šรฆลกยด", + ["Bestial Discipline"] = "รฉโ€กลฝรฅโ€ฆยฝรฆห†โ€™รฅยพโ€น", + ["Bestial Swiftness"] = "รฉโ€กลฝรฅโ€ฆยฝรจยฟโ€ฆรฆยยท", + ["Bestial Wrath"] = "รงโ€นโ€šรฉโ€กลฝรฆโ‚ฌโ€™รงยยซ", +-- ["Binding Heal"] = true, + ["Bite"] = "รฆโ€™โ€ขรฅโ€™ยฌ", + ["Black Arrow"] = "รฉยปโ€˜รงยฎยญ", + ["Blackout"] = "รฆหœยรฉหœโ„ข", + ["Blacksmithing"] = "รฉโ€ยปรฉโ‚ฌย ", + ["Blade Flurry"] = "รฅโ€ฐโ€˜รฅห†ฦ’รคยนยฑรจห†ลพ", + ["Blast Wave"] = "รฅโ€ ยฒรฅโ€กยปรฆยณยข", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"] = "รงยฅลพรฆยยฉรฅโ€บลพรฅยคย", + ["Blessing of Freedom"] = "รจโ€กยชรงโ€ยฑรงยฅยรงยฆย", + ["Blessing of Kings"] = "รงลฝโ€นรจโ‚ฌโ€ฆรงยฅยรงยฆย", + ["Blessing of Light"] = "รฅโ€ฆโ€ฐรฆหœลฝรงยฅยรงยฆย", + ["Blessing of Might"] = "รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Blessing of Protection"] = "รคยฟยรฆล ยครงยฅยรงยฆย", + ["Blessing of Sacrifice"] = "รงโ€ฐยบรงโ€ฐยฒรงยฅยรงยฆย", + ["Blessing of Salvation"] = "รฆโ€นยฏรฆโ€ขโ€˜รงยฅยรงยฆย", + ["Blessing of Sanctuary"] = "รฅยบโ€กรฆล ยครงยฅยรงยฆย", + ["Blessing of Wisdom"] = "รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Blind"] = "รจโ€กยดรงโ€บยฒ", + ["Blinding Powder"] = "รจโ€กยดรงโ€บยฒรงยฒโ€ฐ", + ["Blink"] = "รฉโ€”ยชรงลฝยฐรฆล“ยฏ", + ["Blizzard"] = "รฆลกยดรฉยฃลฝรฉโ€บยช", + ["Block"] = "รฆย ยผรฆล’ยก", + ["Blood Craze"] = "รจยกโ‚ฌรคยนโ€นรงโ€นโ€šรงฦ’ยญ", + ["Blood Frenzy"] = "รจยกโ‚ฌรคยนโ€นรงโ€นโ€šรฆลกยด", + ["Blood Fury"] = "รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Blood Pact"] = "รจยกโ‚ฌรคยนโ€นรฅยฅโ€˜รฅยยฐ", +-- ["Bloodlust"] = true, + ["Bloodrage"] = "รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Bloodthirst"] = "รฆยฎโ€นรฅยฟย", + ["Booming Voice"] = "รฉล“โ€กรจโ‚ฌยณรฅโ€”โ€œรฉลธยณ", + ["Bow Specialization"] = "รฅยผโ€œรคยธโ€œรงยฒยพ", + ["Bows"] = "รฅยผโ€œ", + ["Bright Campfire"] = "รฆหœลฝรคยบยฎรงยฏยรงยยซ", + ["Brutal Impact"] = "รฉโ€กลฝรจโ€บยฎรฅโ€ ยฒรฆโ€™ลพ", + ["Burning Soul"] = "รงโ€กฦ’รงฦ’ยงรคยนโ€นรฉยญโ€š", + ["Call Pet"] = "รฅยยฌรฅโ€ยครฅยฎย รงโ€ฐยฉ", + ["Call of Flame"] = "รงฦ’ห†รงโ€žยฐรฅยยฌรฅโ€ยค", + ["Call of Thunder"] = "รฉโ€บยทรฉล“โ€ รฅยยฌรฅโ€ยค", + ["Camouflage"] = "รคยผยชรจยฃโ€ฆ", + ["Cannibalize"] = "รฉยฃลธรฅยฐยธ", + ["Cat Form"] = "รงล’ลฝรจยฑยนรฅยฝยขรฆโ‚ฌย", + ["Cataclysm"] = "รงยยพรฅยหœ", + ["Chain Heal"] = "รฆยฒยปรงโ€“โ€”รฉโ€œยพ", + ["Chain Lightning"] = "รฉโ€”ยชรงโ€ยตรฉโ€œยพ", + ["Challenging Roar"] = "รฆล’โ€˜รฆห†หœรฅโ€™โ€ รฅโ€œยฎ", + ["Challenging Shout"] = "รฆล’โ€˜รฆห†หœรฆโ‚ฌโ€™รฅยยผ", + ["Charge Rage Bonus Effect"] = "รฅโ€ ยฒรฉโ€โ€นรฉยขยรฅยคโ€“รฆโ‚ฌโ€™รฆยฐโ€รฆโ€ขห†รฆลพล“", -- not sure about this one + ["Charge"] = "รฅโ€ ยฒรฉโ€โ€น", + ["Charge Stun"] = "รฅโ€ ยฒรฉโ€โ€นรฅโ€กยปรฆหœย", + ["Cheap Shot"] = "รฅยยทรจยขยญ", + ["Chilled"] = "รฅโ€ ยฐรฅโ€ ยป", +-- ["Circle of Healing"] = true, + ["Claw"] = "รงห†ยชรฅโ€กยป", + ["Cleanse"] = "รฆยธโ€ฆรฆยดยรฆล“ยฏ", + ["Clearcasting"] = "รจล โ€šรจฦ’ยฝรฆโ€“ยฝรฆยณโ€ข", + ["Cleave"] = "รฉยกยบรฅล ห†รฆโ€“ยฉ", + ["Clever Traps"] = "รงยยตรฅยทยงรฉโ„ขยทรฉหœยฑ", +-- ["Cloak of Shadows"] = true, + ["Closing"] = "รฅโ€ฆยณรฉโ€”ยญ", + ["Cloth"] = "รฅยธฦ’รงโ€ยฒ", + ["Coarse Sharpening Stone"] = "รงยฒโ€”รฅห†ยถรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Cobra Reflexes"] = "รฆยฏโ€™รจโ€บโ€กรฅยยรฅยฐโ€ž", + ["Cold Blood"] = "รฅโ€ ยทรจยกโ‚ฌ", + ["Cold Snap"] = "รฆโ‚ฌยฅรฉโ‚ฌลธรฅโ€ ยทรฅยยด", + ["Combat Endurance"] = "รคยฝล“รฆห†หœรฆล’ยรคยนโ€ฆ", + ["Combustion"] = "รงโ€กฦ’รงฦ’ยง", + ["Command"] = "รฅโ€˜ยฝรคยปยค", +-- ["Commanding Shout"] = true, + ["Concentration Aura"] = "รคยธโ€œรฆยณยจรฅโ€ฆโ€ฐรงลฝยฏ", + ["Concussion Blow"] = "รฉล“โ€กรจยยกรงล’โ€บรฅโ€กยป", + ["Concussion"] = "รฉล“โ€กรจยยก", + ["Concussive Shot"] = "รฉล“โ€กรจยยกรฅยฐโ€žรฅโ€กยป", + ["Cone of Cold"] = "รฅโ€ ยฐรฉโ€ยฅรฆล“ยฏ", + ["Conflagrate"] = "รงโ€กฦ’รงฦ’ยง", + ["Conjure Food"] = "รฉโ‚ฌย รฉยฃลธรฆล“ยฏ", + ["Conjure Mana Agate"] = "รฅห†ยถรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงลฝโ€บรงโ€˜โ„ข", + ["Conjure Mana Citrine"] = "รฅห†ยถรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรฉยปโ€žรฆยฐยดรฆโ„ขยถ", + ["Conjure Mana Jade"] = "รฅห†ยถรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงยฟยกรงยฟย ", + ["Conjure Mana Ruby"] = "รฅห†ยถรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงยบยขรฅยฎยรงลธยณ", + ["Conjure Water"] = "รฉโ‚ฌย รฆยฐยดรฆล“ยฏ", + ["Consecrated Sharpening Stone"] = "รงยฅลพรฅล“ยฃรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Consecration"] = "รฅยฅโ€ฐรงล’ยฎ", +-- ["Consume Magic"] = true, + ["Consume Shadows"] = "รฅยลพรฅโ„ขยฌรฆลกโ€”รฅยฝยฑ", + ["Convection"] = "รคยผย รฅยฏยผ", + ["Conviction"] = "รฅยฎลกรงยฝยช", + ["Cooking"] = "รงฦ’ยนรฉยฅยช", + ["Corruption"] = "รจโ€ฆยรจลกโ‚ฌ", + ["Counterattack"] = "รฅยยรฅโ€กยป", + ["Counterspell"] = "รฆยณโ€ขรฆล“ยฏรฅยยรฅห†ยถ", + ["Counterspell - Silenced"] = "รฆยณโ€ขรฆล“ยฏรฅยยรฅห†ยถ - รฆยฒโ€ฐรฉยปหœ", + ["Cower"] = "รงโ€ขยรงยผยฉ", + ["Create Firestone"] = "รฅห†ยถรฉโ‚ฌย รงยยซรงโ€žยฐรงลธยณ", + ["Create Firestone (Major)"] = "รฅห†ยถรฉโ‚ฌย รฆลพยรฆโ€ขห†รงยยซรงโ€žยฐรงลธยณ", + ["Create Firestone (Greater)"] = "รฅห†ยถรฉโ‚ฌย รฅยผยบรฆโ€ขห†รงยยซรงโ€žยฐรงลธยณ", + ["Create Firestone (Lesser)"] = "รฅห†ยถรฉโ‚ฌย รฆยฌยกรงยบยงรงยยซรงโ€žยฐรงลธยณ", + ["Create Healthstone"] = "รฅห†ยถรฉโ‚ฌย รฆยฒยปรงโ€“โ€”รงลธยณ", + ["Create Healthstone (Major)"] = "รฅห†ยถรฉโ‚ฌย รฆลพยรฆโ€ขห†รฆยฒยปรงโ€“โ€”รงลธยณ", + ["Create Healthstone (Greater)"] = "รฅห†ยถรฉโ‚ฌย รฅยผยบรฆโ€ขห†รฆยฒยปรงโ€“โ€”รงลธยณ", + ["Create Healthstone (Lesser)"] = "รฅห†ยถรฉโ‚ฌย รฆยฌยกรงยบยงรฆยฒยปรงโ€“โ€”รงลธยณ", + ["Create Healthstone (Minor)"] = "รฅห†ยถรฉโ‚ฌย รฅห†ยรงยบยงรฆยฒยปรงโ€“โ€”รงลธยณ", + ["Create Soulstone"] = "รฅห†ยถรฉโ‚ฌย รงยยตรฉยญโ€šรงลธยณ", + ["Create Soulstone (Major)"] = "รฅห†ยถรฉโ‚ฌย รฆลพยรฆโ€ขห†รงยยตรฉยญโ€šรงลธยณ", + ["Create Soulstone (Greater)"] = "รฅห†ยถรฉโ‚ฌย รฅยผยบรฆโ€ขห†รงยยตรฉยญโ€šรงลธยณ", + ["Create Soulstone (Lesser)"] = "รฅห†ยถรฉโ‚ฌย รฆยฌยกรงยบยงรงยยตรฉยญโ€šรงลธยณ", + ["Create Soulstone (Minor)"] = "รฅห†ยถรฉโ‚ฌย รฅห†ยรงยบยงรงยยตรฉยญโ€šรงลธยณ", + ["Create Spellstone"] = "รฅห†ยถรฉโ‚ฌย รฆยณโ€ขรฆล“ยฏรงลธยณ", + ["Create Spellstone (Major)"] = "รฅห†ยถรฉโ‚ฌย รฆลพยรฆโ€ขห†รฆยณโ€ขรฆล“ยฏรงลธยณ", + ["Create Spellstone (Greater)"] = "รฅห†ยถรฉโ‚ฌย รฅยผยบรฆโ€ขห†รฆยณโ€ขรฆล“ยฏรงลธยณ", + ["Crippling Poison II"] = "รจโ€กยดรฆยฎโ€นรฆยฏโ€™รจยยฏ II", + ["Crippling Poison"] = "รจโ€กยดรฆยฎโ€นรฆยฏโ€™รจยยฏ", + ["Critical Mass"] = "รงยยซรงโ€žยฐรฉโ€กยรฅโ€กยป", + ["Crossbows"] = "รฅยผยฉ", + ["Cruelty"] = "รฆยฎโ€นรฅยฟย", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"] = "รฆย ยฝรฅลธยน", + ["Cure Disease"] = "รงยฅโ€บรงโ€”โ€ฆรฆล“ยฏ", + ["Cure Poison"] = "รฆยถห†รฆยฏโ€™รฆล“ยฏ", + ["Curse of Agony"] = "รงโ€”โ€บรจโ€นยฆรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Doom Effect"] = "รฅลฝโ€žรจยฟยรจยฏโ€ฆรฅโ€™โ€™รฆโ€ขห†รฆลพล“", + ["Curse of Doom"] = "รฅลฝโ€žรจยฟยรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Exhaustion"] = "รงโ€“ยฒรฅล ยณรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Idiocy"] = "รงโ€”ยดรฅโ€˜โ€ รจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Recklessness"] = "รฉยฒยรจลฝยฝรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Shadow"] = "รฆลกโ€”รฅยฝยฑรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Tongues"] = "รจยฏยญรจยจโ‚ฌรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of Weakness"] = "รจโ„ขลกรฅยผยฑรจยฏโ€ฆรฅโ€™โ€™", + ["Curse of the Elements"] = "รฅโ€ฆฦ’รงยดย รจยฏโ€ฆรฅโ€™โ€™", +-- ["Cyclone"] = true, + ["Dagger Specialization"] = "รฅล’โ€ขรฉยฆโ€“รคยธโ€œรงยฒยพ", + ["Daggers"] = "รฅล’โ€ขรฉยฆโ€“", + ["Dampen Magic"] = "รฉยญโ€รฆยณโ€ขรฆล โ€˜รฅห†ยถ", + ["Dark Pact"] = "รฉยปโ€˜รฆลกโ€”รฅยฅโ€˜รงยบยฆ", + ["Darkness"] = "รฉยปโ€˜รฆลกโ€”", + ["Dash"] = "รฆโ‚ฌยฅรฅยฅโ€", + ["Deadly Poison II"] = "รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ II", + ["Deadly Poison III"] = "รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ III", + ["Deadly Poison IV"] = "รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ IV", + ["Deadly Poison V"] = "รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ V", + ["Deadly Poison"] = "รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ", +-- ["Deadly Throw"] = true, + ["Death Coil"] = "รฆยญยปรคยบยกรงยผย รงยปโ€ข", + ["Death Wish"] = "รฆยญยปรคยบยกรคยนโ€นรฆโ€žยฟ", + ["Deep Wounds"] = "รฉโ€กยรฅยบยฆรคยผยครฅยยฃ", + ["Defense"] = "รฉหœยฒรฅยพยก", + ["Defensive Stance Passive"] = "รฉหœยฒรฅยพยกรฅยงยฟรฆโ‚ฌยรฏยผห†รจยขยซรฅล ยจรฏยผโ€ฐ", + ["Defensive Stance"] = "รฉหœยฒรฅยพยกรฅยงยฟรฆโ‚ฌย", + ["Defensive State 2"] = "รฉหœยฒรฅยพยกรงล ยถรฆโ‚ฌย 2", -- not sure about this one + ["Defensive State"] = "รฉหœยฒรฅยพยกรงล ยถรฆโ‚ฌย", -- and this one + ["Defiance"] = "รฆล’โ€˜รจยกโ€ฆ", + ["Deflection"] = "รฅยยรฆโ€“ล“", + ["Demon Armor"] = "รฉยญโ€รงโ€ยฒรฆล“ยฏ", + ["Demon Skin"] = "รฆยยถรฉยญโ€รงลกยฎรจโ€šยค", + ["Demonic Embrace"] = "รฆยยถรฉยญโ€รคยนโ€นรฆโ€นยฅ", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = "รฆยยถรฉยญโ€รงโ€ฐยบรงโ€ฐยฒ", + ["Demoralizing Roar"] = "รฆล’ยซรฅยฟโ€”รฅโ€™โ€ รฅโ€œยฎ", + ["Demoralizing Shout"] = "รฆล’ยซรฅยฟโ€”รฆโ‚ฌโ€™รฅยยผ", + ["Dense Sharpening Stone"] = "รจโ€กยดรฅยฏโ€ รงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Desperate Prayer"] = "รงยปยรฆล“โ€บรงยฅยทรจยจโ‚ฌ", + ["Destructive Reach"] = "รฆยฏยรงยยญรฅยปยถรคยผยธ", + ["Detect Greater Invisibility"] = "รคยพยฆรฆยตโ€นรฅยผยบรฆโ€ขห†รฉลกยรฅยฝยข", + ["Detect Invisibility"] = "รคยพยฆรฆยตโ€นรฉลกยรฅยฝยข", + ["Detect Lesser Invisibility"] = "รคยพยฆรฆยตโ€นรฆยฌยกรงยบยงรฉลกยรฅยฝยข", + ["Detect Magic"] = "รคยพยฆรฆยตโ€นรฉยญโ€รฆยณโ€ข", + ["Detect Traps"] = "รคยพยฆรฆยตโ€นรฉโ„ขยทรฉหœยฑ", + ["Detect"] = "รคยพยฆรฆยตโ€น", + ["Deterrence"] = "รฅยจยรฆโ€ฆโ€˜", +-- ["Devastate"] = true, + ["Devastation"] = "รฆยฏยรงยยญ", + ["Devotion Aura"] = "รจโ„ขโ€รจยฏลกรฅโ€ฆโ€ฐรงลฝยฏ", + ["Devour Magic Effect"] = "รฅยลพรฅโ„ขยฌรฉยญโ€รฆยณโ€ขรฆโ€ขห†รฆลพล“", + ["Devour Magic"] = "รฅยลพรฅโ„ขยฌรฉยญโ€รฆยณโ€ข", + ["Devouring Plague"] = "รฅโ„ขยฌรงยยตรงหœลธรงโ€“ยซ", + ["Diplomacy"] = "รฅยคโ€“รคยบยค", + ["Dire Bear Form"] = "รฅยทยจรงโ€ ล รฅยฝยขรฆโ‚ฌย", + ["Disarm Trap"] = "รจยงยฃรฉโ„ขยครฉโ„ขยทรฉหœยฑ", + ["Disarm"] = "รงยผยดรฆยขยฐ", + ["Disease Cleansing Totem"] = "รงยฅโ€บรงโ€”โ€ฆรฅโ€บยพรจโ€ฆยพ", + ["Disenchant"] = "รฅห†โ€ รจยงยฃ", + ["Disengage"] = "รฉโ‚ฌฦ’รจโ€žยฑ", + ["Dismiss Pet"] = "รจยงยฃรฆโ€ขยฃรฉโ€กลฝรฅโ€ฆยฝ", + ["Dispel Magic"] = "รฉยฉยฑรฆโ€ขยฃรฉยญโ€รฆยณโ€ข", + ["Distract"] = "รฆโ€ฐยฐรคยนยฑ", + ["Distracting Shot"] = "รฆโ€ฐยฐรคยนยฑรฅยฐโ€žรฅโ€กยป", + ["Dive"] = "รคยฟยฏรฅโ€ ยฒ", + ["Divine Favor"] = "รงยฅลพรฆยยฉรฆล“ยฏ", + ["Divine Fury"] = "รงยฅลพรฅล“ยฃรคยนโ€นรฆโ‚ฌโ€™", +-- ["Divine Illumination"] = true, + ["Divine Intellect"] = "รงยฅลพรฅล“ยฃรฆโ„ขยบรฆโ€ฆยง", + ["Divine Intervention"] = "รงยฅลพรฅล“ยฃรฅยนยฒรฆยถโ€ฐ", + ["Divine Protection"] = "รฅล“ยฃรคยฝโ€˜รฆล“ยฏ", + ["Divine Shield"] = "รฅล“ยฃรงโ€บยพรฆล“ยฏ", + ["Divine Spirit"] = "รงยฅลพรฅล“ยฃรคยนโ€นรงยยต", + ["Divine Strength"] = "รงยฅลพรฅล“ยฃรคยนโ€นรฅล โ€บ", + ["Dodge"] = "รจยบยฒรฉโ€”ยช", +-- ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"] = "รฉยพโ„ขรฉยณลพรฅห†ยถรงลกยฎ", + ["Drain Life"] = "รฅยยธรฅยโ€“รงโ€ลธรฅโ€˜ยฝ", + ["Drain Mana"] = "รฅยยธรฅยโ€“รฆยณโ€ขรฅล โ€บ", + ["Drain Soul"] = "รฅยยธรฅยโ€“รงยยตรฉยญโ€š", + ["Drink"] = "รฅโ€“ยรฆยฐยด", + ["Dual Wield Specialization"] = "รฅยล’รฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Dual Wield"] = "รฅยล’รฆยญยฆรฅโ„ขยจ", + ["Duel"] = "รฅโ€ ยณรฆโ€“โ€”", + ["Eagle Eye"] = "รฉยนยฐรงล“ยผรฆล“ยฏ", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"] = "รฅยคยงรฅล“ยฐรฉล“โ€กรฅโ€กยป", + ["Earthbind Totem"] = "รฅล“ยฐรงยผลกรฅโ€บยพรจโ€ฆยพ", + ["Efficiency"] = "รฆโ€ขห†รงลฝโ€ก", + ["Elemental Focus"] = "รฅโ€ฆฦ’รงยดย รฉโ€บโ€ รคยธยญ", + ["Elemental Fury"] = "รฅโ€ฆฦ’รงยดย รคยนโ€นรฆโ‚ฌโ€™", + ["Elemental Leatherworking"] = "รฅโ€ฆฦ’รงยดย รฅห†ยถรงลกยฎ", + ["Elemental Mastery"] = "รฅโ€ฆฦ’รงยดย รฆลฝล’รฆยยก", + ["Elemental Sharpening Stone"] = "รฅโ€ฆฦ’รงยดย รงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Elune's Grace"] = "รจโ€ฐยพรฉล“ยฒรฆยยฉรงลกโ€žรจยตยรงยฆย", + ["Elusiveness"] = "รฉยฃหœรฅยฟยฝรคยธยรฅยฎลก", + ["Emberstorm"] = "รงยยฅรงยโ‚ฌรฉยฃลฝรฆลกยด", + ["Enamored Water Spirit"] = "รจยขยซรจยฟยทรฆฦ’โ€˜รงลกโ€žรฆยฐยดรคยนโ€นรฉยญโ€š", + ["Enchanting"] = "รฉโ„ขโ€žรฉยญโ€", + ["Endurance Training"] = "รจโ‚ฌยรคยนโ€ฆรจยฎยญรงยปฦ’", + ["Endurance"] = "รจโ‚ฌยรคยนโ€ฆ", + ["Engineering Specialization"] = "รฅยทยฅรงยจโ€นรฅยญยฆรคยธโ€œรงยฒยพ", + ["Engineering"] = "รฅยทยฅรงยจโ€นรฅยญยฆ", + ["Enrage"] = "รงโ€นโ€šรฆโ‚ฌโ€™", + ["Enriched Manna Biscuit"] = "รฅยยฏรฅยยฃรงลกโ€žรฉยญโ€รฆยณโ€ขรงโ€šยนรฅยฟฦ’", + ["Enslave Demon"] = "รฅยฅยดรฅยฝยนรฆยยถรฉยญโ€", + ["Entangling Roots"] = "รงยบย รงยผย รฆย ยนรฉยกยป", + ["Entrapment"] = "รจยฏยฑรฆยโ€ข", +-- ["Envenom"] = true, + ["Escape Artist"] = "รฉโ‚ฌฦ’รฅโ€˜ยฝรคยธโ€œรฅยฎยถ", + ["Evasion"] = "รฉโ€”ยชรฉยยฟ", + ["Eventide"] = "รฉยปโ€žรฆหœย", --An old talent of shamans, removed from the game. + ["Eviscerate"] = "รฅโ€ฐโ€รฉยชยจ", + ["Evocation"] = "รฅโ€ยครฉโ€ โ€™", + ["Execute"] = "รฆโ€“ยฉรฆยโ‚ฌ", + ["Exorcism"] = "รฉยฉยฑรฉโ€šยชรฆล“ยฏ", + ["Expansive Mind"] = "รฅยผโ‚ฌรฉหœโ€รฆโ‚ฌยรงยปยด", + ["Explosive Trap Effect"] = "รงห†โ€ รงโ€šยธรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Explosive Trap"] = "รงห†โ€ รงโ€šยธรฉโ„ขยทรฉหœยฑ", + ["Expose Armor"] = "รงย ยดรงโ€ยฒ", + ["Eye for an Eye"] = "รคยปยฅรงล“ยผรจยฟหœรงล“ยผ", + ["Eye of Kilrogg"] = "รฅลธยบรฅยฐโ€รงยฝโ€”รฆย ยผรคยนโ€นรงล“ยผ", + ["Eyes of the Beast"] = "รฉโ€กลฝรฅโ€ฆยฝรคยนโ€นรงล“ยผ", + ["Fade"] = "รฆยธยรฉลกยรฆล“ยฏ", + ["Faerie Fire"] = "รงยฒยพรงยยตรคยนโ€นรงยยซ", + ["Faerie Fire (Feral)"] = "รงยฒยพรงยยตรคยนโ€นรงยยซรฏยผห†รฉโ€กลฝรฆโ‚ฌยงรฏยผโ€ฐ", + ["Far Sight"] = "รจยงโ€ รงโ€ขล’รฆล“ยฏ", + ["Fear Ward"] = "รฉหœยฒรฆล ยครฆยยรฆฦ’ยงรงยปโ€œรงโ€ขล’", + ["Fear"] = "รฆยยรฆฦ’ยงรฆล“ยฏ", + ["Feed Pet"] = "รฅโ€“โ€šรฅโ€ฆยปรฅยฎย รงโ€ฐยฉ", + ["Feedback"] = "รฅโ€บลพรฉยฆห†", + ["Feign Death"] = "รฅยโ€กรฆยญยป", + ["Feint"] = "รคยฝยฏรฆโ€ยป", +-- ["Fel Armor"] = true, + ["Fel Concentration"] = "รฆยยถรฉยญโ€รคยธโ€œรฆยณยจ", + ["Fel Domination"] = "รฆยยถรฉยญโ€รฆโ€ยฏรฉโ€ฆย", + ["Fel Intellect"] = "รฆยยถรฉยญโ€รฆโ„ขยบรฅล โ€บ", + ["Fel Stamina"] = "รฆยยถรฉยญโ€รจโ‚ฌยรฅล โ€บ", + ["Felfire"] = "รฉยญโ€รงยยซ", + ["Feline Grace"] = "รจยฑยนรคยนโ€นรคยผหœรฉโ€บโ€ฆ", + ["Feline Swiftness"] = "รจยฑยนรคยนโ€นรจยฟโ€ฆรฆยยท", + ["Feral Aggression"] = "รฉโ€กลฝรฆโ‚ฌยงรคยพยตรงโ€ขยฅ", + ["Feral Charge"] = "รฉโ€กลฝรฆโ‚ฌยงรฅโ€ ยฒรฉโ€โ€น", + ["Feral Instinct"] = "รฉโ€กลฝรฆโ‚ฌยงรฆล“ยฌรจฦ’ยฝ", + ["Ferocious Bite"] = "รฅโ€กยถรงล’โ€บรฆโ€™โ€ขรฅโ€™ยฌ", + ["Ferocity"] = "รฅโ€กยถรฆลกยด", + ["Fetish"] = "รงยฅลพรฅฦ’ย", + ["Find Herbs"] = "รฅยฏยปรฆโ€ฐยพรจยโ€ฐรจยยฏ", + ["Find Minerals"] = "รฅยฏยปรฆโ€ฐยพรงลธยฟรงโ€ฐยฉ", + ["Find Treasure"] = "รฅยฏยปรฆโ€ฐยพรจยดยขรฅยฎย", + ["Fire Blast"] = "รงยยซรงโ€žยฐรฅโ€ ยฒรฅโ€กยป", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = "รงยยซรงโ€žยฐรฆโ€“ยฐรฆหœลธรฅโ€บยพรจโ€ฆยพ", + ["Fire Power"] = "รงยยซรงโ€žยฐรฅยผยบรฅล’โ€“", + ["Fire Resistance Aura"] = "รงยยซรงโ€žยฐรฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงลฝยฏ", + ["Fire Resistance Totem"] = "รฆล โ€”รงยยซรฅโ€บยพรจโ€ฆยพ", + ["Fire Resistance"] = "รงยยซรงโ€žยฐรฆล โ€”รฆโ‚ฌยง", + ["Fire Shield"] = "รงยยซรงโ€žยฐรคยนโ€นรงโ€บยพ", + ["Fire Vulnerability"] = "รงยยซรงโ€žยฐรฆหœโ€œรคยผยค", + ["Fire Ward"] = "รฉหœยฒรฆล ยครงยยซรงโ€žยฐรงยปโ€œรงโ€ขล’", + ["Fireball"] = "รงยยซรงยฦ’รฆล“ยฏ", + ["Firebolt"] = "รงยยซรงโ€žยฐรงยฎยญ", + ["First Aid"] = "รฆโ‚ฌยฅรฆโ€ขโ€˜", + ["Fishing Poles"] = "รฉยฑยผรงยซยฟ", + ["Fishing"] = "รฉโ€™โ€œรฉยฑยผ", + ["Fist Weapon Specialization"] = "รฆโ€นยณรฅยฅโ€”รคยธโ€œรงยฒยพ", + ["Fist Weapons"] = "รฆโ€นยณรฅยฅโ€”", + ["Flame Shock"] = "รงฦ’ห†รงโ€žยฐรฉล“โ€กรฅโ€กยป", + ["Flame Throwing"] = "รงฦ’ห†รงโ€žยฐรฆล โ€ขรฆลฝยท", + ["Flamestrike"] = "รงฦ’ห†รงโ€žยฐรฅโ€ ยฒรฅโ€กยป", + ["Flamethrower"] = "รงยยซรงโ€žยฐรฅโ€“ยทรฅยฐโ€žรฅโ„ขยจ", + ["Flametongue Totem"] = "รงยยซรจห†ล’รฅโ€บยพรจโ€ฆยพ", + ["Flametongue Weapon"] = "รงยยซรจห†ล’รฆยญยฆรฅโ„ขยจ", + ["Flare"] = "รงโ€ฆยงรฆหœลฝรฅยผยน", + ["Flash Heal"] = "รฅยฟยซรฉโ‚ฌลธรฆยฒยปรงโ€“โ€”", + ["Flash of Light"] = "รฅล“ยฃรฅโ€ฆโ€ฐรฉโ€”ยชรงลฝยฐ", +-- ["Flight Form"] = true, + ["Flurry"] = "รคยนยฑรจห†ลพ", + ["Focused Casting"] = "รคยธโ€œรฆยณยจรฆโ€“ยฝรฆยณโ€ข", + ["Food"] = "รจยฟโ€บรฉยฃลธ", + ["Forbearance"] = "รจโ€กยชรฅยพโ€น", +-- ["Force of Nature"] = true, + ["Force of Will"] = "รฆโ€žยรฅยฟโ€”รคยนโ€นรฅล โ€บ", + ["Freezing Trap Effect"] = "รฅโ€ ยฐรฅโ€ ยปรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Freezing Trap"] = "รฅโ€ ยฐรฅโ€ ยปรฉโ„ขยทรฉหœยฑ", + ["Frenzied Regeneration"] = "รงโ€นโ€šรฆลกยดรฅโ€บลพรฅยคย", + ["Frenzy"] = "รงโ€“ยฏรงโ€นโ€š", + ["Frost Armor"] = "รฉล“ล“รงโ€ยฒรฆล“ยฏ", + ["Frost Channeling"] = "รฅโ€ ยฐรฉล“ล“รฅยฏยผรจฦ’ยฝ", + ["Frost Nova"] = "รฅโ€ ยฐรฉล“ล“รฆโ€“ยฐรฆหœลธ", + ["Frost Resistance Aura"] = "รฅโ€ ยฐรฉล“ล“รฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงลฝยฏ", + ["Frost Resistance Totem"] = "รฆล โ€”รฅยฏโ€™รฅโ€บยพรจโ€ฆยพ", + ["Frost Resistance"] = "รฅโ€ ยฐรฉล“ล“รฆล โ€”รฆโ‚ฌยง", + ["Frost Shock"] = "รฅโ€ ยฐรฉล“ล“รฉล“โ€กรฅโ€กยป", + ["Frost Trap"] = "รฅโ€ ยฐรฉล“ล“รฉโ„ขยทรฉหœยฑ", + ["Frost Trap Aura"] = "รฅโ€ ยฐรฉล“ล“รฉโ„ขยทรฉหœยฑรฅโ€ฆโ€ฐรงลฝยฏ", + ["Frost Ward"] = "รฉหœยฒรฆล ยครฅโ€ ยฐรฉล“ล“รงยปโ€œรงโ€ขล’", + ["Frostbite"] = "รฉล“ล“รฅยฏโ€™รฅห†ยบรฉยชยจ", + ["Frostbolt"] = "รฅยฏโ€™รฅโ€ ยฐรงยฎยญ", + ["Frostbrand Weapon"] = "รฅโ€ ยฐรฅยฐยรฆยญยฆรฅโ„ขยจ", + ["Furious Howl"] = "รงโ€นโ€šรฆโ‚ฌโ€™รคยนโ€นรฅลกลฝ", + ["Furor"] = "รฆยฟโ‚ฌรฆโ‚ฌโ€™", + ["Garrote"] = "รงยปลพรฅโ€“โ€ฐ", + ["Generic"] = "รฅลธยบรฆล“ยฌ", -- not sure about this one + ["Ghost Wolf"] = "รฅยนยฝรฉยญโ€šรคยนโ€นรงโ€นยผ", + ["Ghostly Strike"] = "รฉยฌยผรฉยญโ€ฆรฆโ€ยปรฅโ€กยป", + ["Gift of Life"] = true, + ["Gift of Nature"] = "รจโ€กยชรงโ€žยถรจยตยรงยฆย", + ["Gift of the Wild"] = "รฉโ€กลฝรฆโ‚ฌยงรจยตยรงยฆย", + ["Gouge"] = "รฅโ€กยฟรฅโ€กยป", + ["Grace of Air Totem"] = "รฉยฃลฝรคยนโ€นรคยผหœรฉโ€บโ€ฆรฅโ€บยพรจโ€ฆยพ", + ["Great Stamina"] = "รฆล’ยรคยนโ€ฆรจโ‚ฌยรฅล โ€บ", + ["Greater Blessing of Kings"] = "รฅยผยบรฆโ€ขห†รงลฝโ€นรจโ‚ฌโ€ฆรงยฅยรงยฆย", + ["Greater Blessing of Light"] = "รฅยผยบรฆโ€ขห†รฅโ€ฆโ€ฐรฆหœลฝรงยฅยรงยฆย", + ["Greater Blessing of Might"] = "รฅยผยบรฆโ€ขห†รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Greater Blessing of Salvation"] = "รฅยผยบรฆโ€ขห†รฆโ€นยฏรฆโ€ขโ€˜รงยฅยรงยฆย", + ["Greater Blessing of Sanctuary"] = "รฅยผยบรฆโ€ขห†รฅยบโ€กรฆล ยครงยฅยรงยฆย", + ["Greater Blessing of Wisdom"] = "รฅยผยบรฆโ€ขห†รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Greater Heal"] = "รฅยผยบรฆโ€ขห†รฆยฒยปรงโ€“โ€”รฆล“ยฏ", + ["Grim Reach"] = "รฆโ€”ย รฆฦ’โ€ฆรฅยปยถรคยผยธ", + ["Grounding Totem"] = "รฆย ยนรฅลธยบรฅโ€บยพรจโ€ฆยพ", + ["Grovel"] = "รฅล’ยรฅล’ย", + ["Growl"] = "รคยฝลฝรฅยยผ", + ["Guardian's Favor"] = "รฅยฎห†รฆล ยครจโ‚ฌโ€ฆรงลกโ€žรฅยฎย รงห†ยฑ", + ["Gun Specialization"] = "รฆลพยชรฆยขยฐรคยธโ€œรงยฒยพ", + ["Guns"] = "รฆลพยชรฆยขยฐ", + ["Hammer of Justice"] = "รฅห†ยถรจยฃยรคยนโ€นรฉโ€ยค", + ["Hammer of Wrath"] = "รฆโ€žยครฆโ‚ฌโ€™รคยนโ€นรฉโ€ยค", + ["Hamstring"] = "รฆโ€“ยญรงยญโ€น", + ["Harass"] = "รคยพยตรฆโ€ฐยฐ", + ["Hardiness"] = "รฅยลกรฉลธยง", + ["Hawk Eye"] = "รฉยนยฐรงล“ยผ", + ["Heal"] = "รฆยฒยปรงโ€“โ€”รฆล“ยฏ", + ["Healing Focus"] = "รฆยฒยปรงโ€“โ€”รคยธโ€œรฆยณยจ", + ["Healing Light"] = "รฆยฒยปรงโ€“โ€”รคยนโ€นรฅโ€ฆโ€ฐ", + ["Healing Stream Totem"] = "รฆยฒยปรงโ€“โ€”รคยนโ€นรฆยณโ€ฐรฅโ€บยพรจโ€ฆยพ", + ["Healing Touch"] = "รฆยฒยปรงโ€“โ€”รคยนโ€นรจยงยฆ", + ["Healing Wave"] = "รฆยฒยปรงโ€“โ€”รฆยณยข", + ["Healing Way"] = "รฆยฒยปรงโ€“โ€”รคยนโ€นรฉยโ€œ", + ["Health Funnel"] = "รงโ€ลธรฅโ€˜ยฝรฉโ‚ฌลกรฉยโ€œ", + ["Heart of the Wild"] = "รฉโ€กลฝรฆโ‚ฌยงรคยนโ€นรฅยฟฦ’", + ["Heavy Sharpening Stone"] = "รฉโ€กยรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Hellfire Effect"] = "รฅล“ยฐรงโ€นยฑรงฦ’ห†รงโ€žยฐรฆโ€ขห†รฆลพล“", + ["Hellfire"] = "รฅล“ยฐรงโ€นยฑรงฦ’ห†รงโ€žยฐ", + ["Hemorrhage"] = "รฅโ€กยบรจยกโ‚ฌ", + ["Herb Gathering"] = "รฉโ€กโ€กรฉโ€บโ€ รจยโ€ฐรจยยฏ", + ["Herbalism"] = "รจยโ€ฐรจยยฏรฅยญยฆ", + ["Heroic Strike"] = "รจโ€นยฑรฅโ€นโ€กรฆโ€ฐโ€œรฅโ€กยป", +-- ["Heroism"] = true, + ["Hex of Weakness"] = "รจโ„ขลกรฅยผยฑรฅยฆโ€“รฆล“ยฏ", + ["Hibernate"] = "รคยผโ€˜รงล“ย ", + ["Holy Fire"] = "รงยฅลพรฅล“ยฃรคยนโ€นรงยยซ", + ["Holy Light"] = "รฅล“ยฃรฅโ€ฆโ€ฐรฆล“ยฏ", + ["Holy Nova"] = "รงยฅลพรฅล“ยฃรฆโ€“ยฐรฆหœลธ", + ["Holy Power"] = "รงยฅลพรฅล“ยฃรฅยผยบรฅล’โ€“", + ["Holy Reach"] = "รงยฅลพรฅล“ยฃรฅยปยถรคยผยธ", + ["Holy Shield"] = "รงยฅลพรฅล“ยฃรคยนโ€นรงโ€บยพ", + ["Holy Shock"] = "รงยฅลพรฅล“ยฃรฉล“โ€กรฅโ€กยป", + ["Holy Specialization"] = "รงยฅลพรฅล“ยฃรคยธโ€œรงยฒยพ", + ["Holy Wrath"] = "รงยฅลพรฅล“ยฃรฆโ€žยครฆโ‚ฌโ€™", + ["Honorless Target"] = "รฆโ€”ย รจยยฃรจยชโ€ฐรงโ€บยฎรฆย โ€ก", + ["Horse Riding"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรฉยฉยฌ", + ["Howl of Terror"] = "รฆยยรฆฦ’ยงรฅลกลฝรฅยยซ", + ["Humanoid Slaying"] = "รคยบยบรฅลพโ€นรงโ€ลธรงโ€ฐยฉรฆยโ‚ฌรฆโ€ฐโ€น", + ["Hunter's Mark"] = "รงล’ลฝรคยบยบรฅยยฐรจยฎยฐ", + ["Hurricane"] = "รฉยฃโ€œรฉยฃลฝ", + ["Ice Armor"] = "รฅโ€ ยฐรงโ€ยฒรฆล“ยฏ", + ["Ice Barrier"] = "รฅยฏโ€™รฅโ€ ยฐรฆล ยครคยฝโ€œ", + ["Ice Block"] = "รฅยฏโ€™รฅโ€ ยฐรฅยฑยรฉลกล“", +-- ["Ice Lance"] = true, + ["Ice Shards"] = "รฅยฏโ€™รฅโ€ ยฐรงยขลฝรงโ€ฐโ€ก", + ["Ignite"] = "รงโ€šยนรงโ€กฦ’", + ["Illumination"] = "รฅยยฏรฅยโ€˜", + ["Immolate"] = "รงล’ยฎรงยฅยญ", + ["Immolation Trap Effect"] = "รงล’ยฎรงยฅยญรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Immolation Trap"] = "รงล’ยฎรงยฅยญรฉโ„ขยทรฉหœยฑ", + ["Impact"] = "รฅโ€ ยฒรฅโ€กยป", + ["Impale"] = "รงยฉยฟรฅห†ยบ", + ["Improved Ambush"] = "รฅยผยบรฅล’โ€“รคยผยรฅโ€กยป", + ["Improved Arcane Explosion"] = "รฅยผยบรฅล’โ€“รฉยญโ€รงห†โ€ รฆล“ยฏ", + ["Improved Arcane Missiles"] = "รฅยผยบรฅล’โ€“รฅยฅยฅรฆล“ยฏรฉยฃลพรฅยผยน", + ["Improved Arcane Shot"] = "รฅยผยบรฅล’โ€“รฅยฅยฅรฆล“ยฏรฅยฐโ€žรฅโ€กยป", + ["Improved Aspect of the Hawk"] = "รฅยผยบรฅล’โ€“รฉโ€บโ€žรฉยนยฐรฅยฎห†รฆล ยค", + ["Improved Aspect of the Monkey"] = "รฅยผยบรฅล’โ€“รงยยตรงล’ยดรฅยฎห†รฆล ยค", + ["Improved Backstab"] = "รฅยผยบรฅล’โ€“รจฦ’ล’รฅห†ยบ", + ["Improved Battle Shout"] = "รฅยผยบรฅล’โ€“รฆห†หœรฆโ€“โ€”รฆโ‚ฌโ€™รฅยยผ", + ["Improved Berserker Rage"] = "รฅยผยบรฅล’โ€“รงโ€นโ€šรฆลกยดรคยนโ€นรฆโ‚ฌโ€™", + ["Improved Blessing of Might"] = "รฅยผยบรฅล’โ€“รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Improved Blessing of Wisdom"] = "รฅยผยบรฅล’โ€“รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Improved Blizzard"] = "รฅยผยบรฅล’โ€“รฆลกยดรฉยฃลฝรฉโ€บยช", + ["Improved Bloodrage"] = "รฅยผยบรฅล’โ€“รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Improved Chain Heal"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รฉโ€œยพ", + ["Improved Chain Lightning"] = "รฅยผยบรฅล’โ€“รฉโ€”ยชรงโ€ยตรฉโ€œยพ", + ["Improved Challenging Shout"] = "รฅยผยบรฅล’โ€“รฆล’โ€˜รฆห†หœรฆโ‚ฌโ€™รฅยยผ", + ["Improved Charge"] = "รฅยผยบรฅล’โ€“รฅโ€ ยฒรฉโ€โ€น", + ["Improved Cheap Shot"] = "รฅยผยบรฅล’โ€“รฅยยทรจยขยญ", + ["Improved Cleave"] = "รฅยผยบรฅล’โ€“รฉยกยบรฅล ห†รฆโ€“ยฉ", + ["Improved Concentration Aura"] = "รฅยผยบรฅล’โ€“รคยธโ€œรฆยณยจรฅโ€ฆโ€ฐรงลฝยฏ", + ["Improved Concussive Shot"] = "รฅยผยบรฅล’โ€“รฉล“โ€กรจยยกรฅยฐโ€žรฅโ€กยป", + ["Improved Cone of Cold"] = "รฅยผยบรฅล’โ€“รฅโ€ ยฐรฉโ€ยฅรฆล“ยฏ", + ["Improved Corruption"] = "รฅยผยบรฅล’โ€“รจโ€ฆยรจลกโ‚ฌรฆล“ยฏ", + ["Improved Counterspell"] = "รฅยผยบรฅล’โ€“รฆยณโ€ขรฆล“ยฏรฅยยรฅห†ยถ", + ["Improved Curse of Agony"] = "รฅยผยบรฅล’โ€“รงโ€”โ€บรจโ€นยฆรจยฏโ€ฆรฅโ€™โ€™", + ["Improved Curse of Exhaustion"] = "รฅยผยบรฅล’โ€“รงโ€“ยฒรฅล ยณรจยฏโ€ฆรฅโ€™โ€™", + ["Improved Curse of Weakness"] = "รฅยผยบรฅล’โ€“รจโ„ขลกรฅยผยฑรจยฏโ€ฆรฅโ€™โ€™", + ["Improved Dampen Magic"] = "รฅยผยบรฅล’โ€“รฉยญโ€รฆยณโ€ขรฆล โ€˜รฅห†ยถ", + ["Improved Deadly Poison"] = "รฅยผยบรฅล’โ€“รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจยยฏ", + ["Improved Demoralizing Shout"] = "รฅยผยบรฅล’โ€“รฆล’ยซรฅยฟโ€”รฆโ‚ฌโ€™รฅยยผ", + ["Improved Devotion Aura"] = "รฅยผยบรฅล’โ€“รจโ„ขโ€รจยฏลกรฅโ€ฆโ€ฐรงลฝยฏ", + ["Improved Disarm"] = "รฅยผยบรฅล’โ€“รงยผยดรฆยขยฐ", + ["Improved Distract"] = "รฅยผยบรฅล’โ€“รฆโ€ฐยฐรคยนยฑ", + ["Improved Drain Life"] = "รฅยผยบรฅล’โ€“รฅยยธรฅยโ€“รงโ€ลธรฅโ€˜ยฝ", + ["Improved Drain Mana"] = "รฅยผยบรฅล’โ€“รฅยยธรฅยโ€“รฆยณโ€ขรฅล โ€บ", + ["Improved Drain Soul"] = "รฅยผยบรฅล’โ€“รฅยยธรฅยโ€“รงยยตรฉยญโ€š", + ["Improved Enrage"] = "รฅยผยบรฅล’โ€“รงโ€นโ€šรฆโ‚ฌโ€™", + ["Improved Enslave Demon"] = "รฅยผยบรฅล’โ€“รฅยฅยดรฅยฝยนรฆยยถรฉยญโ€", + ["Improved Entangling Roots"] = "รฅยผยบรฅล’โ€“รงยบย รงยผย รฆย ยนรฉยกยป", + ["Improved Evasion"] = "รฅยผยบรฅล’โ€“รฉโ€”ยชรฉยยฟ", + ["Improved Eviscerate"] = "รฅยผยบรฅล’โ€“รฅโ€ฐโ€รฉยชยจ", + ["Improved Execute"] = "รฅยผยบรฅล’โ€“รฆโ€“ยฉรฆยโ‚ฌ", + ["Improved Expose Armor"] = "รฅยผยบรฅล’โ€“รงย ยดรงโ€ยฒ", + ["Improved Eyes of the Beast"] = "รฅยผยบรฅล’โ€“รฉโ€กลฝรฅโ€ฆยฝรคยนโ€นรงล“ยผ", + ["Improved Fade"] = "รฅยผยบรฅล’โ€“รฆยธยรฉลกยรฆล“ยฏ", + ["Improved Feign Death"] = "รฅยผยบรฅล’โ€“รฅยโ€กรฆยญยป", + ["Improved Fire Blast"] = "รฅยผยบรฅล’โ€“รงยยซรงโ€žยฐรฅโ€ ยฒรฅโ€กยป", + ["Improved Fire Nova Totem"] = "รฅยผยบรฅล’โ€“รงยยซรงโ€žยฐรฅโ€บยพรจโ€ฆยพ", + ["Improved Fire Ward"] = "รฅยผยบรฅล’โ€“รฉหœยฒรฆล ยครงยยซรงโ€žยฐรงยปโ€œรงโ€ขล’", + ["Improved Fireball"] = "รฅยผยบรฅล’โ€“รงยยซรงยฦ’รฆล“ยฏ", + ["Improved Firebolt"] = "รฅยผยบรฅล’โ€“รงยยซรงโ€žยฐรงยฎยญ", + ["Improved Firestone"] = "รฅยผยบรฅล’โ€“รงยยซรงโ€žยฐรงลธยณ", + ["Improved Flamestrike"] = "รฅยผยบรฅล’โ€“รงฦ’ห†รงโ€žยฐรฅโ€ ยฒรฅโ€กยป", + ["Improved Flametongue Weapon"] = "รฅยผยบรฅล’โ€“รงยยซรจห†ล’รฆยญยฆรฅโ„ขยจ", + ["Improved Flash of Light"] = "รฅยผยบรฅล’โ€“รฅล“ยฃรฅโ€ฆโ€ฐรฉโ€”ยชรงลฝยฐ", + ["Improved Frost Nova"] = "รฅยผยบรฅล’โ€“รฅโ€ ยฐรฉล“ล“รฆโ€“ยฐรฆหœลธ", + ["Improved Frost Ward"] = "รฅยผยบรฅล’โ€“รฉหœยฒรฆล ยครฅโ€ ยฐรฉล“ล“รงยปโ€œรงโ€ขล’", + ["Improved Frostbolt"] = "รฅยผยบรฅล’โ€“รฅยฏโ€™รฅโ€ ยฐรงยฎยญ", + ["Improved Frostbrand Weapon"] = "รฅยผยบรฅล’โ€“รฅโ€ ยฐรฅยฐยรฆยญยฆรฅโ„ขยจ", + ["Improved Garrote"] = "รฅยผยบรฅล’โ€“รงยปลพรฅโ€“โ€ฐ", + ["Improved Ghost Wolf"] = "รฅยผยบรฅล’โ€“รฅยนยฝรฉยญโ€šรคยนโ€นรงโ€นยผ", + ["Improved Gouge"] = "รฅยผยบรฅล’โ€“รฅโ€กยฟรฅโ€กยป", + ["Improved Grace of Air Totem"] = "รฅยผยบรฅล’โ€“รฉยฃลฝรคยนโ€นรคยผหœรฉโ€บโ€ฆรฅโ€บยพรจโ€ฆยพ", + ["Improved Grounding Totem"] = "รฅยผยบรฅล’โ€“รฆย ยนรฅลธยบรฅโ€บยพรจโ€ฆยพ", + ["Improved Hammer of Justice"] = "รฅยผยบรฅล’โ€“รฅห†ยถรจยฃยรคยนโ€นรฉโ€ยค", + ["Improved Hamstring"] = "รฅยผยบรฅล’โ€“รฆโ€“ยญรงยญโ€น", + ["Improved Healing Stream Totem"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รคยนโ€นรฆยณโ€ฐรฅโ€บยพรจโ€ฆยพ", + ["Improved Healing Touch"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รคยนโ€นรจยงยฆ", + ["Improved Healing Wave"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รฆยณยข", + ["Improved Healing"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รฆล“ยฏ", + ["Improved Health Funnel"] = "รฅยผยบรฅล’โ€“รงโ€ลธรฅโ€˜ยฝรฉโ‚ฌลกรฉยโ€œ", + ["Improved Healthstone"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รงลธยณ", + ["Improved Heroic Strike"] = "รฅยผยบรฅล’โ€“รจโ€นยฑรฅโ€นโ€กรฆโ€ฐโ€œรฅโ€กยป", + ["Improved Hunter's Mark"] = "รฅยผยบรฅล’โ€“รงล’ลฝรคยบยบรฅยยฐรจยฎยฐ", + ["Improved Immolate"] = "รฅยผยบรฅล’โ€“รงล’ยฎรงยฅยญ", + ["Improved Imp"] = "รฅยผยบรฅล’โ€“รฅยฐยรฉยฌยผ", + ["Improved Inner Fire"] = "รฅยผยบรฅล’โ€“รฅยฟฦ’รงยยตรคยนโ€นรงยยซ", + ["Improved Instant Poison"] = "รฅยผยบรฅล’โ€“รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ", + ["Improved Intercept"] = "รฅยผยบรฅล’โ€“รฆโ€นยฆรฆห†ยช", + ["Improved Intimidating Shout"] = "รฅยผยบรฅล’โ€“รงย ยดรจฦ’โ€ รฆโ‚ฌโ€™รฅยยผ", + ["Improved Judgement"] = "รฅยผยบรฅล’โ€“รฅยฎยกรฅห†ยค", + ["Improved Kick"] = "รฅยผยบรฅล’โ€“รจโ€žลกรจยธยข", + ["Improved Kidney Shot"] = "รฅยผยบรฅล’โ€“รจโ€šยพรฅโ€กยป", + ["Improved Lash of Pain"] = "รฅยผยบรฅล’โ€“รฅโ€ฐยงรงโ€”โ€บรฉลพยญรงยฌลพ", + ["Improved Lay on Hands"] = "รฅยผยบรฅล’โ€“รฅล“ยฃรงโ€“โ€”รฆล“ยฏ", + ["Improved Lesser Healing Wave"] = "รฅยผยบรฅล’โ€“รฆยฌยกรงยบยงรฆยฒยปรงโ€“โ€”รฆยณยข", + ["Improved Life Tap"] = "รฅยผยบรฅล’โ€“รงโ€ลธรฅโ€˜ยฝรฅห†โ€ รฆยตย", + ["Improved Lightning Bolt"] = "รฅยผยบรฅล’โ€“รฉโ€”ยชรงโ€ยตรงยฎยญ", + ["Improved Lightning Shield"] = "รฅยผยบรฅล’โ€“รฉโ€”ยชรงโ€ยตรฆล ยครงโ€บยพ", + ["Improved Magma Totem"] = "รฅยผยบรฅล’โ€“รงโ€ โ€รฅยฒยฉรฅโ€บยพรจโ€ฆยพ", + ["Improved Mana Burn"] = "รฅยผยบรฅล’โ€“รฆยณโ€ขรฅล โ€บรงโ€กฦ’รงฦ’ยง", + ["Improved Mana Shield"] = "รฅยผยบรฅล’โ€“รฆยณโ€ขรฅล โ€บรฆล ยครงโ€บยพ", + ["Improved Mana Spring Totem"] = "รฅยผยบรฅล’โ€“รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยณโ€ฐรฅโ€บยพรจโ€ฆยพ", + ["Improved Mark of the Wild"] = "รฅยผยบรฅล’โ€“รฉโ€กลฝรฆโ‚ฌยงรฅยยฐรจยฎยฐ", + ["Improved Mend Pet"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รฅยฎย รงโ€ฐยฉ", + ["Improved Mind Blast"] = "รฅยผยบรฅล’โ€“รฅยฟฦ’รงยยตรฉล“โ€กรงห†โ€ ", + ["Improved Moonfire"] = "รฅยผยบรฅล’โ€“รฆล“ห†รงยยซรฆล“ยฏ", + ["Improved Nature's Grasp"] = "รฅยผยบรฅล’โ€“รจโ€กยชรงโ€žยถรคยนโ€นรฆยยก", + ["Improved Overpower"] = "รฅยผยบรฅล’โ€“รฅลฝโ€นรฅห†ยถ", + ["Improved Power Word: Fortitude"] = "รฅยผยบรฅล’โ€“รงล“ลธรจยจโ‚ฌรฆล“ยฏรฏยผลกรฉลธยง", + ["Improved Power Word: Shield"] = "รฅยผยบรฅล’โ€“รฅล“ยฃรจยจโ‚ฌรฆล“ยฏรฏยผลกรงโ€บยพ", + ["Improved Prayer of Healing"] = "รฅยผยบรฅล’โ€“รฆยฒยปรงโ€“โ€”รงยฅยทรจยจโ‚ฌ", + ["Improved Psychic Scream"] = "รฅยผยบรฅล’โ€“รฅยฟฦ’รงยยตรฅยฐโ€“รฅโ€ขยธ", + ["Improved Pummel"] = "รฅยผยบรฅล’โ€“รฆโ€นยณรฅโ€กยป", + ["Improved Regrowth"] = "รฅยผยบรฅล’โ€“รฆโ€žห†รฅยห†", + ["Improved Reincarnation"] = "รฅยผยบรฅล’โ€“รฅยคยรงโ€ลธ", + ["Improved Rejuvenation"] = "รฅยผยบรฅล’โ€“รฅโ€บลพรฆหœยฅ", + ["Improved Rend"] = "รฅยผยบรฅล’โ€“รฆโ€™โ€ขรจยฃโ€š", + ["Improved Renew"] = "รฅยผยบรฅล’โ€“รฆยยขรฅยคย", + ["Improved Retribution Aura"] = "รฅยผยบรฅล’โ€“รฆฦ’ยฉรงยฝลกรฅโ€ฆโ€ฐรงลฝยฏ", + ["Improved Revenge"] = "รฅยผยบรฅล’โ€“รฅยคยรคยปโ€ก", + ["Improved Revive Pet"] = "รฅยผยบรฅล’โ€“รฅยคยรฆยดยปรฅยฎย รงโ€ฐยฉ", + ["Improved Righteous Fury"] = "รฅยผยบรฅล’โ€“รฆยญยฃรคยนโ€ฐรคยนโ€นรฆโ‚ฌโ€™", + ["Improved Rockbiter Weapon"] = "รฅยผยบรฅล’โ€“รงลธยณรฅล’โ€“รฆยญยฆรฅโ„ขยจ", + ["Improved Rupture"] = "รฅยผยบรฅล’โ€“รฅโ€ฐยฒรจยฃโ€š", + ["Improved Sap"] = "รฅยผยบรฅล’โ€“รฉโ€”ยทรฆยฃย", + ["Improved Scorch"] = "รฅยผยบรฅล’โ€“รงยยผรงฦ’ยง", + ["Improved Scorpid Sting"] = "รฅยผยบรฅล’โ€“รฆยฏโ€™รจยลฝรฉโ€™โ€ฐรฅห†ยบ", + ["Improved Seal of Righteousness"] = "รฅยผยบรฅล’โ€“รฆยญยฃรคยนโ€ฐรฅล“ยฃรฅยยฐ", + ["Improved Seal of the Crusader"] = "รฅยผยบรฅล’โ€“รฅยยรฅยญโ€”รฅโ€ โ€บรฅล“ยฃรฅยยฐ", + ["Improved Searing Pain"] = "รฅยผยบรฅล’โ€“รงยยผรงฦ’ยญรคยนโ€นรงโ€”โ€บ", + ["Improved Searing Totem"] = "รฅยผยบรฅล’โ€“รงยยผรงฦ’ยญรฅโ€บยพรจโ€ฆยพ", + ["Improved Serpent Sting"] = "รฅยผยบรฅล’โ€“รฆยฏโ€™รจโ€บโ€กรฉโ€™โ€ฐรฅห†ยบ", + ["Improved Shadow Bolt"] = "รฅยผยบรฅล’โ€“รฆลกโ€”รฅยฝยฑรงยฎยญ", + ["Improved Shadow Word: Pain"] = "รฅยผยบรฅล’โ€“รฆลกโ€”รจยจโ‚ฌรฆล“ยฏรฏยผลกรงโ€”โ€บ", + ["Improved Shield Bash"] = "รฅยผยบรฅล’โ€“รงโ€บยพรฅโ€กยป", + ["Improved Shield Block"] = "รฅยผยบรฅล’โ€“รงโ€บยพรงโ€ฐล’รฆย ยผรฆล’ยก", + ["Improved Shield Wall"] = "รฅยผยบรฅล’โ€“รงโ€บยพรฅยขโ„ข", + ["Improved Shred"] = "รฅยผยบรฅล’โ€“รฆโ€™โ€ขรงยขลฝ", + ["Improved Sinister Strike"] = "รฅยผยบรฅล’โ€“รฉโ€šยชรฆยยถรฆโ€ยปรฅโ€กยป", + ["Improved Slam"] = "รฅยผยบรฅล’โ€“รงล’โ€บรฅโ€กยป", + ["Improved Slice and Dice"] = "รฅยผยบรฅล’โ€“รฅห†โ€กรฅโ€ฐยฒ", + ["Improved Spellstone"] = "รฅยผยบรฅล’โ€“รฆยณโ€ขรฆล“ยฏรงลธยณ", + ["Improved Sprint"] = "รฅยผยบรฅล’โ€“รงโ€“ยพรจยทโ€˜", + ["Improved Starfire"] = "รฅยผยบรฅล’โ€“รฆหœลธรงยยซรฆล“ยฏ", + ["Improved Stoneclaw Totem"] = "รฅยผยบรฅล’โ€“รงลธยณรงห†ยชรฅโ€บยพรจโ€ฆยพ", + ["Improved Stoneskin Totem"] = "รฅยผยบรฅล’โ€“รงลธยณรจโ€šยครฅโ€บยพรจโ€ฆยพ", + ["Improved Strength of Earth Totem"] = "รฅยผยบรฅล’โ€“รฅยคยงรฅล“ยฐรคยนโ€นรฅล โ€บรฅโ€บยพรจโ€ฆยพ", + ["Improved Succubus"] = "รฅยผยบรฅล’โ€“รฉยญโ€ฆรฉยญโ€", + ["Improved Sunder Armor"] = "รฅยผยบรฅล’โ€“รงย ยดรงโ€ยฒรฆโ€ยปรฅโ€กยป", + ["Improved Taunt"] = "รฅยผยบรฅล’โ€“รฅหœยฒรจยฎยฝ", + ["Improved Thorns"] = "รฅยผยบรฅล’โ€“รจยโ€ รฆยฃหœรฆล“ยฏ", + ["Improved Thunder Clap"] = "รฅยผยบรฅล’โ€“รฉโ€บยทรฉล“โ€ รคยธโ‚ฌรฅโ€กยป", + ["Improved Tranquility"] = "รฅยผยบรฅล’โ€“รฅยฎยรฉยโ„ข", + ["Improved Vampiric Embrace"] = "รฅยผยบรฅล’โ€“รฅยยธรจยกโ‚ฌรฉยฌยผรงลกโ€žรฆโ€นยฅรฆล ยฑ", + ["Improved Vanish"] = "รฅยผยบรฅล’โ€“รฆยถห†รฅยคยฑ", + ["Improved Voidwalker"] = "รฅยผยบรฅล’โ€“รจโ„ขลกรงยฉยบรจยกล’รจโ‚ฌโ€ฆ", + ["Improved Windfury Weapon"] = "รฅยผยบรฅล’โ€“รฉยฃลฝรฆโ‚ฌโ€™รฆยญยฆรฅโ„ขยจ", + ["Improved Wing Clip"] = "รฅยผยบรฅล’โ€“รฆโ€˜โ€รงยปล ", + ["Improved Wrath"] = "รฅยผยบรฅล’โ€“รฆโ€žยครฆโ‚ฌโ€™", + ["Incinerate"] = "รงโ€žลกรงฦ’ยง", + ["Inferno"] = "รฅล“ยฐรงโ€นยฑรงยยซ", + ["Initiative"] = "รฅโ€ฆห†รฅยโ€˜รฅห†ยถรคยบยบ", + ["Inner Fire"] = "รฅยฟฦ’รงยยตรคยนโ€นรงยยซ", + ["Inner Focus"] = "รฅยฟฦ’รงยยตรคยธโ€œรฆยณยจ", + ["Innervate"] = "รฆยฟโ‚ฌรฆยดยป", + ["Insect Swarm"] = "รจโ„ขยซรงยพยค", + ["Inspiration"] = "รงยยตรฆโ€žลธ", + ["Instant Poison II"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ II", + ["Instant Poison III"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ III", + ["Instant Poison IV"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ IV", + ["Instant Poison V"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ V", + ["Instant Poison VI"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ VI", + ["Instant Poison"] = "รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจยยฏ", + ["Intensity"] = "รฅยผยบรงฦ’ห†", + ["Intercept"] = "รฆโ€นยฆรฆห†ยช", + ["Intercept Stun"] = "รฆโ€นยฆรฆห†ยชรฆหœยรจยฟยท", +-- ["Intervene"] = true, + ["Intimidating Shout"] = "รงย ยดรจฦ’โ€ รฆโ‚ฌโ€™รฅยยผ", + ["Intimidation"] = "รจฦ’ยรจยฟยซ", +-- ["Invisibility"] = true, + ["Iron Will"] = "รฅยลกรฅยฎลกรฆโ€žยรฅยฟโ€”", + ["Judgement of Command"] = "รฅโ€˜ยฝรคยปยครฅยฎยกรฅห†ยค", + ["Judgement of Justice"] = "รฅโ€ฆยฌรฆยญยฃรฅยฎยกรฅห†ยค", + ["Judgement of Light"] = "รฅโ€ฆโ€ฐรฆหœลฝรฅยฎยกรฅห†ยค", + ["Judgement of Righteousness"] = "รฆยญยฃรคยนโ€ฐรฅยฎยกรฅห†ยค", + ["Judgement of Wisdom"] = "รฆโ„ขยบรฆโ€ฆยงรฅยฎยกรฅห†ยค", + ["Judgement of the Crusader"] = "รฅยยรฅยญโ€”รฅโ€ โ€บรฅยฎยกรฅห†ยค", + ["Judgement"] = "รฅยฎยกรฅห†ยค", + ["Kick"] = "รจโ€žลกรจยธยข", + ["Kick - Silenced"] = "รจโ€žลกรจยธยข - รฆยฒโ€ฐรฉยปหœ", + ["Kidney Shot"] = "รจโ€šยพรฅโ€กยป", +-- ["Kill Command"] = true, + ["Killer Instinct"] = "รฆยโ‚ฌรฆห†ยฎรฆล“ยฌรจฦ’ยฝ", + ["Kodo Riding"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรงยงโ€˜รฅยคลกรฅโ€ฆยฝ", +-- ["Lacerate"] = true, + ["Lash of Pain"] = "รฅโ€ฐยงรงโ€”โ€บรฉลพยญรงยฌลพ", + ["Last Stand"] = "รงย ยดรฉโ€กล“รฆยฒโ€ฐรจห†ลธ", + ["Lasting Judgement"] = "รฆล’ยรคยนโ€ฆรฅยฎยกรฅห†ยค", + ["Lay on Hands"] = "รฅล“ยฃรงโ€“โ€”รฆล“ยฏ", + ["Leader of the Pack"] = "รฅโ€ฆยฝรงยพยครฉยขโ€ รจยขโ€“", + ["Leather"] = "รงลกยฎรงโ€ยฒ", + ["Leatherworking"] = "รฅห†ยถรงลกยฎ", + ["Lesser Heal"] = "รฆยฌยกรงยบยงรฆยฒยปรงโ€“โ€”รฆล“ยฏ", + ["Lesser Healing Wave"] = "รฆยฌยกรงยบยงรฆยฒยปรงโ€“โ€”รฆยณยข", + ["Lesser Invisibility"] = "รฆยฌยกรงยบยงรฉลกยรฅยฝยขรฆล“ยฏ", + ["Lethal Shots"] = "รฅยคยบรฅโ€˜ยฝรฅยฐโ€žรฅโ€กยป", + ["Lethality"] = "รจโ€กยดรฅโ€˜ยฝรฅยยทรจยขยญ", + ["Levitate"] = "รฆยผโ€šรฆยตยฎ", + ["Libram"] = "รฅล“ยฃรงโ€ฐยฉ", +-- ["Lifebloom"] = true, + ["Life Tap"] = "รงโ€ลธรฅโ€˜ยฝรฅห†โ€ รฆยตย", + ["Lifegiving Gem"] = true, + ["Lightning Bolt"] = "รฉโ€”ยชรงโ€ยตรงยฎยญ", + ["Lightning Breath"] = "รฉโ€”ยชรงโ€ยตรฅยยรฆยยฏ", + ["Lightning Mastery"] = "รฉโ€”ยชรงโ€ยตรฆลฝล’รฆยยก", + ["Lightning Reflexes"] = "รฉโ€”ยชรงโ€ยตรฅยยรฅยฐโ€ž", + ["Lightning Shield"] = "รฉโ€”ยชรงโ€ยตรฆล ยครงโ€บยพ", + ["Lightwell Renew"] = "รฅโ€ฆโ€ฐรฆหœลฝรคยนโ€นรฆยณโ€ฐรฅโ€บลพรฅยคย", + ["Lightwell"] = "รฅโ€ฆโ€ฐรฆหœลฝรคยนโ€นรฆยณโ€ฐ", + ["Lockpicking"] = "รฅยผโ‚ฌรฉโ€ย", + ["Long Daze"] = "รฉโ€ขยฟรฆโ€”ยถรฉโ€”ยดรงล“ยฉรฆโ„ขโ€ข", + ["Mace Specialization"] = "รฉโ€ยครงยฑยปรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Mace Stun Effect"] = "รฉโ€ยครฅโ€กยปรฆหœยรจยฟยทรฆโ€ขห†รฆลพล“", + ["Mage Armor"] = "รฉยญโ€รงโ€ยฒรฆล“ยฏ", + ["Magma Totem"] = "รงโ€ โ€รฅยฒยฉรฅโ€บยพรจโ€ฆยพ", + ["Mail"] = "รฉโ€ยรงโ€ยฒ", +-- ["Maim"] = true, + ["Malice"] = "รฆยยถรฆโ€žย", + ["Mana Burn"] = "รฆยณโ€ขรฅล โ€บรงโ€กฦ’รงฦ’ยง", + ["Mana Shield"] = "รฆยณโ€ขรฅล โ€บรฆล ยครงโ€บยพ", + ["Mana Spring Totem"] = "รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยณโ€ฐรฅโ€บยพรจโ€ฆยพ", + ["Mana Tide Totem"] = "รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยฝยฎรฅโ€บยพรจโ€ฆยพ", + ["Mangle"] = "รฅโ€ฐยฒรงยขลฝ", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = "รฉโ€กลฝรฆโ‚ฌยงรฅยยฐรจยฎยฐ", + ["Martyrdom"] = "รฆยฎโ€ฐรฉลกยพ", +-- ["Mass Dispel"] = true, + ["Master Demonologist"] = "รฆยยถรฉยญโ€รฅยญยฆรจยฏโ€ รฅยคยงรฅยธห†", + ["Master Summoner"] = "รฅยยฌรฅโ€ยครฅยคยงรฅยธห†", + ["Master of Deception"] = "รฆยฌยบรจยฏห†รฉยซหœรฆโ€ฐโ€น", + ["Maul"] = "รฆยงล’รฅโ€กยป", + ["Mechanostrider Piloting"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรฆล“ยบรฆยขยฐรฉโ„ขโ€ รจยกล’รฉยธลธ", + ["Meditation"] = "รฅโ€ ยฅรฆฦ’ยณ", + ["Melee Specialization"] = "รจยฟโ€˜รฆห†หœรคยธโ€œรงยฒยพ", + ["Mend Pet"] = "รฆยฒยปรงโ€“โ€”รฅยฎย รงโ€ฐยฉ", + ["Mental Agility"] = "รงยฒยพรงยฅลพรฆโ€ขยรฉโ€ย", + ["Mental Strength"] = "รฅยฟฦ’รงยยตรคยนโ€นรฅล โ€บ", + ["Mind Blast"] = "รฅยฟฦ’รงยยตรฉล“โ€กรงห†โ€ ", + ["Mind Control"] = "รงยฒยพรงยฅลพรฆลฝยงรฅห†ยถ", + ["Mind Flay"] = "รงยฒยพรงยฅลพรฉลพยญรงยฌลพ", + ["Mind Soothe"] = "รฅยฎโ€ฐรฆล ลกรฅยฟฦ’รงยยต", + ["Mind Vision"] = "รฅยฟฦ’รงยยตรจยงโ€ รงโ€ขล’", + ["Mind-numbing Poison II"] = "รฉยบยปรงโ€”ยนรฆยฏโ€™รจยยฏ II", + ["Mind-numbing Poison III"] = "รฉยบยปรงโ€”ยนรฆยฏโ€™รจยยฏ III", + ["Mind-numbing Poison"] = "รฉยบยปรงโ€”ยนรฆยฏโ€™รจยยฏ", + ["Mining"] = "รฉโ€กโ€กรงลธยฟ", +-- ["Misdirection"] = true, + ["Mocking Blow"] = "รฆฦ’ยฉรฆห†โ€™รงโ€”โ€บรฅโ€กยป", +-- ["Molten Armor"] = true, + ["Mongoose Bite"] = "รงล’ยซรฉยผยฌรฆโ€™โ€ขรฅโ€™ยฌ", + ["Monster Slaying"] = "รฆโ‚ฌยชรงโ€ฐยฉรฆยโ‚ฌรฆโ€ฐโ€น", + ["Moonfire"] = "รฆล“ห†รงยยซรฆล“ยฏ", + ["Moonfury"] = "รฆล“ห†รฆโ‚ฌโ€™", + ["Moonglow"] = "รฆล“ห†รฅโ€ฆโ€ฐ", + ["Moonkin Aura"] = "รฆลพยญรฅโ€ฆยฝรฅโ€ฆโ€ฐรงลฝยฏ", + ["Moonkin Form"] = "รฆลพยญรฅโ€ฆยฝรฅยฝยขรฆโ‚ฌย", + ["Mortal Shots"] = "รจโ€กยดรฆยญยปรฅยฐโ€žรฅโ€กยป", + ["Mortal Strike"] = "รจโ€กยดรฆยญยปรฆโ€ฐโ€œรฅโ€กยป", + ["Multi-Shot"] = "รฅยคลกรฉโ€กยรฅยฐโ€žรฅโ€กยป", + ["Murder"] = "รจยฐโ€นรฆยโ‚ฌ", +-- ["Mutilate"] = true, + ["Natural Armor"] = "รจโ€กยชรงโ€žยถรฆล ยครงโ€ยฒ", + ["Natural Shapeshifter"] = "รจโ€กยชรงโ€žยถรฅยหœรฅยฝยข", + ["Natural Weapons"] = "รฆยญยฆรฅโ„ขยจรฅยนยณรจยกยก", + ["Nature Resistance Totem"] = "รจโ€กยชรงโ€žยถรฆล โ€”รฆโ‚ฌยงรฅโ€บยพรจโ€ฆยพ", + ["Nature Resistance"] = "รจโ€กยชรงโ€žยถรฆล โ€”รฆโ‚ฌยง", + ["Nature's Focus"] = "รจโ€กยชรงโ€žยถรฉโ€บโ€ รคยธยญ", + ["Nature's Grace"] = "รจโ€กยชรงโ€žยถรคยนโ€นรจยตย", + ["Nature's Grasp"] = "รจโ€กยชรงโ€žยถรคยนโ€นรฆยยก", + ["Nature's Reach"] = "รจโ€กยชรงโ€žยถรฅยปยถรคยผยธ", + ["Nature's Swiftness"] = "รจโ€กยชรงโ€žยถรจยฟโ€ฆรฆยยท", + ["Nightfall"] = "รฅยคล“รฅยนโ€ข", + ["Omen of Clarity"] = "รฆยธโ€ฆรฆโ„ขยฐรฉยขโ€žรฅโ€ฆโ€ ", + ["One-Handed Axes"] = "รฅยโ€ขรฆโ€ฐโ€นรฆโ€“ยง", + ["One-Handed Maces"] = "รฅยโ€ขรฆโ€ฐโ€นรฉโ€ยค", + ["One-Handed Swords"] = "รฅยโ€ขรฆโ€ฐโ€นรฅโ€ฐโ€˜", + ["One-Handed Weapon Specialization"] = "รฅยโ€ขรฆโ€ฐโ€นรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Opening - No Text"] = "รฆโ€ฐโ€œรฅยผโ‚ฌ - No Text", --not sure what this is + ["Opening"] = "รฆโ€ฐโ€œรฅยผโ‚ฌ", + ["Opportunity"] = "รคยผยบรฆล“ยบรจโ‚ฌล’รฅล ยจ", + ["Overpower"] = "รฅลฝโ€นรฅห†ยถ", +-- ["Pain Suppression"] = true, + ["Paranoia"] = "รฅยคลกรงโ€“โ€˜", + ["Parry"] = "รฆโ€นโ€บรฆลพยถ", + ["Pathfinding"] = "รฅยฏยปรจยทยฏ", + ["Perception"] = "รฆโ€žลธรงลธยฅ", + ["Permafrost"] = "รฆลพยรฅยฏโ€™รฅโ€ ยฐรฉล“ล“", + ["Pet Aggression"] = "รฅยฎย รงโ€ฐยฉรฅยฅยฝรฆโ€“โ€”", + ["Pet Hardiness"] = "รฅยฎย รงโ€ฐยฉรจโ‚ฌยรคยนโ€ฆ", + ["Pet Recovery"] = "รฅยฎย รงโ€ฐยฉรฆยยขรฅยคย", + ["Pet Resistance"] = "รฅยฎย รงโ€ฐยฉรฆล โ€”รฉยญโ€", + ["Phase Shift"] = "รงโ€บยธรคยฝยรฅยหœรฆยยข", + ["Pick Lock"] = "รฅยผโ‚ฌรฉโ€ย", + ["Pick Pocket"] = "รฅยยทรงยชฦ’", + ["Piercing Howl"] = "รฅห†ยบรจโ‚ฌยณรฆโ‚ฌโ€™รฅยยผ", + ["Piercing Ice"] = "รฅห†ยบรฉยชยจรฅยฏโ€™รฅโ€ ยฐ", + ["Plate Mail"] = "รฆยยฟรงโ€ยฒ", + ["Poison Cleansing Totem"] = "รงยฅโ€บรงโ€”โ€ฆรฅโ€บยพรจโ€ฆยพ", + ["Poisons"] = "รฆยฏโ€™รจยยฏ", + ["Polearm Specialization"] = "รฉโ€ขยฟรฆลธโ€žรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Polearms"] = "รฉโ€ขยฟรฆลธโ€žรฆยญยฆรฅโ„ขยจ", + ["Polymorph"] = "รฅยหœรฅยฝยขรฆล“ยฏ", + ["Polymorph: Pig"] = "รฅยหœรฅยฝยขรฆล“ยฏรฏยผลกรงล’ยช", + ["Polymorph: Turtle"] = "รฅยหœรฅยฝยขรฆล“ยฏรฏยผลกรฉยพลธ", + ["Portal: Darnassus"] = "รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรจยพยพรงยบยณรจโ€นยรฆโ€“ยฏ", + ["Portal: Ironforge"] = " รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรฉโ€œยรงโ€šโ€ฐรฅย ยก", + ["Portal: Orgrimmar"] = "รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรฅยฅยฅรฆย ยผรงโ€˜ลพรงลฝโ€บ", + ["Portal: Stormwind"] = "รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรฆลกยดรฉยฃลฝรฅลธลฝ", + ["Portal: Thunder Bluff"] = "รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรฉโ€บยทรฉล“โ€ รฅยดโ€“", + ["Portal: Undercity"] = "รคยผย รฉโ‚ฌยรฉโ€”ยจรฏยผลกรฅยนยฝรฆลกโ€”รฅลธลฝ", + ["Pounce Bleed"] = "รงยชยรจยขยญ", + ["Pounce"] = "รงยชยรจยขยญ", + ["Power Infusion"] = "รจฦ’ยฝรฉโ€กยรงยล’รฆยณยจ", + ["Power Word: Fortitude"] = "รงล“ลธรจยจโ‚ฌรฆล“ยฏรฏยผลกรฉลธยง", + ["Power Word: Shield"] = "รงล“ลธรจยจโ‚ฌรฆล“ยฏรฏยผลกรงโ€บยพ", + ["Prayer of Fortitude"] = "รฅยลกรฉลธยงรงยฅยทรจยจโ‚ฌ", + ["Prayer of Healing"] = "รฆยฒยปรงโ€“โ€”รงยฅยทรจยจโ‚ฌ", +-- ["Prayer of Mending"] = true, + ["Prayer of Spirit"] = "รงยฒยพรงยฅลพรงยฅยทรจยจโ‚ฌ", + ["Prayer of Shadow Protection"] = "รฆลกโ€”รฅยฝยฑรฉหœยฒรฆล ยครงยฅยทรจยจโ‚ฌ", + ["Precision"] = "รงยฒยพรงยกยฎ", + ["Predatory Strikes"] = "รงล’โ€บรฅโ€ฆยฝรฆโ€ยปรฅโ€กยป", + ["Premeditation"] = "รฉยขโ€žรจยฐโ€น", + ["Preparation"] = "รคยผยบรฆล“ยบรฅยพโ€ฆรฅยโ€˜", + ["Presence of Mind"] = "รฆยฐโ€รฅยฎลกรงยฅลพรฉโ€”ยฒ", + ["Primal Fury"] = "รฅลฝลธรฅยงโ€นรงโ€นโ€šรฆโ‚ฌโ€™", + ["Prowl"] = "รฆยฝล“รคยผย", + ["Psychic Scream"] = "รฅยฟฦ’รงยยตรฅยฐโ€“รฅโ€ขยธ", + ["Pummel"] = "รฆโ€นยณรฅโ€กยป", + ["Purge"] = "รฅโ€กโ‚ฌรฅล’โ€“รฆล“ยฏ", + ["Purification"] = "รฅโ€กโ‚ฌรฅล’โ€“", + ["Purify"] = "รงยบยฏรฅโ€กโ‚ฌรฆล“ยฏ", + ["Pursuit of Justice"] = "รฆยญยฃรคยนโ€ฐรจยฟยฝรฅโ€กยป", + ["Pyroblast"] = "รงโ€šลฝรงห†โ€ รฆล“ยฏ", + ["Pyroclasm"] = "รงยยซรงโ€žยฐรฅโ€ ยฒรฆโ€™ลพ", + ["Quick Shots"] = "รฅยฟยซรฉโ‚ฌลธรฅยฐโ€žรฅโ€กยป", + ["Quickness"] = "รจยฟโ€ฆรฆยยท", + ["Rain of Fire"] = "รงยยซรงโ€žยฐรคยนโ€นรฉโ€บยจ", + ["Rake"] = "รฆโ€ฐยซรฅโ€กยป", +-- ["Rampage"] = true, + ["Ram Riding"] = " รฉยชโ€˜รฆล“ยฏรฏยผลกรงยพล ", + ["Ranged Weapon Specialization"] = "รจยฟล“รงยจโ€นรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Rapid Concealment"] = "รจยฟโ€ฆรฉโ‚ฌลธรฉลกยรจโ€ยฝ", + ["Rapid Fire"] = "รฆโ‚ฌยฅรฉโ‚ฌลธรฅยฐโ€žรฅโ€กยป", + ["Raptor Riding"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรจยฟโ€ฆรงล’โ€บรฉยพโ„ข", + ["Raptor Strike"] = "รงล’โ€บรงยฆยฝรคยธโ‚ฌรฅโ€กยป", + ["Ravage"] = "รฆยฏยรงยยญ", + ["Readiness"] = "รฅโ€กโ€ รฅยคโ€กรฅยฐยฑรงยปยช", + ["Rebirth"] = "รฅยคยรงโ€ลธ", + ["Reckless Charge"] = "รฆโ€”ย รงโ€ขยรฅโ€ ยฒรฉโ€โ€น", + ["Recklessness"] = "รฉยฒยรจลฝยฝ", + ["Reckoning"] = "รฆยธโ€ฆรงยฎโ€”", + ["Redemption"] = "รฆโ€ขโ€˜รจยตลฝ", + ["Redoubt"] = "รงโ€บยพรงโ€ฐล’รฅยฃยรฅลพโ€™", + ["Reflection"] = "รฅยยรฅยฐโ€ž", + ["Regeneration"] = "รฅโ€บลพรฅยคย", + ["Regrowth"] = "รฆโ€žห†รฅยห†", + ["Reincarnation"] = "รฅยคยรงโ€ลธ", + ["Rejuvenation"] = "รฅโ€บลพรฆหœยฅรฆล“ยฏ", + ["Relentless Strikes"] = "รฆโ€”ย รฆฦ’โ€ฆรฆโ€ฐโ€œรฅโ€กยป", + ["Remorseless"] = "รฅโ€ ยทรฉโ€ฆยท", + ["Remorseless Attacks"] = "รฅโ€ ยทรฉโ€ฆยทรฆโ€ยปรฅโ€กยป", + ["Remove Curse"] = "รจยงยฃรฉโ„ขยครจยฏโ€ฆรฅโ€™โ€™", + ["Remove Insignia"] = "รจยงยฃรฉโ„ขยครฅยพยฝรจยฎยฐ", + ["Remove Lesser Curse"] = "รจยงยฃรฉโ„ขยครฆยฌยกรงยบยงรจยฏโ€ฆรฅโ€™โ€™", + ["Rend"] = "รฆโ€™โ€ขรจยฃโ€š", + ["Renew"] = "รฆยยขรฅยคย", + ["Repentance"] = "รฅยฟยรฆโ€šโ€", + ["Resurrection"] = "รฅยคยรฆยดยป", + ["Retaliation"] = "รฅยยรฅโ€กยปรฉยฃลฝรฆลกยด", + ["Retribution Aura"] = "รฆฦ’ยฉรงยฝลกรฅโ€ฆโ€ฐรงลฝยฏ", + ["Revenge Stun"] = "รฅยคยรคยปโ€กรฆหœยรจยฟยท", + ["Revenge"] = "รฅยคยรคยปโ€ก", + ["Reverberation"] = "รฅโ€บลพรฅโ€œย", + ["Revive Pet"] = "รฅยคยรฆยดยปรฅยฎย รงโ€ฐยฉ", +-- ["Righteous Defense"] = true, + ["Righteous Fury"] = "รฆยญยฃรคยนโ€ฐรคยนโ€นรฆโ‚ฌโ€™", + ["Rip"] = "รฆโ€™โ€ขรฆโ€ฐยฏ", + ["Riposte"] = "รจยฟหœรฅโ€กยป", + ["Ritual of Doom Effect"] = "รฆล“ยซรฆโ€”ยฅรคยปยชรฅยผยรฆโ€ขห†รฆลพล“", + ["Ritual of Doom"] = "รฆล“ยซรฆโ€”ยฅรคยปยชรฅยผย", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = "รฅยยฌรฅโ€ยครคยปยชรฅยผย", + ["Rockbiter Weapon"] = "รงลธยณรฅล’โ€“รฆยญยฆรฅโ„ขยจ", + ["Rogue Passive"] = "รงโ€บโ€”รจยดยผรจยขยซรฅล ยจรฆโ€ขห†รฆลพล“", -- not sure + ["Rough Sharpening Stone"] = "รฅล ยฃรจยดยจรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Ruin"] = "รฆยฏยรงยยญ", + ["Rupture"] = "รฅโ€ฐยฒรจยฃโ€š", + ["Ruthlessness"] = "รฆโ€”ย รฆฦ’โ€ฆ", + ["Sacrifice"] = "รงโ€ฐยบรงโ€ฐยฒ", + ["Safe Fall"] = "รฅยฎโ€ฐรฅโ€ฆยจรฉโ„ขยรจยยฝ", + ["Sanctity Aura"] = "รฅล“ยฃรฆยดยรฅโ€ฆโ€ฐรงลฝยฏ", + ["Sap"] = "รฉโ€”ยทรฆยฃย", + ["Savage Fury"] = "รฉโ€กลฝรจโ€บยฎรฆลกยดรฆโ‚ฌโ€™", + ["Savage Strikes"] = "รฉโ€กลฝรจโ€บยฎรฆโ€ฐโ€œรฅโ€กยป", + ["Scare Beast"] = "รฆยยรฅยโ€œรฉโ€กลฝรฅโ€ฆยฝ", + ["Scatter Shot"] = "รฉยฉยฑรฆโ€ขยฃรฅยฐโ€žรฅโ€กยป", + ["Scorch"] = "รงยยผรงฦ’ยง", + ["Scorpid Poison"] = "รจยลฝรฆยฏโ€™", + ["Scorpid Sting"] = "รฆยฏโ€™รจยลฝรฉโ€™โ€ฐรฅห†ยบ", + ["Screech"] = "รฅยฐโ€“รฅโ€ขยธ", + ["Seal Fate"] = "รฅยฐยรฅยยฐรฅโ€˜ยฝรจยฟย", +-- ["Seal of Blood"] = true, + ["Seal of Command"] = "รฅโ€˜ยฝรคยปยครฅล“ยฃรฅยยฐ", + ["Seal of Justice"] = "รฅโ€ฆยฌรฆยญยฃรฅล“ยฃรฅยยฐ", + ["Seal of Light"] = "รฅโ€ฆโ€ฐรฆหœลฝรฅล“ยฃรฅยยฐ", + ["Seal of Righteousness"] = "รฆยญยฃรคยนโ€ฐรฅล“ยฃรฅยยฐ", + ["Seal of Wisdom"] = "รฆโ„ขยบรฆโ€ฆยงรฅล“ยฃรฅยยฐ", + ["Seal of the Crusader"] = "รฅยยรฅยญโ€”รฅโ€ โ€บรฅล“ยฃรฅยยฐ", +-- ["Seal of Vengeance"] = true, + ["Searing Light"] = "รงยยผรงฦ’ยญรคยนโ€นรฅโ€ฆโ€ฐ", + ["Searing Pain"] = "รงยยผรงฦ’ยญรคยนโ€นรงโ€”โ€บ", + ["Searing Totem"] = "รงยยผรงฦ’ยญรฅโ€บยพรจโ€ฆยพ", +-- ["Second Wind"] = true, + ["Seduction"] = "รจยฏยฑรฆฦ’โ€˜", +-- ["Seed of Corruption"] = true, + ["Sense Demons"] = "รฆโ€žลธรงลธยฅรฆยยถรฉยญโ€", + ["Sense Undead"] = "รฆโ€žลธรงลธยฅรคยบยกรงยยต", + ["Sentry Totem"] = "รฅยฒโ€”รฅโ€œยจรฅโ€บยพรจโ€ฆยพ", + ["Serpent Sting"] = "รฆยฏโ€™รจโ€บโ€กรฉโ€™โ€ฐรฅห†ยบ", + ["Setup"] = "รจยฐฦ’รฆโ€ขยด", + ["Shackle Undead"] = "รฆยลธรงยผลกรคยบยกรงยยต", + ["Shadow Affinity"] = "รฆลกโ€”รฅยฝยฑรคยบยฒรฅโ€™ล’", + ["Shadow Bolt"] = "รฆลกโ€”รฅยฝยฑรงยฎยญ", + ["Shadow Focus"] = "รฆลกโ€”รฅยฝยฑรฉโ€บโ€ รคยธยญ", + ["Shadow Mastery"] = "รฆลกโ€”รฅยฝยฑรฆลฝล’รฆยยก", + ["Shadow Protection"] = "รฆลกโ€”รฅยฝยฑรฉหœยฒรฆล ยค", + ["Shadow Reach"] = "รฆลกโ€”รฅยฝยฑรฅยปยถรคยผยธ", + ["Shadow Resistance Aura"] = "รฆลกโ€”รฅยฝยฑรฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงลฝยฏ", + ["Shadow Resistance"] = "รฆลกโ€”รฅยฝยฑรฆล โ€”รฆโ‚ฌยง", + ["Shadow Trance"] = "รฆลกโ€”รฅยฝยฑรฅโ€ ยฅรฆโ‚ฌย", + ["Shadow Vulnerability"] = "รฆลกโ€”รฅยฝยฑรฆหœโ€œรคยผยค", + ["Shadow Ward"] = "รฉหœยฒรฆล ยครฆลกโ€”รฅยฝยฑรงยปโ€œรงโ€ขล’", + ["Shadow Weaving"] = "รฆลกโ€”รฅยฝยฑรคยนโ€นรฆยณยข", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = "รฆลกโ€”รจยจโ‚ฌรฆล“ยฏรฏยผลกรงโ€”โ€บ", + ["Shadowburn"] = "รฆลกโ€”รฅยฝยฑรงยยผรงฦ’ยง", +-- ["Shadowfiend"] = true, + ["Shadowform"] = "รฆลกโ€”รฅยฝยฑรฅยฝยขรฆโ‚ฌย", +-- ["Shadowfury"] = true, + ["Shadowguard"] = "รฆลกโ€”รฅยฝยฑรฅยฎห†รฅยยซ", + ["Shadowmeld Passive"] = "รฅยฝยฑรฉยย", + ["Shadowmeld"] = "รฅยฝยฑรฉยย", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = "รฉโ€โ€นรฅห†ยฉรฅโ€ฆยฝรงห†ยช", + ["Shatter"] = "รงยขลฝรฅโ€ ยฐ", + ["Sheep"] = "รงยปยตรงยพล ", --not sure + ["Shell Shield"] = "รงโ€ยฒรฅยฃยณรฆล ยครงโ€บยพ", + ["Shield Bash"] = "รงโ€บยพรฅโ€กยป", + ["Shield Bash - Silenced"] = "รงโ€บยพรฅโ€กยป - รฆยฒโ€ฐรฉยปหœ", + ["Shield Block"] = "รงโ€บยพรงโ€ฐล’รฆย ยผรฆล’ยก", + ["Shield Slam"] = "รงโ€บยพรงโ€ฐล’รงล’โ€บรฅโ€กยป", + ["Shield Specialization"] = "รงโ€บยพรงโ€ฐล’รคยธโ€œรงยฒยพ", + ["Shield Wall"] = "รงโ€บยพรฅยขโ„ข", + ["Shield"] = "รงโ€บยพรงโ€ฐล’", +-- ["Shiv"] = true, + ["Shoot Bow"] = "รฅยผโ€œรฅยฐโ€žรฅโ€กยป", + ["Shoot Crossbow"] = "รฅยผยฉรฅยฐโ€žรฅโ€กยป", + ["Shoot Gun"] = "รฆลพยชรฆยขยฐรฅยฐโ€žรฅโ€กยป", + ["Shoot"] = "รฅยฐโ€žรฅโ€กยป", + ["Shred"] = "รฆโ€™โ€ขรงยขลฝ", + ["Silence"] = "รฆยฒโ€ฐรฉยปหœ", +-- ["Silencing Shot"] = true, + ["Silent Resolve"] = "รฆโ€”ย รฅยฃยฐรฆยถห†รฉโ‚ฌโ‚ฌ", + ["Sinister Strike"] = "รฉโ€šยชรฆยยถรฆโ€ยปรฅโ€กยป", + ["Siphon Life"] = "รงโ€ลธรฅโ€˜ยฝรจโ„ขยนรฅยยธ", + ["Skinning"] = "รฅโ€ฐยฅรงลกยฎ", + ["Slam"] = "รงล’โ€บรฅโ€กยป", + ["Sleep"] = "รฆยฒโ€ฐรงยยก", --not so sure + ["Slice and Dice"] = "รฅห†โ€กรฅโ€ฐยฒ", +-- ["Slow"] = true, + ["Slow Fall"] = "รงยผโ€œรจยยฝรฆล“ยฏ", + ["Smelting"] = "รงโ€ โ€รงโ€šยผ", + ["Smite"] = "รฆฦ’ยฉรฅโ€กยป", +-- ["Snake Trap"] = true, + ["Solid Sharpening Stone"] = "รฅยลกรฅโ€บยบรงลกโ€žรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Soothe Animal"] = "รฅยฎโ€ฐรฆล ลกรฅล ยจรงโ€ฐยฉ", + ["Soothing Kiss"] = "รฅยฎโ€ฐรฆล ลกรคยนโ€นรฅยยป", + ["Soul Fire"] = "รงยยตรฉยญโ€šรคยนโ€นรงยยซ", + ["Soul Link"] = "รงยยตรฉยญโ€šรฉโ€œยพรฆลฝยฅ", + ["Soul Siphon"] = "รงยยตรฉยญโ€šรจโ„ขยนรฅยยธ", +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"] = "รงยยตรฉยญโ€šรงลธยณรฅยคยรฆยดยป", + ["Spell Lock"] = "รฆยณโ€ขรฆล“ยฏรฅยฐยรฉโ€ย", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"] = "รฆยณโ€ขรฆล“ยฏรฅยฑยรฉลกล“", + ["Spirit Bond"] = "รงยยตรฉยญโ€šรจยฟลพรฆลฝยฅ", + ["Spirit Tap"] = "รงยฒยพรงยฅลพรฅห†โ€ รฆยตย", + ["Spirit of Redemption"] = "รฆโ€ขโ€˜รจยตลฝรคยนโ€นรฉยญโ€š", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = "รงยฒยพรงยฅลพรฉโ€บโ€ รคยธยญ", + ["Spiritual Guidance"] = "รงยฒยพรงยฅลพรฆล’โ€กรฅยผโ€ข", + ["Spiritual Healing"] = "รงยฒยพรงยฅลพรฆยฒยปรงโ€“โ€”", + ["Sprint"] = "รงโ€“ยพรจยทโ€˜", +-- ["Stance Mastery"] = true, + ["Starfire"] = "รฆหœลธรงยยซรฆล“ยฏ", + ["Starfire Stun"] = "รฆหœลธรงยยซรฆหœยรจยฟยท", + ["Starshards"] = "รฆหœลธรจยพยฐรงยขลฝรงโ€ฐโ€ก", + ["Staves"] = "รฆยณโ€ขรฆยโ€“", +-- ["Steady Shot"] = true, + ["Stealth"] = "รฆยฝล“รจยกล’", + ["Stoneclaw Totem"] = "รงลธยณรงห†ยชรฅโ€บยพรจโ€ฆยพ", + ["Stoneform"] = "รงลธยณรฅฦ’ยรฅยฝยขรฆโ‚ฌย", + ["Stoneskin Totem"] = "รงลธยณรจโ€šยครฅโ€บยพรจโ€ฆยพ", + ["Stormstrike"] = "รฉยฃลฝรฆลกยดรฆโ€ฐโ€œรฅโ€กยป", + ["Strength of Earth Totem"] = "รฅยคยงรฅล“ยฐรคยนโ€นรฅล โ€บรฅโ€บยพรจโ€ฆยพ", + ["Stuck"] = "รฅยยกรฆยญยป", + ["Subtlety"] = "รฅยพยฎรฅยฆโ„ข", + ["Suffering"] = "รฅยโ€”รฉลกยพ", + ["Summon Charger"] = "รฅยยฌรฅโ€ยครฆห†หœรฉยฉยฌ", + ["Summon Dreadsteed"] = "รฅยยฌรฅโ€ยครฆยยรฆฦ’ยงรฆห†หœรฉยฉยฌ", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"] = "รฅยยฌรฅโ€ยครฅล“ยฐรงโ€นยฑรงล’ลฝรงล ยฌ", + ["Summon Felsteed"] = "รฅยยฌรฅโ€ยครฅล“ยฐรงโ€นยฑรฆห†หœรฉยฉยฌ", + ["Summon Imp"] = "รฅยยฌรฅโ€ยครฅยฐยรฉยฌยผ", + ["Summon Succubus"] = "รฅยยฌรฅโ€ยครฉยญโ€ฆรฉยญโ€", + ["Summon Voidwalker"] = "รฅยยฌรฅโ€ยครจโ„ขลกรงยฉยบรจยกล’รจโ‚ฌโ€ฆ", + ["Summon Warhorse"] = "รฅยยฌรฅโ€ยครฅโ€ โ€บรฉยฉยฌ", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"] = "รงย ยดรงโ€ยฒ", + ["Suppression"] = "รฅลฝโ€นรฅห†ยถ", + ["Surefooted"] = "รงยจยณรฅโ€บยบ", + ["Survivalist"] = "รงโ€ลธรฅยญหœรคยธโ€œรฅยฎยถ", + ["Sweeping Strikes"] = "รฆยจยชรฆโ€ฐยซรฆโ€ยปรฅโ€กยป", + ["Swiftmend"] = "รจยฟโ€ฆรฆยยทรฆยฒยปรฆโ€žห†", + ["Swipe"] = "รฆล’ยฅรฅโ€กยป", + ["Sword Specialization"] = "รฅโ€ฐโ€˜รงยฑยปรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Tactical Mastery"] = "รฆห†หœรฆล“ยฏรฆลฝล’รฆยยก", + ["Tainted Blood"] = "รจโ€ฆยรฅยยรคยนโ€นรจยกโ‚ฌ", + ["Tailoring"] = "รจยฃยรงยผย", + ["Tame Beast"] = "รฉยฉยฏรฆล“ยรฉโ€กลฝรฅโ€ฆยฝ", + ["Tamed Pet Passive"] = "รฉยฉยฏรฆล“ยรฅยฎย รงโ€ฐยฉรฏยผห†รจยขยซรฅล ยจรฏยผโ€ฐ", + ["Taunt"] = "รฅหœยฒรจยฎยฝ", + ["Teleport: Darnassus"] = "รคยผย รฉโ‚ฌยรฏยผลกรจยพยพรงยบยณรจโ€นยรฆโ€“ยฏ", + ["Teleport: Ironforge"] = "รคยผย รฉโ‚ฌยรฏยผลกรฉโ€œยรงโ€šโ€ฐรฅย ยก", + ["Teleport: Moonglade"] = "รคยผย รฉโ‚ฌยรฏยผลกรฆล“ห†รฅโ€ฆโ€ฐรฆลพโ€”รฅล“ยฐ", + ["Teleport: Orgrimmar"] = "รคยผย รฉโ‚ฌยรฏยผลกรฅยฅยฅรฆย ยผรงโ€˜ลพรงลฝโ€บ", + ["Teleport: Stormwind"] = "รคยผย รฉโ‚ฌยรฏยผลกรฆลกยดรฉยฃลฝรฅลธลฝ", + ["Teleport: Thunder Bluff"] = "รคยผย รฉโ‚ฌยรฏยผลกรฉโ€บยทรฉล“โ€ รฅยดโ€“", + ["Teleport: Undercity"] = "รคยผย รฉโ‚ฌยรฏยผลกรฅยนยฝรฆลกโ€”รฅลธลฝ", +-- ["The Beast Within"] = true, + ["The Human Spirit"] = "รคยบยบรงยฑยปรงยฒยพรฉยญโ€š", + ["Thick Hide"] = "รฅลฝลกรงลกยฎ", + ["Thorns"] = "รจยโ€ รฆยฃหœรฆล“ยฏ", + ["Throw"] = "รฆล โ€ขรฆลฝยท", + ["Throwing Specialization"] = "รฆล โ€ขรฆลฝยทรคยธโ€œรงยฒยพ", + ["Throwing Weapon Specialization"] = "รฆล โ€ขรฆลฝยทรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Thrown"] = "รฆล โ€ขรฆลฝยท", + ["Thunder Clap"] = "รฉโ€บยทรฉล“โ€ รคยธโ‚ฌรฅโ€กยป", + ["Thundering Strikes"] = "รฉโ€บยทรฉยธยฃรงล’โ€บรฅโ€กยป", + ["Thunderstomp"] = "รฉโ€บยทรฉล“โ€ รจยทยตรจยธย", + ["Tidal Focus"] = "รฆยฝยฎรฆยฑยรฉโ€บโ€ รคยธยญ", + ["Tidal Mastery"] = "รฆยฝยฎรฆยฑยรฆลฝล’รฆยยก", + ["Tiger Riding"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรจยฑยน", + ["Tiger's Fury"] = "รงล’โ€บรจโ„ขลฝรคยนโ€นรฆโ‚ฌโ€™", + ["Torment"] = "รฆล หœรงยฃยจ", + ["Totem"] = "รฅโ€บยพรจโ€ฆยพ", + -- ["Totem of Wrath"] = true, + ["Totemic Focus"] = "รฅโ€บยพรจโ€ฆยพรฉโ€บโ€ รคยธยญ", + ["Touch of Weakness"] = "รจโ„ขลกรฅยผยฑรคยนโ€นรจยงยฆ", + ["Toughness"] = "รฅยลกรฉลธยง", + ["Track Beasts"] = "รจยฟยฝรจยธยชรฉโ€กลฝรฅโ€ฆยฝ", + ["Track Demons"] = "รจยฟยฝรจยธยชรฆยยถรฉยญโ€", + ["Track Dragonkin"] = "รจยฟยฝรจยธยชรฉยพโ„ขรงยฑยป", + ["Track Elementals"] = "รจยฟยฝรจยธยชรฅโ€ฆฦ’รงยดย รงโ€ลธรงโ€ฐยฉ", + ["Track Giants"] = "รจยฟยฝรจยธยชรฅยทยจรคยบยบ", + ["Track Hidden"] = "รจยฟยฝรจยธยชรฉลกยรจโ€”ยรงโ€ลธรงโ€ฐยฉ", + ["Track Humanoids"] = "รจยฟยฝรจยธยชรคยบยบรฅลพโ€นรงโ€ลธรงโ€ฐยฉ", + ["Track Undead"] = "รจยฟยฝรจยธยชรคยบยกรงยยต", + ["Tranquil Air Totem"] = "รฅยฎยรฉยโ„ขรคยนโ€นรฉยฃลฝรฅโ€บยพรจโ€ฆยพ", + ["Tranquil Spirit"] = "รฅยฎยรฉยโ„ขรคยนโ€นรฉยญโ€š", + ["Tranquility"] = "รฅยฎยรฉยโ„ข", + ["Tranquilizing Shot"] = "รฅยฎยรงยฅลพรฅยฐโ€žรฅโ€กยป", + ["Trap Mastery"] = "รฉโ„ขยทรฉหœยฑรฆลฝล’รฆยยก", + ["Travel Form"] = "รฆโ€”โ€ฆรจยกล’รฅยฝยขรฆโ‚ฌย", +-- ["Tree of Life"] = true, + ["Tremor Totem"] = "รฆห†หœรฆย โ€”รฅโ€บยพรจโ€ฆยพ", + ["Tribal Leatherworking"] = "รฉฦ’ยจรฆโ€”ยรฅห†ยถรงลกยฎ", + ["Trueshot Aura"] = "รฅยผยบรฅโ€กยปรฅโ€ฆโ€ฐรงลฝยฏ", + ["Turn Undead"] = "รจยถโ€ฆรฅยบยฆรคยบยกรงยยต", + ["Two-Handed Axes and Maces"] = "รฅยล’รฆโ€ฐโ€นรฆโ€“ยงรฅโ€™ล’รฉโ€ยค", + ["Two-Handed Axes"] = "รฅยล’รฆโ€ฐโ€นรฆโ€“ยง", + ["Two-Handed Maces"] = "รฅยล’รฆโ€ฐโ€นรฉโ€ยค", + ["Two-Handed Swords"] = "รฆโ€”ย รฅโ€ฆโ€ฐรฆยณยฝรงลกโ€žรฅยล’รฅห†ฦ’รฅห†โ‚ฌ", + ["Two-Handed Weapon Specialization"] = "รฅยล’รฆโ€ฐโ€นรฆยญยฆรฅโ„ขยจรคยธโ€œรงยฒยพ", + ["Unarmed"] = "รฅยพโ€™รฆโ€ฐโ€น", + ["Unbreakable Will"] = "รฅยลกรฅยฎลกรฆโ€žยรฅยฟโ€”", + ["Unbridled Wrath Effect"] = "รฆโ‚ฌโ€™รคยธยรฅยยฏรฉยย", + ["Unbridled Wrath"] = "รฆโ‚ฌโ€™รคยธยรฅยยฏรฉยย", + ["Undead Horsemanship"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรฉยชยธรฉยชยจรฆห†หœรฉยฉยฌ", + ["Underwater Breathing"] = "รฆยฐยดรคยธโ€นรฅโ€˜ยผรฅยยธ", + ["Unending Breath"] = "รฉยญโ€รฆยยฏรฆล“ยฏ", + ["Unholy Power"] = "รฉโ€šยชรฆยยถรฅยผยบรฅล’โ€“", + ["Unleashed Fury"] = "รงโ€นโ€šรฆโ‚ฌโ€™รฉโ€กล รฆโ€ยพ", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"] = "รคยธยรงยยญรคยฟยกรคยปยฐ", + ["Vampiric Embrace"] = "รฅยยธรจยกโ‚ฌรฉยฌยผรงลกโ€žรฆโ€นยฅรฆล ยฑ", + ["Vanish"] = "รฆยถห†รฅยคยฑ", + ["Vanished"] = "รฆยถห†รฅยคยฑ", +-- ["Vampiric Touch"] = true, + ["Vengeance"] = "รฅยคยรคยปโ€ก", +-- ["Victory Rush"] = true, + ["Vigor"] = "รงยฒยพรฅล โ€บ", + ["Vile Poisons"] = "รฆยยถรฆโ‚ฌยงรฆยฏโ€™รจยยฏ", + ["Vindication"] = "รจยพยฉรฆล ยค", + ["Viper Sting"] = "รจยยฐรจโ€บโ€กรฉโ€™โ€ฐรฅห†ยบ", + ["Volley"] = "รคยนยฑรฅยฐโ€ž", + ["Wand Specialization"] = "รฉยญโ€รฆยโ€“รฆลฝล’รฆยยก", + ["Wands"] = "รฉยญโ€รฆยโ€“", + ["War Stomp"] = "รฆห†หœรคยบโ€ฐรจยทยตรจยธย", + ["Water Breathing"] = "รฆยฐยดรคยธโ€นรฅโ€˜ยผรฅยยธ", +-- ["Water Shield"] = true, + ["Water Walking"] = "รฆยฐยดรคยธล รจยกล’รจยตยฐ", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "รจโ„ขลกรฅยผยฑรงยยตรฉยญโ€š", + ["Weaponsmith"] = "รฆยญยฆรฅโ„ขยจรฉโ€ยปรฉโ‚ฌย รฅยธห†", + ["Whirlwind"] = "รฆโ€”โ€นรฉยฃลฝรฆโ€“ยฉ", + ["Will of the Forsaken"] = "รคยบยกรงยยตรฆโ€žยรฅยฟโ€”", + ["Windfury Totem"] = "รฉยฃลฝรฆโ‚ฌโ€™รฅโ€บยพรจโ€ฆยพ", + ["Windfury Weapon"] = "รฉยฃลฝรฆโ‚ฌโ€™รฆยญยฆรฅโ„ขยจ", + ["Windwall Totem"] = "รฉยฃลฝรฅยขโ„ขรฅโ€บยพรจโ€ฆยพ", + ["Wing Clip"] = "รฆโ€˜โ€รงยปล ", + ["Winter's Chill"] = "รฆยทยฑรฅโ€ ยฌรคยนโ€นรฅยฏโ€™", + ["Wisp Spirit"] = "รงยฒยพรงยยตรคยนโ€นรฉยญโ€š", + ["Wolf Riding"] = "รฉยชโ€˜รฆล“ยฏรฏยผลกรงโ€นยผ", + ["Wound Poison II"] = "รจโ€กยดรคยผยครฆยฏโ€™รจยยฏ II", + ["Wound Poison III"] = "รจโ€กยดรคยผยครฆยฏโ€™รจยยฏ III", + ["Wound Poison IV"] = "รจโ€กยดรคยผยครฆยฏโ€™รจยยฏ IV", + ["Wound Poison"] = "รจโ€กยดรคยผยครฆยฏโ€™รจยยฏ", + ["Wrath"] = "รฆโ€žยครฆโ‚ฌโ€™", + -- ["Wrath of Air Totem"] = true, + ["Wyvern Sting"] = "รงยฟยผรฉยพโ„ขรฉโ€™โ€ฐรฅห†ยบ", + } +end) + +BabbleSpell:RegisterTranslations("zhTW", function() + return { + ["Abolish Disease"]="รฉยฉโ€ฆรฉโ„ขยครงโ€“ยพรงโ€”โ€ฆ", + ["Abolish Poison Effect"]="รฉยฉโ€ฆรฆยฏโ€™รจยกโ€œรฆโ€ขห†รฆลพล“", + ["Abolish Poison"]="รฉยฉโ€ฆรฆยฏโ€™รจยกโ€œ", + ["Activate MG Turret"]="รงโ„ขยผรฅยฐโ€žMGs", + ["Adrenaline Rush"]="รจฦ’ยฝรฉโ€กยรฅห†ยบรฆยฟโ‚ฌ", + ["Aftermath"]="รฆยธโ€ฆรงยฎโ€”", + ["Aggression"]="รคยพยตรงโ€ขยฅ", + ["Aimed Shot"]="รงลพโ€žรฆยบโ€“รฅยฐโ€žรฆโ€œล ", + ["Alchemy"]="รงโ€ฆโ€ฐรฉโ€กโ€˜รจยกโ€œ", + ["Ambush"]="รคยผยรฆโ€œล ", + ["Amplify Curse"]="รจยฉโ€บรฅโ€™โ€™รฅยขลพรฅยนโ€ฆ", + ["Amplify Magic"]="รฉยญโ€รฆยณโ€ขรฅยขลพรฆโ€ขห†", + ["Ancestral Fortitude"] = "รฅโ€ฆห†รงยฅโ€“รฅย โ€ฆรฉลธล’", + ["Ancestral Healing"]="รฅโ€ฆห†รงยฅโ€“รฆยฒยปรงโ„ขโ€š", + ["Ancestral Knowledge"]="รฅโ€ฆห†รงยฅโ€“รงลธยฅรจยญหœ", + ["Ancestral Spirit"]="รฅโ€ฆห†รงยฅโ€“รคยนโ€นรฉยญโ€š", +-- ["Anesthetic Poison"] = true, + ["Anger Management"]="รฆโ€ ยครฆโ‚ฌโ€™รฆลฝล’รฆลฝยง", +-- ["Anguish"] = true, + ["Anticipation"]="รฉย ยรงลธยฅ", + ["Aquatic Form"]="รฆยฐยดรฆยฃยฒรฅยฝยขรฆโ€ฆโ€น", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"]="รงยฅโ€ขรฆยณโ€ขรฅโ€ฆโ€ฐรจยผย", + ["Arcane Concentration"]="รงยฅโ€ขรฆยณโ€ขรฅยฐห†รฆยณยจ", + ["Arcane Explosion"]="รฉยญโ€รงห†โ€ รจยกโ€œ", + ["Arcane Focus"]="รงยฅโ€ขรฆยณโ€ขรฉโ€บโ€ รคยธยญ", + ["Arcane Instability"]="รงยฅโ€ขรฆยณโ€ขรฅยขลพรฆโ€ขห†", + ["Arcane Intellect"]="รงยฅโ€ขรฆยณโ€ขรฆโ„ขยบรฆโ€ฆยง", + ["Arcane Meditation"]="รงยฅโ€ขรฆยณโ€ขรฅโ€ ยฅรฆฦ’ยณ", + ["Arcane Mind"]="รงยฅโ€ขรฆยณโ€ขรฅยฟฦ’รฆโ„ขยบ", + ["Arcane Missiles"]="รงยฅโ€ขรฆยณโ€ขรฉยฃโ€บรฅยฝห†", + ["Arcane Power"]="รงยฅโ€ขรฆยณโ€ขรฅยผยทรฅล’โ€“", + ["Arcane Resistance"]="รงยฅโ€ขรฆยณโ€ขรฆล โ€”รฆโ‚ฌยง", + ["Arcane Shot"]="รงยฅโ€ขรฆยณโ€ขรฅยฐโ€žรฆโ€œล ", + ["Arcane Subtlety"]="รงยฅโ€ขรฆยณโ€ขรงยฒยพรฅยฆโ„ข", + ["Arctic Reach"]="รฆยฅยตรฅยฏโ€™รฅยปยถรคยผยธ", + ["Armorsmith"]="รจยญยทรงโ€ยฒรฉยโ€บรฉโ‚ฌย รฅยธยซ", + ["Aspect of the Beast"]="รฉโ€กลฝรงยยธรฅยฎห†รจยญยท", + ["Aspect of the Cheetah"]="รงยยตรจยฑยนรฅยฎห†รจยญยท", + ["Aspect of the Hawk"]="รฉโ€บโ€žรฉยทยนรฅยฎห†รจยญยท", + ["Aspect of the Monkey"]="รฉยห†รงล’ยดรฅยฎห†รจยญยท", + ["Aspect of the Pack"]="รจยฑยนรงยพยครฅยฎห†รจยญยท", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"]="รฉโ€กลฝรฆโ‚ฌยงรฅยฎห†รจยญยท", + ["Astral Recall"]="รฆหœลธรงโ€ขล’รฅโ€šยณรฉโ‚ฌย", + ["Attack"]="รฆโ€ยปรฆโ€œล ", + ["Attacking"]="รฆโ€ยปรฆโ€œล ", + ["Auto Shot"]="รจโ€กยชรฅโ€นโ€ขรฅยฐโ€žรฆโ€œล ", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"]="รฆโ€“ยงรฅยฐห†รงยฒยพ", +-- ["Backlash"] = true, + ["Backstab"]="รจฦ’ล’รฅห†ยบ", + ["Bane"]="รงยยฝรงยฆย", + ["Banish"]="รฆโ€ยพรฉโ‚ฌยรจยกโ€œ", + ["Barkskin Effect"]="รฆยจยนรงลกยฎรฆโ€ขห†รฆลพล“", + ["Barkskin"]="รฆยจยนรงลกยฎรจยกโ€œ", + ["Barrage"]="รฅยฝห†รฅยนโ€ข", + ["Bash"]="รฉโ€กยรฆโ€œล ", + ["Basic Campfire"]="รฅลธยบรงยคลฝรงยฏยรงยยซ", + ["Battle Shout"]="รฆห†ยฐรฉยฌยฅรฆโ‚ฌโ€™รฅยยผ", + ["Battle Stance Passive"]="รฆห†ยฐรฉยฌยฅรฅยงยฟรฆโ€ฆโ€นรฏยผห†รจยขยซรฅโ€นโ€ขรฏยผโ€ฐ", + ["Battle Stance"]="รฆห†ยฐรฉยฌยฅรฅยงยฟรฆโ€ฆโ€น", + ["Bear Form"]="รงโ€ ล รฅยฝยขรฆโ€ฆโ€น", + ["Beast Lore"]="รฉโ€กลฝรงยยธรงลธยฅรจยญหœ", + ["Beast Slaying"]="รฉโ€กลฝรงยยธรฆยฎยบรฆโ€ฐโ€น", + ["Beast Training"]="รจยจโ€œรงยทยดรฉโ€กลฝรงยยธ", + ["Benediction"]="รงยฅห†รงยฆย", + ["Berserker Rage"]="รงโ€นโ€šรฆลกยดรคยนโ€นรฆโ‚ฌโ€™", + ["Berserker Stance Passive"]="รงโ€นโ€šรฆลกยดรฅยงยฟรฆโ€ฆโ€นรฏยผห†รจยขยซรฅโ€นโ€ขรฏยผโ€ฐ", + ["Berserker Stance"]="รงโ€นโ€šรฆลกยดรฅยงยฟรฆโ€ฆโ€น", + ["Berserking"]="รงโ€นโ€šรฆลกยด", + ["Bestial Discipline"]="รฉโ€กลฝรงยยธรฆห†โ€™รฅยพโ€น", + ["Bestial Swiftness"]="รฉโ€กลฝรงยยธรจยฟโ€ฆรฆยยท", + ["Bestial Wrath"]="รงโ€นโ€šรฉโ€กลฝรฆโ‚ฌโ€™รงยยซ", +-- ["Binding Heal"] = true, + ["Bite"]="รฆโ€™โ€ขรฅโ€™ยฌ", + ["Black Arrow"]="รฉยปโ€˜รงยฎยญ", + ["Blackout"]="รฆหœยรฅลฝยฅ", + ["Blacksmithing"]="รฉยโ€บรฉโ‚ฌย ", + ["Blade Flurry"]="รฅล ยรฅห†ฦ’รคยบโ€šรจห†ลพ", + ["Blast Wave"]="รจยกยรฆโ€œล รฆยณยข", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"]="รงยฅยรงยฆยรฅยพยฉรฅโ€ฆฦ’", + ["Blessing of Freedom"]="รจโ€กยชรงโ€ยฑรงยฅยรงยฆย", + ["Blessing of Kings"]="รงลฝโ€นรจโ‚ฌโ€ฆรงยฅยรงยฆย", + ["Blessing of Light"]="รฅโ€ฆโ€ฐรฆหœลฝรงยฅยรงยฆย", + ["Blessing of Might"]="รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Blessing of Protection"]="รคยฟยรจยญยทรงยฅยรงยฆย", + ["Blessing of Sacrifice"]="รงล ยงรงโ€ฐยฒรงยฅยรงยฆย", + ["Blessing of Salvation"]="รฆโ€นยฏรฆโ€ขโ€˜รงยฅยรงยฆย", + ["Blessing of Sanctuary"]="รฅยบโ€กรจยญยทรงยฅยรงยฆย", + ["Blessing of Wisdom"]="รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Blind"]="รจโ€กยดรงโ€บยฒ", + ["Blinding Powder"]="รจโ€กยดรงโ€บยฒรงยฒโ€ฐ", + ["Blink"]="รฉโ€“ฦ’รงยยพรจยกโ€œ", + ["Blizzard"]="รฆลกยดรฉยขยจรฉโ€บยช", + ["Block"]="รฆย ยผรฆโ€œโ€น", + ["Blood Craze"]="รจยกโ‚ฌรคยนโ€นรงโ€นโ€šรงโ€ ยฑ", + ["Blood Frenzy"]="รจยกโ‚ฌรคยนโ€นรงโ€นโ€šรฆลกยด", + ["Blood Fury"]="รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Blood Pact"]="รจยกโ‚ฌรคยนโ€นรฅยฅโ€˜รฅยยฐ", +-- ["Bloodlust"] = true, + ["Bloodrage"]="รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Bloodthirst"]="รฅโ€”ล“รจยกโ‚ฌ", + ["Booming Voice"]="รฉล“โ€กรจโ‚ฌยณรฅโ€”โ€œรฉลธยณ", + ["Bow Specialization"]="รฅยผโ€œรงยฎยญรฅยฐห†รงยฒยพ", + ["Bows"]="รฅยผโ€œ", + ["Bright Campfire"]="รฆหœลฝรคยบยฎรงยฏยรงยยซ", + ["Brutal Impact"]="รฉโ€กลฝรจย ยปรจยกยรฆโ€™ลพ", + ["Burning Soul"]="รงโ€กฦ’รงโ€กโ€™รคยนโ€นรฉยญโ€š", + ["Call Pet"]="รฅยยฌรฅโ€“ลกรฅยฏยตรงโ€ฐยฉ", + ["Call of Flame"]="รงฦ’ห†รงโ€žยฐรฅยยฌรฅโ€“ลก", + ["Call of Thunder"]="รฉโ€บยทรฉล“โ€ รฅยยฌรฅโ€“ลก", + ["Camouflage"]="รฅยยฝรจยฃย", + ["Cannibalize"]="รฉยฃลธรฅยฑย", + ["Cat Form"]="รงยยตรจยฑยนรฅยฝยขรฆโ€ฆโ€น", + ["Cataclysm"]="รงยยฝรจยฎล ", + ["Chain Heal"]="รฆยฒยปรงโ„ขโ€šรฉยล ", + ["Chain Lightning"]="รฉโ€“ฦ’รฉโ€บยปรฉยห†", + ["Challenging Roar"]="รฆล’โ€˜รฆห†ยฐรฅโ€™โ€ รฅโ€œยฎ", + ["Challenging Shout"]="รฆล’โ€˜รฆห†ยฐรฆโ‚ฌโ€™รฅยยผ", + ["Charge Rage Bonus Effect"]="Charge Rage Bonus Effect", + ["Charge"]="รจยกยรฉโ€นโ€™", + ["Charge Stun"] = "รจยกยรฉโ€นโ€™รฆโ€œล รฆหœย", + ["Cheap Shot"]="รฅยยทรจยฅยฒ", + ["Chilled"]="รฅโ€ ยฐรฅโ€กย", +-- ["Circle of Healing"] = true, + ["Claw"]="รงห†ยชรฆโ€œล ", + ["Cleanse"]="รฆยทยจรฅล’โ€“รจยกโ€œ", + ["Clearcasting"]="รงยฏโ‚ฌรจฦ’ยฝรฆโ€“ยฝรฆยณโ€ข", + ["Cleave"]="รฉย โ€ รฅล ห†รฆโ€“ยฌ", + ["Clever Traps"]="รฉยห†รฅยทยงรฉโ„ขยทรฉหœยฑ", +-- ["Cloak of Shadows"] = true, + ["Closing"]="รฉโ€”ล“รฉโ€“โ€ฐ", + ["Cloth"]="รฅยธฦ’รงโ€ยฒ", + ["Coarse Sharpening Stone"]="รงยฒโ€”รจยฃยฝรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Cobra Reflexes"]="รฆยฏโ€™รจโ€บโ€กรฅยยรฅยฐโ€ž", + ["Cold Blood"]="รฅโ€ ยทรจยกโ‚ฌ", + ["Cold Snap"]="รฆโ‚ฌยฅรฉโ‚ฌลธรฅโ€ ยทรฅยยป", + ["Combat Endurance"]="รคยฝล“รฆห†ยฐรฆล’ยรคยนโ€ฆ", + ["Combustion"]="รงโ€กฦ’รงโ€กโ€™", + ["Command"]="รฅโ€˜ยฝรคยปยค", +-- ["Commanding Shout"] = true, + ["Concentration Aura"]="รฅยฐห†รฆยณยจรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Concussion Blow"]="รฉล“โ€กรงโ€บยชรงล’โ€บรฆโ€œล ", + ["Concussion"]="รฅยฅโ€ฐรงยยป", + ["Concussive Shot"]="รฉล“โ€กรงโ€บยชรฅยฐโ€žรฆโ€œล ", + ["Cone of Cold"]="รฅโ€ ยฐรฉล’ยรจยกโ€œ", + ["Conflagrate"]="รงโ€กฦ’รงโ€กโ€™", + ["Conjure Food"]="รฉโ‚ฌย รฉยฃลธรจยกโ€œ", + ["Conjure Mana Agate"]="รจยฃยฝรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงโ€˜ยชรงโ€˜โ„ข", + ["Conjure Mana Citrine"]="รจยฃยฝรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรฉยปฦ’รฆยฐยดรฆโ„ขยถ", + ["Conjure Mana Jade"]="รจยฃยฝรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงยฟยกรงยฟย ", + ["Conjure Mana Ruby"]="รจยฃยฝรฉโ‚ฌย รฉยญโ€รฆยณโ€ขรงยดโ€ฆรฅยฏยถรงลธยณ", + ["Conjure Water"]="รฉโ‚ฌย รฆยฐยดรจยกโ€œ", + ["Consecrated Sharpening Stone"]="รงยฅลพรจยโ€“รงลกโ€žรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Consecration"]="รฅยฅโ€ฐรงยยป", +-- ["Consume Magic"] = true, + ["Consume Shadows"]="รฅยลพรฅโ„ขยฌรฆลกโ€”รฅยฝยฑ", + ["Convection"]="รฅโ€šยณรฅยฐลฝ", + ["Conviction"]="รฅยฎลกรงยฝยช", + ["Cooking"]="รงฦ’ยนรฉยฃยช", + ["Corruption"]="รจโ€ฆยรจยโ€ขรจยกโ€œ", + ["Counterattack"]="รฅยยรฆโ€œล ", + ["Counterspell"]="รฆยณโ€ขรจยกโ€œรฅยยรฅห†ยถ", + ["Counterspell - Silenced"] = "รฆยณโ€ขรจยกโ€œรฅยยรฅห†ยถ - รฆยฒห†รฉยปหœ", + ["Cower"]="รงโ€ขยรงยธยฎ", + ["Create Firestone"]="รจยฃยฝรฉโ‚ฌย รงยยซรงโ€žยฐรงลธยณ", +-- ["Create Firestone (Major)"] ="รจยฃยฝรฉโ‚ฌย รฆยฅยตรฆโ€ขห†รงยยซรงโ€žยฐรงลธยณ", +-- ["Create Firestone (Greater)"] ="รจยฃยฝรฉโ‚ฌย รฅยผยทรฆโ€ขห†รงยยซรงโ€žยฐรงลธยณ", +-- ["Create Firestone (Lesser)"] ="รจยฃยฝรฉโ‚ฌย รฆยฌยกรงยดลกรงยยซรงโ€žยฐรงลธยณ", + ["Create Healthstone"]="รจยฃยฝรฉโ‚ฌย รฆยฒยปรงโ„ขโ€šรงลธยณ", +-- ["Create Healthstone (Major)"] ="รจยฃยฝรฉโ‚ฌย รฆยฅยตรฆโ€ขห†รฆยฒยปรงโ„ขโ€šรงลธยณ", +-- ["Create Healthstone (Greater)"] ="รจยฃยฝรฉโ‚ฌย รฅยผยทรฆโ€ขห†รฆยฒยปรงโ„ขโ€šรงลธยณ", +-- ["Create Healthstone (Lesser)"] ="รจยฃยฝรฉโ‚ฌย รฆยฌยกรงยดลกรฆยฒยปรงโ„ขโ€šรงลธยณ", +-- ["Create Healthstone (Minor)"] ="รจยฃยฝรฉโ‚ฌย รฅห†ยรงยดลกรฆยฒยปรงโ„ขโ€šรงลธยณ", + ["Create Soulstone"]="รจยฃยฝรฉโ‚ฌย รฉยห†รฉยญโ€šรงลธยณ", +-- ["Create Soulstone (Major)"] ="รจยฃยฝรฉโ‚ฌย รฆยฅยตรฆโ€ขห†รฉยห†รฉยญโ€šรงลธยณ", +-- ["Create Soulstone (Greater)"] ="รจยฃยฝรฉโ‚ฌย รฅยผยทรฆโ€ขห†รฉยห†รฉยญโ€šรงลธยณ", +-- ["Create Soulstone (Lesser)"] ="รจยฃยฝรฉโ‚ฌย รฆยฌยกรงยดลกรฉยห†รฉยญโ€šรงลธยณ", +-- ["Create Soulstone (Minor)"] ="รจยฃยฝรฉโ‚ฌย รฅห†ยรงยดลกรฉยห†รฉยญโ€šรงลธยณ", + ["Create Spellstone"]="รจยฃยฝรฉโ‚ฌย รฆยณโ€ขรจยกโ€œรงลธยณ", +-- ["Create Spellstone (Major)"] ="รจยฃยฝรฉโ‚ฌย รฆยฅยตรฆโ€ขห†รฆยณโ€ขรจยกโ€œรงลธยณ", +-- ["Create Spellstone (Greater)"] ="รจยฃยฝรฉโ‚ฌย รฅยผยทรฆโ€ขห†รฆยณโ€ขรจยกโ€œรงลธยณ", + ["Crippling Poison II"]="รจโ€กยดรฆยฎหœรฆยฏโ€™รจโ€”ยฅ II", + ["Crippling Poison"]="รจโ€กยดรฆยฎหœรฆยฏโ€™รจโ€”ยฅ", + ["Critical Mass"]="รงยยซรงโ€žยฐรฉโ€กยรฆโ€œล ", + ["Crossbows"]="รฅยผยฉ", + ["Cruelty"]="รฆยฎหœรฅยฟย", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"]="รฆย ยฝรฅลธยน", + ["Cure Disease"]="รงยฅโ€บรงโ€”โ€ฆรจยกโ€œ", + ["Cure Poison"]="รฆยถห†รฆยฏโ€™รจยกโ€œ", + ["Curse of Agony"]="รงโ€”โ€บรจโ€นยฆรจยฉโ€บรฅโ€™โ€™", + ["Curse of Doom Effect"]="รฅลฝโ€žรฉยโ€นรจยฉโ€บรฅโ€™โ€™รฆโ€ขห†รฆลพล“", + ["Curse of Doom"]="รฅลฝโ€žรฉยโ€นรจยฉโ€บรฅโ€™โ€™", + ["Curse of Exhaustion"]="รงโ€“ยฒรฅโ€นลพรจยฉโ€บรฅโ€™โ€™", + ["Curse of Idiocy"]="รงโ„ขยกรฅโ€˜โ€ รจยฉโ€บรฅโ€™โ€™", + ["Curse of Recklessness"]="รฉยญยฏรจลฝยฝรจยฉโ€บรฅโ€™โ€™", + ["Curse of Shadow"]="รฆลกโ€”รฅยฝยฑรจยฉโ€บรฅโ€™โ€™", + ["Curse of Tongues"]="รจยชลพรจยจโ‚ฌรจยฉโ€บรฅโ€™โ€™", + ["Curse of Weakness"]="รจโ„ขโ€บรฅยผยฑรจยฉโ€บรฅโ€™โ€™", + ["Curse of the Elements"]="รฅโ€ฆฦ’รงยดย รจยฉโ€บรฅโ€™โ€™", +-- ["Cyclone"] = true, + ["Dagger Specialization"]="รฅล’โ€ขรฉยฆโ€“รฅยฐห†รงยฒยพ", + ["Daggers"]="รฅล’โ€ขรฉยฆโ€“", + ["Dampen Magic"]="รฉยญโ€รฆยณโ€ขรฆล โ€˜รฅห†ยถ", + ["Dark Pact"]="รฉยปโ€˜รฆลกโ€”รฅยฅโ€˜รงยดโ€ž", + ["Darkness"]="รฉยปโ€˜รฆลกโ€”", + ["Dash"]="รฆโ‚ฌยฅรฅยฅโ€", + ["Deadly Poison II"]="รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ II", + ["Deadly Poison III"]="รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ III", + ["Deadly Poison IV"]="รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ IV", + ["Deadly Poison V"]="รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ V", + ["Deadly Poison"]="รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ", +-- ["Deadly Throw"] = true, + ["Death Coil"]="รฆยญยปรคยบยกรงยบยรงยนลพ", + ["Death Wish"]="รฆยญยปรคยบยกรคยนโ€นรฉยกหœ", + ["Deep Wounds"]="รฉโ€กยรฅโ€šยท", + ["Defense"]="รฉหœยฒรงยฆยฆ", + ["Defensive Stance Passive"]="รฉหœยฒรงยฆยฆรฅยงยฟรฆโ€ฆโ€นรฏยผห†รจยขยซรฅโ€นโ€ขรฏยผโ€ฐ", + ["Defensive Stance"]="รฉหœยฒรงยฆยฆรฅยงยฟรฆโ€ฆโ€น", + ["Defensive State 2"]="รฉหœยฒรงยฆยฆรงโ€นโ‚ฌรฆโ€ฆโ€น 2", + ["Defensive State"]="รฉหœยฒรงยฆยฆรงโ€นโ‚ฌรฆโ€ฆโ€น", + ["Defiance"]="รฆล’โ€˜รฉโ€กย", + ["Deflection"]="รฅยยรฆโ€“ล“", + ["Demon Armor"]="รฉยญโ€รงโ€ยฒรจยกโ€œ", + ["Demon Skin"]="รฆฦ’ยกรฉยญโ€รงลกยฎรจโ€ ลก", + ["Demonic Embrace"]="รฆฦ’ยกรฉยญโ€รคยนโ€นรฆโ€œย", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"]="รฆฦ’ยกรฉยญโ€รงล ยงรงโ€ฐยฒ", + ["Demoralizing Roar"]="รฆล’ยซรฅยฟโ€”รฅโ€™โ€ รฅโ€œยฎ", + ["Demoralizing Shout"]="รฆล’ยซรฅยฟโ€”รฆโ‚ฌโ€™รฅยยผ", + ["Dense Sharpening Stone"]="รงยทยปรฅยฏโ€ รงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Desperate Prayer"]="รงยตโ€ขรฆล“โ€บรงยฆยฑรจยจโ‚ฌ", + ["Destructive Reach"]="รฆยฏโ‚ฌรฆยปโ€ฆรฅยปยถรคยผยธ", + ["Detect Greater Invisibility"]="รฅยยตรฆยธยฌรฅยผยทรฆโ€ขห†รฉลกยฑรฅยฝยข", + ["Detect Invisibility"]="รฅยยตรฆยธยฌรฉลกยฑรฅยฝยข", + ["Detect Lesser Invisibility"]="รฅยยตรฆยธยฌรฆยฌยกรงยดลกรฉลกยฑรฅยฝยข", + ["Detect Magic"]="รฅยยตรฆยธยฌรฉยญโ€รฆยณโ€ข", + ["Detect Traps"]="รฅยยตรฆยธยฌรฉโ„ขยทรฉหœยฑ", + ["Detect"]="รฅยยตรฆยธยฌ", + ["Deterrence"]="รฅยจยรฆโ€กยพ", +-- ["Devastate"] = true, + ["Devastation"]="รฆยฏโ‚ฌรฆยปโ€ฆ", + ["Devotion Aura"]="รจโ„ขโ€รจยชย รฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Devour Magic Effect"]="รฅยลพรฅโ„ขยฌรฉยญโ€รฆยณโ€ขรฆโ€ขห†รฆลพล“", + ["Devour Magic"]="รฅยลพรฅโ„ขยฌรฉยญโ€รฆยณโ€ข", + ["Devouring Plague"]="รฅโ„ขยฌรฉยห†รงหœลธรงโ€“ยซ", + ["Diplomacy"]="รฅยคโ€“รคยบยค", + ["Dire Bear Form"]="รฅยทยจรงโ€ ล รฅยฝยขรฆโ€ฆโ€น", + ["Disarm Trap"]="รจยงยฃรฉโ„ขยครฉโ„ขยทรฉหœยฑ", + ["Disarm"]="รงยนยณรฆยขยฐ", + ["Disease Cleansing Totem"]="รงยฅโ€บรงโ€”โ€ฆรฅล“โ€“รฉยจยฐ", + ["Disenchant"]="รฅห†โ€ รจยงยฃ", + ["Disengage"]="รฉโ‚ฌฦ’รจโ€žยซ", + ["Dismiss Pet"]="รจยงยฃรฆโ€ขยฃรฉโ€กลฝรงยยธ", + ["Dispel Magic"]="รฉยฉโ€ฆรฆโ€ขยฃรฉยญโ€รฆยณโ€ข", + ["Distract"]="รฆโ€œยพรคยบโ€š", + ["Distracting Shot"]="รฆโ€œยพรคยบโ€šรฅยฐโ€žรฆโ€œล ", + ["Dive"]="รคยฟยฏรจยกย", + ["Divine Favor"]="รงยฅลพรฆยยฉรจยกโ€œ", + ["Divine Fury"]="รงยฅลพรจยโ€“รคยนโ€นรฆโ‚ฌโ€™", +-- ["Divine Illumination"] = true, + ["Divine Intellect"]="รงยฅลพรจยโ€“รฆโ„ขยบรฆโ€ฆยง", + ["Divine Intervention"]="รงยฅลพรจยโ€“รฅยนยฒรฆยถโ€ฐ", + ["Divine Protection"]="รจยโ€“รคยฝโ€˜รจยกโ€œ", + ["Divine Shield"]="รจยโ€“รงโ€บยพรจยกโ€œ", + ["Divine Spirit"]="รงยฅลพรจยโ€“รคยนโ€นรฉยห†", + ["Divine Strength"]="รงยฅลพรจยโ€“รคยนโ€นรฅล โ€บ", + ["Dodge"]="รจยบยฒรฉโ€“ฦ’", +-- ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"]="รฉยพยรฉยฑโ€”รจยฃยฝรงลกยฎ", + ["Drain Life"]="รฅยยธรฅยโ€“รงโ€ลธรฅโ€˜ยฝ", + ["Drain Mana"]="รฅยยธรฅยโ€“รฆยณโ€ขรฅล โ€บ", + ["Drain Soul"]="รฅยยธรฅยโ€“รฉยห†รฉยญโ€š", + ["Drink"]="รฅโ€“ยรฆยฐยด", + ["Dual Wield Specialization"]="รฉโ€บโ„ขรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Dual Wield"]="รฉโ€บโ„ขรฆยญยฆรฅโ„ขยจ", + ["Duel"]="รฆยฑยบรฉยฌยฅ", + ["Eagle Eye"]="รฉยทยนรงล“ยผรจยกโ€œ", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"]="รฅล“ยฐรฉล“โ€กรจยกโ€œ", + ["Earthbind Totem"]="รฅล“ยฐรงยธโ€บรฅล“โ€“รฉยจยฐ", + ["Efficiency"]="รฆโ€ขห†รงลฝโ€ก", + ["Elemental Focus"]="รฅโ€ฆฦ’รงยดย รฉโ€บโ€ รคยธยญ", + ["Elemental Fury"]="รฅโ€ฆฦ’รงยดย รคยนโ€นรฆโ‚ฌโ€™", + ["Elemental Leatherworking"]="รฅโ€ฆฦ’รงยดย รจยฃยฝรงลกยฎ", + ["Elemental Mastery"]="รฅโ€ฆฦ’รงยดย รฅยฐห†รงยฒยพ", + ["Elemental Sharpening Stone"]="รฅโ€ฆฦ’รงยดย รงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Elune's Grace"]="รคยผล รฉล“ยฒรฆยยฉรงลกโ€žรจยณล“รงยฆย", + ["Elusiveness"]="รฉยฃโ€žรฅยฟยฝรคยธยรฅยฎลก", + ["Emberstorm"]="รงยยฅรงยโ‚ฌรฉยขยจรฆลกยด", + ["Enamored Water Spirit"] = "รจยขยซรจยฟยทรฆฦ’โ€˜รงลกโ€žรฆยฐยดรคยนโ€นรฉยญโ€š", + ["Enchanting"]="รฉโ„ขโ€žรฉยญโ€", + ["Endurance Training"]="รจโ‚ฌยรคยนโ€ฆรจยจโ€œรงยทยด", + ["Endurance"]="รจโ‚ฌยรคยนโ€ฆ", + ["Engineering Specialization"]="รฅยทยฅรงยจโ€นรฅยญยธรฅยฐห†รงยฒยพ", + ["Engineering"]="รฅยทยฅรงยจโ€นรฅยญยธ", + ["Enrage"]="รงโ€นโ€šรฆโ‚ฌโ€™", + ["Enriched Manna Biscuit"]="รฅยยฏรฅยยฃรงลกโ€žรฉยญโ€รฆยณโ€ขรฉยปลพรฅยฟฦ’", + ["Enslave Demon"]="รฅยฅยดรฅยฝยนรฆฦ’ยกรฉยญโ€", + ["Entangling Roots"]="รงยณยพรงยบยรฆย ยนรฉยฌลก", + ["Entrapment"]="รจยชหœรฆยโ€ข", +-- ["Envenom"] = true, + ["Escape Artist"]="รฉโ‚ฌฦ’รฅโ€˜ยฝรฅยฐห†รฅยฎยถ", + ["Evasion"]="รฉโ€“ฦ’รฉยยฟ", + ["Eventide"]="รฉยปฦ’รฆหœย", + ["Eviscerate"]="รฅโ€ฐโ€รฉยชยจ", + ["Evocation"]="รฅโ€“ลกรฉโ€ โ€™", + ["Execute"]="รฆโ€“ยฌรฆยฎยบ", + ["Exorcism"]="รฉยฉโ€ฆรฉโ€šยชรจยกโ€œ", + ["Expansive Mind"]="รฉโ€“โ€นรฉโ€”ล รฆโ‚ฌยรงยถยญ", + ["Explosive Trap Effect"]="รงห†โ€ รงโ€šยธรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Explosive Trap"]="รงห†โ€ รงโ€šยธรฉโ„ขยทรฉหœยฑ", + ["Expose Armor"]="รงย ยดรงโ€ยฒ", + ["Eye for an Eye"]="รคยปยฅรงล“ยผรฉโ€šโ€žรงล“ยผ", + ["Eye of Kilrogg"]="รฅลธยบรงห†ยพรงยพโ€ฆรฆย ยผรคยนโ€นรงล“ยผ", + ["Eyes of the Beast"]="รฉโ€กลฝรงยยธรคยนโ€นรงล“ยผ", + ["Fade"]="รฆยผยธรฉลกยฑรจยกโ€œ", + ["Faerie Fire"]="รงยฒยพรฉยห†รคยนโ€นรงยยซ", + ["Faerie Fire (Feral)"] = "รงยฒยพรฉยห†รคยนโ€นรงยยซรฏยผห†รฉโ€กลฝรฆโ‚ฌยงรฏยผโ€ฐ", + ["Far Sight"]="รจยฆโ€“รงโ€ขล’รจยกโ€œ", + ["Fear Ward"]="รฉหœยฒรจยญยทรฆยยรฆโ€กยผรงยตยรงโ€ขล’", + ["Fear"]="รฆยยรฆโ€กยผรจยกโ€œ", + ["Feed Pet"]="รฉยคยตรฉยคล รฅยฏยตรงโ€ฐยฉ", + ["Feedback"]="รฅโ€บลพรฉยฅโ€น", + ["Feign Death"]="รฅยโ€กรฆยญยป", + ["Feint"]="รคยฝยฏรฆโ€ยป", +-- ["Fel Armor"] = true, + ["Fel Concentration"]="รฆฦ’ยกรฉยญโ€รฅยฐห†รฆยณยจ", + ["Fel Domination"]="รฆฦ’ยกรฉยญโ€รฆโ€ยฏรฉโ€ฆย", + ["Fel Intellect"]="รฆฦ’ยกรฉยญโ€รฆโ„ขยบรฅล โ€บ", + ["Fel Stamina"]="รฆฦ’ยกรฉยญโ€รจโ‚ฌยรฅล โ€บ", + ["Felfire"]="รฉยญโ€รงยยซ", + ["Feline Grace"]="รจยฑยนรคยนโ€นรฅโ€žยชรฉโ€บโ€ฆ", + ["Feline Swiftness"]="รจยฑยนรคยนโ€นรจยฟโ€ฆรฆยยท", + ["Feral Aggression"]="รฉโ€กลฝรฆโ‚ฌยงรคยพยตรงโ€ขยฅ", + ["Feral Charge"]="รฉโ€กลฝรฆโ‚ฌยงรจยกยรฉโ€นโ€™", + ["Feral Instinct"]="รฉโ€กลฝรฆโ‚ฌยงรฆล“ยฌรจฦ’ยฝ", + ["Ferocious Bite"]="รฅโ€ฆโ€กรงล’โ€บรฆโ€™โ€ขรฅโ€™ยฌ", + ["Ferocity"]="รฅโ€ฆโ€กรฆลกยด", + ["Fetish"]="รฅยกโ€˜รฅฦ’ย", + ["Find Herbs"]="รฅยฐโ€นรฆโ€ฐยพรจยโ€ฐรจโ€”ยฅ", + ["Find Minerals"]="รฅยฐโ€นรฆโ€ฐยพรงยคยฆรงโ€ฐยฉ", + ["Find Treasure"]="รฅยฐโ€นรฆโ€ฐยพรจยฒยกรฅยฏยถ", + ["Fire Blast"]="รงยยซรงโ€žยฐรจยกยรฆโ€œล ", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"]="รงยยซรงโ€žยฐรฆโ€“ยฐรฆหœลธรฅล“โ€“รฉยจยฐ", + ["Fire Power"]="รงยยซรงโ€žยฐรฅยผยทรฅล’โ€“", + ["Fire Resistance Aura"]="รงยยซรงโ€žยฐรฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Fire Resistance Totem"]="รฆล โ€”รงยยซรฅล“โ€“รฉยจยฐ", + ["Fire Resistance"]="รงยยซรงโ€žยฐรฆล โ€”รฆโ‚ฌยง", + ["Fire Shield"]="รงยยซรงโ€žยฐรคยนโ€นรงโ€บยพ", + ["Fire Vulnerability"]="รงยยซรงโ€žยฐรฆหœโ€œรฅโ€šยท", + ["Fire Ward"]="รฉหœยฒรจยญยทรงยยซรงโ€žยฐรงยตยรงโ€ขล’", + ["Fireball"]="รงยยซรงยฦ’รจยกโ€œ", + ["Firebolt"]="รงยยซรงโ€žยฐรงยฎยญ", + ["First Aid"]="รฆโ‚ฌยฅรฆโ€ขโ€˜", + ["Fishing Poles"]="รฉยญลกรงยซยฟ", + ["Fishing"]="รฉโ€กยฃรฉยญลก", + ["Fist Weapon Specialization"]="รฆโ€นยณรฅยฅโ€”รฅยฐห†รงยฒยพ", + ["Fist Weapons"]="รฆโ€นยณรฅยฅโ€”", + ["Flame Shock"]="รงฦ’ห†รงโ€žยฐรฉล“โ€กรฆโ€œล ", + ["Flame Throwing"]="รงฦ’ห†รงโ€žยฐรฆล โ€ขรฆโ€œยฒ", + ["Flamestrike"]="รงฦ’ห†รงโ€žยฐรฉยขยจรฆลกยด", + ["Flamethrower"]="รงยยซรงโ€žยฐรฅโ„ขยดรฅยฐโ€žรฅโ„ขยจ", + ["Flametongue Totem"]="รงยยซรจห†ล’รฅล“โ€“รฉยจยฐ", + ["Flametongue Weapon"]="รงยยซรจห†ล’รฆยญยฆรฅโ„ขยจ", + ["Flare"]="รงโ€ฆยงรฆหœลฝรฅยฝห†", + ["Flash Heal"]="รฅยฟยซรฉโ‚ฌลธรฆยฒยปรงโ„ขโ€š", + ["Flash of Light"]="รจยโ€“รฅโ€ฆโ€ฐรฉโ€“ฦ’รงยยพ", +-- ["Flight Form"] = true, + ["Flurry"]="รคยบโ€šรจห†ลพ", + ["Focused Casting"]="รฅยฐห†รฆยณยจรฆโ€“ยฝรฆยณโ€ข", + ["Food"]="รฉโ‚ฌยฒรฉยฃลธ", + ["Forbearance"] = "รจโ€กยชรฅยพโ€น", +-- ["Force of Nature"] = true, + ["Force of Will"]="รฆโ€žยรฅยฟโ€”รคยนโ€นรฅล โ€บ", + ["Freezing Trap Effect"]="รฅโ€ ยฐรฅโ€กยรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Freezing Trap"]="รฅโ€ ยฐรฅโ€กยรฉโ„ขยทรฉหœยฑ", + ["Frenzied Regeneration"]="รงโ€นโ€šรฆลกยดรฅโ€บลพรฅยพยฉ", + ["Frenzy"]="รงโ€นโ€šรคยบโ€š", + ["Frost Armor"]="รฉล“ล“รงโ€ยฒรจยกโ€œ", + ["Frost Channeling"]="รฅโ€ ยฐรฉล“ล“รฅยฐลฝรจฦ’ยฝ", + ["Frost Nova"]="Frost Nova", + ["Frost Resistance Aura"]="รฅโ€ ยฐรฉล“ล“รฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Frost Resistance Totem"]="รฆล โ€”รฅยฏโ€™รฅล“โ€“รฉยจยฐ", + ["Frost Resistance"]="รฅโ€ ยฐรฉล“ล“รฆล โ€”รฆโ‚ฌยง", + ["Frost Shock"]="รฅโ€ ยฐรฉล“ล“รฉล“โ€กรฆโ€œล ", + ["Frost Trap"]="รฅโ€ ยฐรฉล“ล“รฉโ„ขยทรฉหœยฑ", + ["Frost Trap Aura"] = "รฅโ€ ยฐรฉล“ล“รฉโ„ขยทรฉหœยฑรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Frost Ward"]="รฉหœยฒรจยญยทรฅโ€ ยฐรฉล“ล“รงยตยรงโ€ขล’", + ["Frostbite"]="รฉล“ล“รฅยฏโ€™รฅห†ยบรฉยชยจ", + ["Frostbolt"]="รฅยฏโ€™รฅโ€ ยฐรงยฎยญ", + ["Frostbrand Weapon"]="รฅโ€ ยฐรฅยฐยรฆยญยฆรฅโ„ขยจ", + ["Furious Howl"]="รงโ€นโ€šรฆโ‚ฌโ€™รคยนโ€นรฅลกลฝ", + ["Furor"]="รฆยฟโ‚ฌรฆโ‚ฌโ€™", + ["Garrote"]="รงยตลพรฅโ€“โ€ฐ", + ["Generic"]="Generic", + ["Ghost Wolf"]="รฅยนยฝรฉยญโ€šรคยนโ€นรงโ€นยผ", + ["Ghostly Strike"]="รฉยฌยผรฉยญโ€ฆรฆโ€ยปรฆโ€œล ", + ["Gift of Life"] = true, + ["Gift of Nature"]="รจโ€กยชรงโ€žยถรจยณล“รงยฆย", + ["Gift of the Wild"]="รฉโ€กลฝรฆโ‚ฌยงรจยณล“รงยฆย", + ["Gouge"]="รฉโ€˜ยฟรฆโ€œล ", + ["Grace of Air Totem"]="รฉยขยจรคยนโ€นรฅโ€žยชรฉโ€บโ€ฆรฅล“โ€“รฉยจยฐ", + ["Great Stamina"]="รฅยผยทรฆโ€ขห†รจโ‚ฌยรฅล โ€บ", + ["Greater Blessing of Kings"]="รฅยผยทรฆโ€ขห†รงลฝโ€นรจโ‚ฌโ€ฆรงยฅยรงยฆย", + ["Greater Blessing of Light"]="รฅยผยทรฆโ€ขห†รฅโ€ฆโ€ฐรฆหœลฝรงยฅยรงยฆย", + ["Greater Blessing of Might"]="รฅยผยทรฆโ€ขห†รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Greater Blessing of Salvation"]="รฅยผยทรฆโ€ขห†รฆโ€นยฏรฆโ€ขโ€˜รงยฅยรงยฆย", + ["Greater Blessing of Sanctuary"]="รฅยผยทรฆโ€ขห†รฅยบโ€กรจยญยทรงยฅยรงยฆย", + ["Greater Blessing of Wisdom"]="รฅยผยทรฆโ€ขห†รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Greater Heal"]="รฅยผยทรฆโ€ขห†รฆยฒยปรงโ„ขโ€šรจยกโ€œ", + ["Grim Reach"]="รงโ€žยกรฆฦ’โ€ฆรฅยปยถรคยผยธ", + ["Grounding Totem"]="รฆย ยนรฅลธยบรฅล“โ€“รฉยจยฐ", + ["Grovel"]="รฅล’ยรฅล’ย", + ["Growl"]="รคยฝลฝรฅยยผ", + ["Guardian's Favor"]="รฅยฎห†รจยญยทรจโ‚ฌโ€ฆรงลกโ€žรฅยฏยตรฆโ€žโ€บ", + ["Gun Specialization"]="รฆยงยรฆยขยฐรฅยฐห†รงยฒยพ", + ["Guns"]="รฆยงยรฆยขยฐ", + ["Hammer of Justice"]="รฅห†ยถรจยฃยรคยนโ€นรฉล’หœ", + ["Hammer of Wrath"]="รฆโ€ ยครฆโ‚ฌโ€™รคยนโ€นรฉล’หœ", + ["Hamstring"]="รฆโ€“ยทรงยญโ€น", + ["Harass"]="รคยพยตรฆโ€œยพ", + ["Hardiness"]="รฅย โ€ฆรฉลธล’", + ["Hawk Eye"]="รฉยทยนรงล“ยผ", + ["Heal"]="รฆยฒยปรงโ„ขโ€šรจยกโ€œ", + ["Healing Focus"]="รฅยฐห†รฆยณยจรฆยฒยปรงโ„ขโ€š", + ["Healing Light"]="รฆยฒยปรงโ„ขโ€šรคยนโ€นรฅโ€ฆโ€ฐ", + ["Healing Stream Totem"]="รฆยฒยปรงโ„ขโ€šรคยนโ€นรฆยณโ€ฐรฅล“โ€“รฉยจยฐ", + ["Healing Touch"]="รฆยฒยปรงโ„ขโ€šรคยนโ€นรจยงยธ", + ["Healing Wave"]="รฆยฒยปรงโ„ขโ€šรฆยณยข", + ["Healing Way"] = "รฆยฒยปรงโ„ขโ€šรคยนโ€นรฉยโ€œ", + ["Health Funnel"]="รงโ€ลธรฅโ€˜ยฝรฉโ‚ฌลกรฉยโ€œ", + ["Heart of the Wild"]="รฉโ€กลฝรฆโ‚ฌยงรคยนโ€นรฅยฟฦ’", + ["Heavy Sharpening Stone"]="รฉโ€กยรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Hellfire Effect"]="รฅล“ยฐรงยโ€žรงฦ’ห†รงโ€žยฐรฆโ€ขห†รฆลพล“", + ["Hellfire"]="รฅล“ยฐรงยโ€žรงฦ’ห†รงโ€žยฐ", + ["Hemorrhage"]="รฅโ€กยบรจยกโ‚ฌ", + ["Herb Gathering"]="รฆลฝยกรฉโ€บโ€ รจยโ€ฐรจโ€”ยฅ", + ["Herbalism"]="รจยโ€ฐรจโ€”ยฅรฅยญยธ", + ["Heroic Strike"]="รจโ€นยฑรฅโ€นโ€กรฆโ€ฐโ€œรฆโ€œล ", +-- ["Heroism"] = true, + ["Hex of Weakness"]="รจโ„ขโ€บรฅยผยฑรฅยฆโ€“รจยกโ€œ", + ["Hibernate"]="รคยผโ€˜รงล“ย ", + ["Holy Fire"]="รงยฅลพรจยโ€“รคยนโ€นรงยยซ", + ["Holy Light"]="รจยโ€“รฅโ€ฆโ€ฐรจยกโ€œ", + ["Holy Nova"]="รงยฅลพรจยโ€“รฆโ€“ยฐรฆหœลธ", + ["Holy Power"]="รงยฅลพรจยโ€“รฅยผยทรฅล’โ€“", + ["Holy Reach"]="รงยฅลพรจยโ€“รฅยปยถรคยผยธ", + ["Holy Shield"]="รงยฅลพรจยโ€“รคยนโ€นรงโ€บยพ", + ["Holy Shock"]="รงยฅลพรจยโ€“รฉล“โ€กรฆโ€œล ", + ["Holy Specialization"]="รงยฅลพรจยโ€“รฅยฐห†รงยฒยพ", + ["Holy Wrath"]="รงยฅลพรจยโ€“รฆโ€ ยครฆโ‚ฌโ€™", + ["Honorless Target"]="รงโ€žยกรฆยฆยฎรจยญยฝรงโ€บยฎรฆยจโ„ข", + ["Horse Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรฉยฆยฌ", + ["Howl of Terror"]="รฆยยรฆโ€กยผรฅลกลฝรฅยยซ", + ["Humanoid Slaying"]="รคยบยบรฅลพโ€นรงโ€ลธรงโ€ฐยฉรฆยฎยบรฆโ€ฐโ€น", + ["Hunter's Mark"]="รงยยตรคยบยบรฅยยฐรจยจหœ", + ["Hurricane"]="รฉยขยถรฉยขยจ", + ["Ice Armor"]="รฅโ€ ยฐรงโ€ยฒรจยกโ€œ", + ["Ice Barrier"]="รฅยฏโ€™รฅโ€ ยฐรจยญยทรฉยซโ€", + ["Ice Block"]="รฅยฏโ€™รฅโ€ ยฐรฅยฑยรฉลกล“", +-- ["Ice Lance"] = true, + ["Ice Shards"]="รฅยฏโ€™รฅโ€ ยฐรงยขลฝรงโ€ฐโ€ก", + ["Ignite"]="รฉยปลพรงโ€กฦ’", + ["Illumination"]="รฅโ€ขลธรงโ„ขยผ", + ["Immolate"]="รงยยปรงยฅยญ", + ["Immolation Trap Effect"]="รงยยปรงยฅยญรฉโ„ขยทรฉหœยฑรฆโ€ขห†รฆลพล“", + ["Immolation Trap"]="รงยยปรงยฅยญรฉโ„ขยทรฉหœยฑ", + ["Impact"]="รจยกยรฆโ€œล ", + ["Impale"]="รงยฉยฟรฅห†ยบ", + ["Improved Ambush"]="รฅยผยทรฅล’โ€“รคยผยรฆโ€œล ", + ["Improved Arcane Explosion"]="รฅยผยทรฅล’โ€“รฉยญโ€รงห†โ€ รจยกโ€œ", + ["Improved Arcane Missiles"]="รฅยผยทรฅล’โ€“รงยฅโ€ขรฆยณโ€ขรฉยฃโ€บรฅยฝห†", + ["Improved Arcane Shot"]="รฅยผยทรฅล’โ€“รงยฅโ€ขรฆยณโ€ขรฅยฐโ€žรฆโ€œล ", + ["Improved Aspect of the Hawk"]="รฅยผยทรฅล’โ€“รฉโ€บโ€žรฉยทยนรฅยฎห†รจยญยท", + ["Improved Aspect of the Monkey"]="รฅยผยทรฅล’โ€“รฉยห†รงล’ยดรฅยฎห†รจยญยท", + ["Improved Backstab"]="รฅยผยทรฅล’โ€“รจฦ’ล’รฅห†ยบ", + ["Improved Battle Shout"]="รฅยผยทรฅล’โ€“รฆห†ยฐรฉยฌยฅรฆโ‚ฌโ€™รฅยยผ", + ["Improved Berserker Rage"]="รฅยผยทรฅล’โ€“รงโ€นโ€šรฆลกยดรคยนโ€นรฆโ‚ฌโ€™", + ["Improved Blessing of Might"]="รฅยผยทรฅล’โ€“รฅล โ€บรฉโ€กยรงยฅยรงยฆย", + ["Improved Blessing of Wisdom"]="รฅยผยทรฅล’โ€“รฆโ„ขยบรฆโ€ฆยงรงยฅยรงยฆย", + ["Improved Blizzard"]="รฅยผยทรฅล’โ€“รฆลกยดรฉยขยจรฉโ€บยช", + ["Improved Bloodrage"]="รฅยผยทรฅล’โ€“รจยกโ‚ฌรฆโ‚ฌยงรงโ€นโ€šรฆลกยด", + ["Improved Chain Heal"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรฉยล ", + ["Improved Chain Lightning"]="รฅยผยทรฅล’โ€“รฉโ€“ฦ’รฉโ€บยปรฉยห†", + ["Improved Challenging Shout"]="รฅยผยทรฅล’โ€“รฆล’โ€˜รฆห†ยฐรฆโ‚ฌโ€™รฅยยผ", + ["Improved Charge"]="รฅยผยทรฅล’โ€“รจยกยรฉโ€นโ€™", + ["Improved Cheap Shot"]="รฅยผยทรฅล’โ€“รฅยยทรจยฅยฒ", + ["Improved Cleave"]="รฅยผยทรฅล’โ€“รฉย โ€ รฅล ห†รฆโ€“ยฌ", + ["Improved Concentration Aura"]="รฅยผยทรฅล’โ€“รฅยฐห†รฆยณยจรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Improved Concussive Shot"]="รฅยผยทรฅล’โ€“รฉล“โ€กรงโ€บยชรฅยฐโ€žรฆโ€œล ", + ["Improved Cone of Cold"]="รฅยผยทรฅล’โ€“รฅโ€ ยฐรฉล’ยรจยกโ€œ", + ["Improved Corruption"]="รฅยผยทรฅล’โ€“รจโ€ฆยรจยโ€ขรจยกโ€œ", + ["Improved Counterspell"]="รฅยผยทรฅล’โ€“รฆยณโ€ขรจยกโ€œรฅยยรฅห†ยถ", + ["Improved Curse of Agony"]="รฅยผยทรฅล’โ€“รงโ€”โ€บรจโ€นยฆรจยฉโ€บรฅโ€™โ€™", + ["Improved Curse of Exhaustion"]="รฅยผยทรฅล’โ€“รงโ€“ยฒรฅโ€นลพรจยฉโ€บรฅโ€™โ€™", + ["Improved Curse of Weakness"]="รฅยผยทรฅล’โ€“รจโ„ขโ€บรฅยผยฑรจยฉโ€บรฅโ€™โ€™", + ["Improved Dampen Magic"]="รฅยผยทรฅล’โ€“รฉยญโ€รฆยณโ€ขรฆล โ€˜รฅห†ยถ", + ["Improved Deadly Poison"]="รฅยผยทรฅล’โ€“รจโ€กยดรฅโ€˜ยฝรฆยฏโ€™รจโ€”ยฅ", + ["Improved Demoralizing Shout"]="รฅยผยทรฅล’โ€“รฆล’ยซรฅยฟโ€”รฆโ‚ฌโ€™รฅยยผ", + ["Improved Devotion Aura"]="รฅยผยทรฅล’โ€“รจโ„ขโ€รจยชย รฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Improved Disarm"]="รฅยผยทรฅล’โ€“รงยนยณรฆยขยฐ", + ["Improved Distract"]="รฅยผยทรฅล’โ€“รฆโ€œยพรคยบโ€š", + ["Improved Drain Life"]="รฅยผยทรฅล’โ€“รฅยยธรฅยโ€“รงโ€ลธรฅโ€˜ยฝ", + ["Improved Drain Mana"]="รฅยผยทรฅล’โ€“รฅยยธรฅยโ€“รฆยณโ€ขรฅล โ€บ", + ["Improved Drain Soul"]="รฅยผยทรฅล’โ€“รฅยยธรฅยโ€“รฉยห†รฉยญโ€š", + ["Improved Enrage"]="รฅยผยทรฅล’โ€“รงโ€นโ€šรฆโ‚ฌโ€™", + ["Improved Enslave Demon"]="รฅยผยทรฅล’โ€“รฅยฅยดรฅยฝยนรฆฦ’ยกรฉยญโ€", + ["Improved Entangling Roots"]="รฅยผยทรฅล’โ€“รงยณยพรงยบยรฆย ยนรฉยฌลก", + ["Improved Evasion"]="รฅยผยทรฅล’โ€“รฉโ€“ฦ’รฉยยฟ", + ["Improved Eviscerate"]="รฅยผยทรฅล’โ€“รฅโ€ฐโ€รฉยชยจ", + ["Improved Execute"]="รฅยผยทรฅล’โ€“รฆโ€“ยฌรฆยฎยบ", + ["Improved Expose Armor"]="รฅยผยทรฅล’โ€“รงย ยดรงโ€ยฒ", + ["Improved Eyes of the Beast"]="รฅยผยทรฅล’โ€“รฉโ€กลฝรงยยธรคยนโ€นรงล“ยผ", + ["Improved Fade"]="รฅยผยทรฅล’โ€“รฆยผยธรฉลกยฑรจยกโ€œ", + ["Improved Feign Death"]="รฅยผยทรฅล’โ€“รฅยโ€กรฆยญยป", + ["Improved Fire Blast"]="รฅยผยทรฅล’โ€“รงยยซรงโ€žยฐรจยกยรฆโ€œล ", + ["Improved Fire Nova Totem"]="รฅยผยทรฅล’โ€“รงยยซรงโ€žยฐรฆโ€“ยฐรฆหœลธรฅล“โ€“รฉยจยฐ", + ["Improved Fire Ward"]="รฅยผยทรฅล’โ€“รฉหœยฒรจยญยทรงยยซรงโ€žยฐรงยตยรงโ€ขล’", + ["Improved Fireball"]="รฅยผยทรฅล’โ€“รงยยซรงยฦ’รจยกโ€œ", + ["Improved Firebolt"]="รฅยผยทรฅล’โ€“รงยยซรงโ€žยฐรงยฎยญ", + ["Improved Firestone"]="รฅยผยทรฅล’โ€“รงยยซรงโ€žยฐรงลธยณ", + ["Improved Flamestrike"]="รฅยผยทรฅล’โ€“รงฦ’ห†รงโ€žยฐรฉยขยจรฆลกยด", + ["Improved Flametongue Weapon"]="รฅยผยทรฅล’โ€“รงยยซรจห†ล’รฆยญยฆรฅโ„ขยจ", + ["Improved Flash of Light"]="รฅยผยทรฅล’โ€“รจยโ€“รฅโ€ฆโ€ฐรฉโ€“ฦ’รงยยพ", + ["Improved Frost Nova"]="รฅยผยทรฅล’โ€“รฅโ€ ยฐรฉล“ล“รฆโ€“ยฐรฆหœลธ", + ["Improved Frost Ward"]="รฅยผยทรฅล’โ€“รฉหœยฒรจยญยทรฅโ€ ยฐรฉล“ล“รงยตยรงโ€ขล’", + ["Improved Frostbolt"]="รฅยผยทรฅล’โ€“รฅยฏโ€™รฅโ€ ยฐรงยฎยญ", + ["Improved Frostbrand Weapon"]="รฅยผยทรฅล’โ€“รฅโ€ ยฐรฅยฐยรฆยญยฆรฅโ„ขยจ", + ["Improved Garrote"]="รฅยผยทรฅล’โ€“รงยตลพรฅโ€“โ€ฐ", + ["Improved Ghost Wolf"]="รฅยผยทรฅล’โ€“รฅยนยฝรฉยญโ€šรคยนโ€นรงโ€นยผ", + ["Improved Gouge"]="รฅยผยทรฅล’โ€“รฉโ€˜ยฟรฆโ€œล ", + ["Improved Grace of Air Totem"]="รฅยผยทรฅล’โ€“รฉยขยจรคยนโ€นรฅโ€žยชรฉโ€บโ€ฆรฅล“โ€“รฉยจยฐ", + ["Improved Grounding Totem"]="รฅยผยทรฅล’โ€“รฆย ยนรฅลธยบรฅล“โ€“รฉยจยฐ", + ["Improved Hammer of Justice"]="รฅยผยทรฅล’โ€“รจยฃยรฆยฑยบรคยนโ€นรฉล’หœ", + ["Improved Hamstring"]="รฅยผยทรฅล’โ€“รฆโ€“ยทรงยญโ€น", + ["Improved Healing Stream Totem"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรคยนโ€นรฆยณโ€ฐรฅล“โ€“รฉยจยฐ", + ["Improved Healing Touch"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรคยนโ€นรจยงยธ", + ["Improved Healing Wave"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรฆยณยข", + ["Improved Healing"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรจยกโ€œ", + ["Improved Health Funnel"]="รฅยผยทรฅล’โ€“รงโ€ลธรฅโ€˜ยฝรฉโ‚ฌลกรฉยโ€œ", + ["Improved Healthstone"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรงลธยณ", + ["Improved Heroic Strike"]="รฅยผยทรฅล’โ€“รจโ€นยฑรฅโ€นโ€กรฆโ€ฐโ€œรฆโ€œล ", + ["Improved Hunter's Mark"]="รฅยผยทรฅล’โ€“รงยยตรคยบยบรฅยยฐรจยจหœ", + ["Improved Immolate"]="รฅยผยทรฅล’โ€“รงยยปรงยฅยญ", + ["Improved Imp"]="รฅยผยทรฅล’โ€“รฅยฐยรฉยฌยผ", + ["Improved Inner Fire"]="รฅยผยทรฅล’โ€“รฅยฟฦ’รฉยห†รคยนโ€นรงยยซ", + ["Improved Instant Poison"]="รฅยผยทรฅล’โ€“รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ", + ["Improved Intercept"]="รฅยผยทรฅล’โ€“รฆโ€โ€รฆห†ยช", + ["Improved Intimidating Shout"]="รฅยผยทรฅล’โ€“รงย ยดรจโ€ ยฝรฆโ‚ฌโ€™รฅยยผ", + ["Improved Judgement"]="รฅยผยทรฅล’โ€“รฅยฏยฉรฅห†ยค", + ["Improved Kick"]="รฅยผยทรฅล’โ€“รจโ€ฆยณรจยธยข", + ["Improved Kidney Shot"]="รฅยผยทรฅล’โ€“รจโ€ฆลฝรฆโ€œล ", + ["Improved Lash of Pain"]="รฅยผยทรฅล’โ€“รฅล โ€กรงโ€”โ€บรฉลพยญรงยฌลพ", + ["Improved Lay on Hands"]="รฅยผยทรฅล’โ€“รจยโ€“รงโ„ขโ€šรจยกโ€œ", + ["Improved Lesser Healing Wave"]="รฅยผยทรฅล’โ€“รฆยฌยกรงยดลกรฆยฒยปรงโ„ขโ€šรฆยณยข", + ["Improved Life Tap"]="รฅยผยทรฅล’โ€“รงโ€ลธรฅโ€˜ยฝรฅห†โ€ รฆยตย", + ["Improved Lightning Bolt"]="รฅยผยทรฅล’โ€“รฉโ€“ฦ’รฉโ€บยปรงยฎยญ", + ["Improved Lightning Shield"]="รฅยผยทรฅล’โ€“รฉโ€“ฦ’รฉโ€บยปรคยนโ€นรงโ€บยพ", + ["Improved Magma Totem"]="รฅยผยทรฅล’โ€“รงโ€ โ€รฅยฒยฉรฅล“โ€“รฉยจยฐ", + ["Improved Mana Burn"]="รฅยผยทรฅล’โ€“รฆยณโ€ขรฅล โ€บรงโ€กฦ’รงโ€กโ€™", + ["Improved Mana Shield"]="รฅยผยทรฅล’โ€“รฆยณโ€ขรฅล โ€บรจยญยทรงโ€บยพ", + ["Improved Mana Spring Totem"]="รฅยผยทรฅล’โ€“รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยณโ€ฐรฅล“โ€“รฉยจยฐ", + ["Improved Mark of the Wild"]="รฅยผยทรฅล’โ€“รฉโ€กลฝรฆโ‚ฌยงรฅยยฐรจยจหœ", + ["Improved Mend Pet"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรฅยฏยตรงโ€ฐยฉ", + ["Improved Mind Blast"]="รฅยผยทรฅล’โ€“รฅยฟฦ’รฉยห†รฉล“โ€กรงห†โ€ ", + ["Improved Moonfire"]="รฅยผยทรฅล’โ€“รฆล“ห†รงยยซรจยกโ€œ", + ["Improved Nature's Grasp"]="รฅยผยทรฅล’โ€“รจโ€กยชรงโ€žยถรคยนโ€นรฆยยก", + ["Improved Overpower"]="รฅยผยทรฅล’โ€“รฅยฃโ€œรฅห†ยถ", + ["Improved Power Word: Fortitude"]="รฅยผยทรฅล’โ€“รงล“ลธรจยจโ‚ฌรจยกโ€œรฏยผลกรฉลธล’", + ["Improved Power Word: Shield"]="รฅยผยทรฅล’โ€“รงล“ลธรจยจโ‚ฌรจยกโ€œรฏยผลกรงโ€บยพ", + ["Improved Prayer of Healing"]="รฅยผยทรฅล’โ€“รฆยฒยปรงโ„ขโ€šรงยฆยฑรจยจโ‚ฌ", + ["Improved Psychic Scream"]="รฅยผยทรฅล’โ€“รฅยฟฦ’รฉยห†รฅยฐโ€“รฅหœยฏ", + ["Improved Pummel"]="รฅยผยทรฅล’โ€“รฆโ€นยณรฆโ€œล ", + ["Improved Regrowth"]="รฅยผยทรฅล’โ€“รงโ„ขโ€™รฅยห†", + ["Improved Reincarnation"]="รฅยผยทรฅล’โ€“รจยคโ€กรงโ€ลธ", + ["Improved Rejuvenation"]="รฅยผยทรฅล’โ€“รฅโ€บลพรฆหœยฅรจยกโ€œ", + ["Improved Rend"]="รฅยผยทรฅล’โ€“รฆโ€™โ€ขรจยฃโ€š", + ["Improved Renew"]="รฅยผยทรฅล’โ€“รฆยยขรฅยพยฉ", + ["Improved Retribution Aura"]="รฅยผยทรฅล’โ€“รฆโ€กยฒรงยฝยฐรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Improved Revenge"]="รฅยผยทรฅล’โ€“รฅยพยฉรคยปโ€ก", + ["Improved Revive Pet"]="รฅยผยทรฅล’โ€“รฅยพยฉรฆยดยปรฅยฏยตรงโ€ฐยฉ", + ["Improved Righteous Fury"]="รฅยผยทรฅล’โ€“รฆยญยฃรงยพยฉรคยนโ€นรฆโ‚ฌโ€™", + ["Improved Rockbiter Weapon"]="รฅยผยทรฅล’โ€“รงลธยณรฅล’โ€“รฆยญยฆรฅโ„ขยจ", + ["Improved Rupture"]="รฅยผยทรฅล’โ€“รฅโ€ฐยฒรจยฃโ€š", + ["Improved Sap"]="รฅยผยทรฅล’โ€“รฆโ€šยถรฆยฃย", + ["Improved Scorch"]="รฅยผยทรฅล’โ€“รงยยผรงโ€กโ€™", + ["Improved Scorpid Sting"]="รฅยผยทรฅล’โ€“รฆยฏโ€™รจย ยรฉโ€กหœรฅห†ยบ", + ["Improved Seal of Righteousness"]="รฅยผยทรฅล’โ€“รฆยญยฃรงยพยฉรจยโ€“รฅยยฐ", + ["Improved Seal of the Crusader"]="รฅยผยทรฅล’โ€“รฅยยรฅยญโ€”รจยปยรจยโ€“รฅยยฐ", + ["Improved Searing Pain"]="รฅยผยทรฅล’โ€“รงยยผรงโ€ ยฑรคยนโ€นรงโ€”โ€บ", + ["Improved Searing Totem"]="รฅยผยทรฅล’โ€“รงยยผรงโ€ ยฑรฅล“โ€“รฉยจยฐ", + ["Improved Serpent Sting"]="รฅยผยทรฅล’โ€“รฆยฏโ€™รจโ€บโ€กรฉโ€กหœรฅห†ยบ", + ["Improved Shadow Bolt"]="รฅยผยทรฅล’โ€“รฆลกโ€”รฅยฝยฑรงยฎยญ", + ["Improved Shadow Word: Pain"]="รฅยผยทรฅล’โ€“รฆลกโ€”รจยจโ‚ฌรจยกโ€œรฏยผลกรงโ€”โ€บ", + ["Improved Shield Bash"]="รฅยผยทรฅล’โ€“รงโ€บยพรฆโ€œล ", + ["Improved Shield Block"]="รฅยผยทรฅล’โ€“รงโ€บยพรงโ€ฐล’รฆย ยผรฆโ€œโ€น", + ["Improved Shield Wall"]="รฅยผยทรฅล’โ€“รงโ€บยพรงโ€ฐโ€ ", + ["Improved Shred"]="รฅยผยทรฅล’โ€“รฆโ€™โ€ขรงยขลฝ", + ["Improved Sinister Strike"]="รฅยผยทรฅล’โ€“รฉโ€šยชรฆฦ’ยกรฆโ€ยปรฆโ€œล ", + ["Improved Slam"]="รฅยผยทรฅล’โ€“รงล’โ€บรฆโ€œล ", + ["Improved Slice and Dice"]="รฅยผยทรฅล’โ€“รฅห†โ€กรฅโ€ฐยฒ", + ["Improved Spellstone"]="รฅยผยทรฅล’โ€“รฆยณโ€ขรจยกโ€œรงลธยณ", + ["Improved Sprint"]="รฅยผยทรฅล’โ€“รงโ€“ยพรจยทโ€˜", + ["Improved Starfire"]="รฅยผยทรฅล’โ€“รฆหœลธรงยยซรจยกโ€œ", + ["Improved Stoneclaw Totem"]="รฅยผยทรฅล’โ€“รงลธยณรงห†ยชรฅล“โ€“รฉยจยฐ", + ["Improved Stoneskin Totem"]="รฅยผยทรฅล’โ€“รงลธยณรงโ€ยฒรฅล“โ€“รฉยจยฐ", + ["Improved Strength of Earth Totem"]="รฅยผยทรฅล’โ€“รฅยคยงรฅล“ยฐรคยนโ€นรฅล โ€บรฅล“โ€“รฉยจยฐ", + ["Improved Succubus"]="รฅยผยทรฅล’โ€“รฉยญโ€ฆรฉยญโ€", + ["Improved Sunder Armor"]="รฅยผยทรฅล’โ€“รงย ยดรงโ€ยฒรฆโ€ยปรฆโ€œล ", + ["Improved Taunt"]="รฅยผยทรฅล’โ€“รฅหœยฒรจยซยท", + ["Improved Thorns"]="รฅยผยทรฅล’โ€“รจยล รฆยฃหœรจยกโ€œ", + ["Improved Thunder Clap"]="รฅยผยทรฅล’โ€“รฉโ€บยทรฉล“โ€ รคยธโ‚ฌรฆโ€œล ", + ["Improved Tranquility"]="รฅยผยทรฅล’โ€“รฅยฏยงรฉยล“", + ["Improved Vampiric Embrace"]="รฅยผยทรฅล’โ€“รฅยยธรจยกโ‚ฌรฉยฌยผรงลกโ€žรฆโ€œยรฆล ยฑ", + ["Improved Vanish"]="รฅยผยทรฅล’โ€“รฆยถห†รฅยคยฑ", + ["Improved Voidwalker"]="รฅยผยทรฅล’โ€“รจโ„ขโ€บรงยฉยบรจยกล’รจโ‚ฌโ€ฆ", + ["Improved Windfury Weapon"]="รฅยผยทรฅล’โ€“รฉยขยจรฆโ‚ฌโ€™รฆยญยฆรฅโ„ขยจ", + ["Improved Wing Clip"]="รฅยผยทรฅล’โ€“รฆโ€˜โ€รงยตโ€ ", + ["Improved Wrath"]="รฅยผยทรฅล’โ€“รฆโ€ ยครฆโ‚ฌโ€™", + ["Incinerate"]="รงโ€กโ€™รงโ€บยก", + ["Inferno"]="รฅล“ยฐรงยโ€žรงยยซ", + ["Initiative"]="รฅโ€ฆห†รงโ„ขยผรฅห†ยถรคยบยบ", + ["Inner Fire"]="รฅยฟฦ’รฉยห†รคยนโ€นรงยยซ", + ["Inner Focus"]="รฅยฟฦ’รฉยห†รฅยฐห†รฆยณยจ", + ["Innervate"]="รฅโ€ขลธรฅโ€นโ€ข", + ["Insect Swarm"]="รจลธยฒรงยพยค", + ["Inspiration"]="รฉยห†รฆโ€žลธ", + ["Instant Poison II"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ II", + ["Instant Poison III"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ III", + ["Instant Poison IV"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ IV", + ["Instant Poison V"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ V", + ["Instant Poison VI"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ VI", + ["Instant Poison"]="รฉโ‚ฌลธรฆโ€ขห†รฆยฏโ€™รจโ€”ยฅ", + ["Intensity"]="รฅยผยทรงฦ’ห†", + ["Intercept"]="รฆโ€โ€รฆห†ยช", + ["Intercept Stun"] = "รฆโ€โ€รฆห†ยชรฆหœยรจยฟยท", +-- ["Intervene"] = true, + ["Intimidating Shout"]="รงย ยดรจโ€ ยฝรฆโ‚ฌโ€™รฅยยผ", + ["Intimidation"]="รจโ€žโ€ฆรจยฟยซ", +-- ["Invisibility"] = true, + ["Iron Will"]="รฉโ€นยผรฉยยตรฆโ€žยรฅยฟโ€”", + ["Judgement of Command"]="รฅโ€˜ยฝรคยปยครฅยฏยฉรฅห†ยค", + ["Judgement of Justice"]="รฆยญยฃรงยพยฉรฅยฏยฉรฅห†ยค", + ["Judgement of Light"]="รจยโ€“รฅโ€ฆโ€ฐรฅยฏยฉรฅห†ยค", + ["Judgement of Righteousness"]="รฆยญยฃรงยพยฉรฅยฏยฉรฅห†ยค", + ["Judgement of Wisdom"]="รฆโ„ขยบรฆโ€ฆยงรฅยฏยฉรฅห†ยค", + ["Judgement of the Crusader"]="รฅยยรฅยญโ€”รจยปยรฅยฏยฉรฅห†ยค", + ["Judgement"]="รฅยฏยฉรฅห†ยค", + ["Kick"]="รจโ€ฆยณรจยธยข", + ["Kick - Silenced"] = "รจโ€ฆยณรจยธยข - รฆยฒห†รฉยปหœ", + ["Kidney Shot"]="รจโ€ฆลฝรฆโ€œล ", +-- ["Kill Command"] = true, + ["Killer Instinct"]="รฆยฎยบรฆห†ยฎรฆล“ยฌรจฦ’ยฝ", + ["Kodo Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรงยงโ€˜รฅยคลกรงยยธ", +-- ["Lacerate"] = true, + ["Lash of Pain"]="รฅล โ€กรงโ€”โ€บรฉลพยญรงยฌลพ", + ["Last Stand"]="รงย ยดรฉโ€กล“รฆยฒโ€ฐรจห†ลธ", + ["Lasting Judgement"]="รฆล’ยรคยนโ€ฆรฅยฏยฉรฅห†ยค", + ["Lay on Hands"]="รจยโ€“รงโ„ขโ€šรจยกโ€œ", + ["Leader of the Pack"]="รงยยธรงยพยครฉย หœรจยขโ€“", + ["Leather"]="รงลกยฎรฉยยฉ", + ["Leatherworking"]="รจยฃยฝรงลกยฎ", + ["Lesser Heal"]="รฆยฌยกรงยดลกรฆยฒยปรงโ„ขโ€šรจยกโ€œ", + ["Lesser Healing Wave"]="รฆยฌยกรงยดลกรฆยฒยปรงโ„ขโ€šรฆยณยข", + ["Lesser Invisibility"]="รฆยฌยกรงยดลกรฉลกยฑรฅยฝยขรจยกโ€œ", + ["Lethal Shots"]="รฅยฅยชรฅโ€˜ยฝรฅยฐโ€žรฆโ€œล ", + ["Lethality"]="รจโ€กยดรฅโ€˜ยฝรฅยยทรจยฅยฒ", + ["Levitate"]="รฆยผโ€šรฆยตยฎรจยกโ€œ", + ["Libram"]="รจยโ€“รฅยฅโ€˜", +-- ["Lifebloom"] = true, + ["Life Tap"]="รงโ€ลธรฅโ€˜ยฝรฅห†โ€ รฆยตย", + ["Lifegiving Gem"] = true, + ["Lightning Bolt"]="รฉโ€“ฦ’รฉโ€บยปรงยฎยญ", + ["Lightning Breath"]="รฉโ€“ฦ’รฉโ€บยปรฅยยรฆยยฏ", + ["Lightning Mastery"]="รฉโ€“ฦ’รฉโ€บยปรฅยฐห†รงยฒยพ", + ["Lightning Reflexes"]="รฉโ€“ฦ’รฉโ€บยปรฅยยรฅยฐโ€ž", + ["Lightning Shield"]="รฉโ€“ฦ’รฉโ€บยปรคยนโ€นรงโ€บยพ", + ["Lightwell Renew"]="รฆยยขรฅยพยฉรฅโ€ฆโ€ฐรฆยลธรฆยณโ€ฐ", + ["Lightwell"]="รฅโ€ฆโ€ฐรฆยลธรฆยณโ€ฐ", + ["Lockpicking"]="รฉโ€“โ€นรฉลฝโ€“", + ["Long Daze"]="รฉโ€ขยทรฆโ„ขโ€šรฉโ€“โ€œรงล“ยฉรฆลกห†", + ["Mace Specialization"]="รฉล’หœรฉยกลพรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Mace Stun Effect"]="รฉล’หœรฆโ€œล รฆหœยรจยฟยทรฆโ€ขห†รฆลพล“", + ["Mage Armor"]="รฉยญโ€รงโ€ยฒรจยกโ€œ", + ["Magma Totem"]="รงโ€ โ€รฅยฒยฉรฅล“โ€“รฉยจยฐ", + ["Mail"]="รฉลฝโ€“รงโ€ยฒ", +-- ["Maim"] = true, + ["Malice"]="รฆฦ’ยกรฆโ€žย", + ["Mana Burn"]="รฆยณโ€ขรฅล โ€บรงโ€กฦ’รงโ€กโ€™", + ["Mana Shield"]="รฆยณโ€ขรฅล โ€บรจยญยทรงโ€บยพ", + ["Mana Spring Totem"]="รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยณโ€ฐรฅล“โ€“รฉยจยฐ", + ["Mana Tide Totem"]="รฆยณโ€ขรฅล โ€บรคยนโ€นรฆยฝยฎรฅล“โ€“รฉยจยฐ", + ["Mangle"]="รฅโ€ฐยฒรงยขลฝ", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"]="รฉโ€กลฝรฆโ‚ฌยงรฅยยฐรจยจหœ", + ["Martyrdom"]="รฆยฎโ€ฐรฉโ€บยฃ", +-- ["Mass Dispel"] = true, + ["Master Demonologist"]="รฆฦ’ยกรฉยญโ€รฅยญยธรจยญหœรฅยคยงรฅยธยซ", + ["Master Summoner"]="รฅยยฌรฅโ€“ลกรฅยคยงรฅยธยซ", + ["Master of Deception"]="รฆยฌยบรจยฉยรฅยคยงรฅยธยซ", + ["Maul"]="รฆยงล’รฆโ€œล ", + ["Mechanostrider Piloting"]="รฉยจลฝรจยกโ€œรฏยผลกรฆยฉลธรฆยขยฐรฉโ„ขยธรจยกล’รฉยณยฅ", + ["Meditation"]="รฅโ€ ยฅรฆฦ’ยณ", + ["Melee Specialization"]="รจยฟโ€˜รฆห†ยฐรฅยฐห†รงยฒยพ", + ["Mend Pet"]="รฆยฒยปรงโ„ขโ€šรฅยฏยตรงโ€ฐยฉ", + ["Mental Agility"]="รงยฒยพรงยฅลพรฆโ€ขยรฉล ยณ", + ["Mental Strength"]="รฅยฟฦ’รฉยห†รคยนโ€นรฅล โ€บ", + ["Mind Blast"]="รฅยฟฦ’รฉยห†รฉล“โ€กรงห†โ€ ", + ["Mind Control"]="รงยฒยพรงยฅลพรฆลฝยงรฅห†ยถ", + ["Mind Flay"]="รงยฒยพรงยฅลพรฉลพยญรงยฌลพ", + ["Mind Soothe"]="รฅยฎโ€ฐรฆโ€™ยซรฅยฟฦ’รฉยห†", + ["Mind Vision"]="รฅยฟฦ’รฉยห†รจยฆโ€“รงโ€ขล’", + ["Mind-numbing Poison II"]="รฉยบยปรงโ€”ยนรฆยฏโ€™รจโ€”ยฅ II", + ["Mind-numbing Poison III"]="รฉยบยปรงโ€”ยนรฆยฏโ€™รจโ€”ยฅ III", + ["Mind-numbing Poison"]="รฉยบยปรงโ€”ยนรฆยฏโ€™รจโ€”ยฅ", + ["Mining"]="รฆลฝยกรงยคยฆ", +-- ["Misdirection"] = true, + ["Mocking Blow"]="รฆโ€กยฒรฆห†โ€™รงโ€”โ€บรฆโ€œล ", +-- ["Molten Armor"] = true, + ["Mongoose Bite"]="รจยฒโ€œรฉยผยฌรฆโ€™โ€ขรฅโ€™ยฌ", + ["Monster Slaying"]="รฆโ‚ฌยชรงโ€ฐยฉรฆยฎยบรฆโ€ฐโ€น", + ["Moonfire"]="รฆล“ห†รงยยซรจยกโ€œ", + ["Moonfury"]="รฆล“ห†รฆโ‚ฌโ€™", + ["Moonglow"]="รฆล“ห†รฅโ€ฆโ€ฐ", + ["Moonkin Aura"]="รฆยขลธรงยยธรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Moonkin Form"]="รฆยขลธรงยยธรฅยฝยขรฆโ€ฆโ€น", + ["Mortal Shots"]="รจโ€กยดรฆยญยปรฅยฐโ€žรฆโ€œล ", + ["Mortal Strike"]="รจโ€กยดรฆยญยปรฆโ€ฐโ€œรฆโ€œล ", + ["Multi-Shot"]="รฅยคลกรฉโ€กยรฅยฐโ€žรฆโ€œล ", + ["Murder"]="รจยฌโ‚ฌรฆยฎยบ", +-- ["Mutilate"] = true, + ["Natural Armor"]="รจโ€กยชรงโ€žยถรจยญยทรงโ€ยฒ", + ["Natural Shapeshifter"]="รจโ€กยชรงโ€žยถรจยฎล รฅยฝยข", + ["Natural Weapons"]="รฆยญยฆรฅโ„ขยจรฅยนยณรจยกยก", + ["Nature Resistance Totem"]="รจโ€กยชรงโ€žยถรฆล โ€”รฆโ‚ฌยงรฅล“โ€“รฉยจยฐ", + ["Nature Resistance"]="รจโ€กยชรงโ€žยถรฆล โ€”รฆโ‚ฌยง", + ["Nature's Focus"]="รจโ€กยชรงโ€žยถรฉโ€บโ€ รคยธยญ", + ["Nature's Grace"]="รจโ€กยชรงโ€žยถรคยนโ€นรจยณล“", + ["Nature's Grasp"]="รจโ€กยชรงโ€žยถรคยนโ€นรฆยยก", + ["Nature's Reach"]="รจโ€กยชรงโ€žยถรฅยปยถรคยผยธ", + ["Nature's Swiftness"]="รจโ€กยชรงโ€žยถรจยฟโ€ฆรฆยยท", + ["Nightfall"]="รฅยคล“รฅยนโ€ข", + ["Omen of Clarity"]="รฆยธโ€ฆรฆโ„ขยฐรฉย ยรฅโ€ฆโ€ ", + ["One-Handed Axes"]="รฅโ€“ยฎรฆโ€ฐโ€นรฆโ€“ยง", + ["One-Handed Maces"]="รฅโ€“ยฎรฆโ€ฐโ€นรฉล’หœ", + ["One-Handed Swords"]="รฅโ€“ยฎรฆโ€ฐโ€นรฅล ย", + ["One-Handed Weapon Specialization"]="รฅโ€“ยฎรฆโ€ฐโ€นรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Opening - No Text"]="Opening - No Text", + ["Opening"]="รฆโ€ฐโ€œรฉโ€“โ€น", + ["Opportunity"]="รคยผยบรฆยฉลธรจโ‚ฌล’รฅโ€นโ€ข", + ["Overpower"]="รฅยฃโ€œรฅห†ยถ", +-- ["Pain Suppression"] = true, + ["Paranoia"]="รฅยคลกรงโ€“โ€˜", + ["Parry"]="รฆโ€นโ€บรฆลพยถ", + ["Pathfinding"]="รฅยฐโ€นรจยทยฏ", + ["Perception"]="รฆโ€žลธรงลธยฅ", + ["Permafrost"]="รฆยฅยตรฅยฏโ€™รฅโ€ ยฐรฉล“ล“", + ["Pet Aggression"]="รฅยฏยตรงโ€ฐยฉรฅยฅยฝรฉยฌยฅ", + ["Pet Hardiness"]="รฅยฏยตรงโ€ฐยฉรจโ‚ฌยรคยนโ€ฆ", + ["Pet Recovery"]="รฅยฏยตรงโ€ฐยฉรฆยยขรฅยพยฉ", + ["Pet Resistance"]="รฅยฏยตรงโ€ฐยฉรฆล โ€”รฉยญโ€", + ["Phase Shift"]="รงโ€บยธรคยฝยรจยฎล รฆยโ€บ", + ["Pick Lock"]="รฉโ€“โ€นรฉลฝโ€“", + ["Pick Pocket"]="รฅยยทรงยซล ", + ["Piercing Howl"]="รฅห†ยบรจโ‚ฌยณรฆโ‚ฌโ€™รฅยยผ", + ["Piercing Ice"]="รฅห†ยบรฉยชยจรฅยฏโ€™รฅโ€ ยฐ", + ["Plate Mail"]="รฉลฝยงรงโ€ยฒ", + ["Poison Cleansing Totem"]="รฆยธโ€ฆรฆยฏโ€™รฅล“โ€“รฉยจยฐ", + ["Poisons"]="รฆยฏโ€™รจโ€”ยฅ", + ["Polearm Specialization"]="รฉโ€ขยทรฆลธโ€žรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Polearms"]="รฉโ€ขยทรฆลธโ€žรฆยญยฆรฅโ„ขยจ", + ["Polymorph"]="รจยฎล รฅยฝยขรจยกโ€œ", + ["Polymorph: Pig"] ="รจยฎล รฅยฝยขรจยกโ€œรฏยผลกรจยฑยฌ", + ["Polymorph: Turtle"] ="รจยฎล รฅยฝยขรจยกโ€œรฏยผลกรฉยพล“", + ["Portal: Darnassus"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฉยโ€รงยดยรจหœโ€กรฆโ€“ยฏ", + ["Portal: Ironforge"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฉยยตรงห†ยรฅย ยก", + ["Portal: Orgrimmar"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฅยฅยงรฆย ยผรงโ€˜ยช", + ["Portal: Stormwind"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฆลกยดรฉยขยจรฅลธลฝ", + ["Portal: Thunder Bluff"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฉโ€บยทรฉล“โ€ รฅยดโ€“", + ["Portal: Undercity"]="รฅโ€šยณรฉโ‚ฌยรฉโ€“โ‚ฌรฏยผลกรฅยนยฝรฆลกโ€”รฅลธลฝ", + ["Pounce Bleed"]="รจยกโ‚ฌรจยฅยฒ", + ["Pounce"]="รงยชยรจยฅยฒ", + ["Power Infusion"]="รฆยณยจรฅโ€ฆยฅรจฦ’ยฝรฉโ€กย", + ["Power Word: Fortitude"]="รงล“ลธรจยจโ‚ฌรจยกโ€œรฏยผลกรฉลธล’", + ["Power Word: Shield"]="รงล“ลธรจยจโ‚ฌรจยกโ€œรฏยผลกรงโ€บยพ", + ["Prayer of Fortitude"]="รฅย โ€ฆรฉลธล’รงยฆยฑรจยจโ‚ฌ", + ["Prayer of Healing"]="รฆยฒยปรงโ„ขโ€šรงยฆยฑรจยจโ‚ฌ", +-- ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"]="รฆลกโ€”รฅยฝยฑรฉหœยฒรจยญยทรงยฆยฑรจยจโ‚ฌ", + ["Prayer of Spirit"]="รงยฒยพรงยฅลพรงยฆยฑรจยจโ‚ฌ", + ["Precision"]="รงยฒยพรงยขยบ", + ["Predatory Strikes"]="รงล’โ€บรงยยธรฆโ€ยปรฆโ€œล ", + ["Premeditation"]="รฉย ยรจยฌโ‚ฌ", + ["Preparation"]="รคยผยบรฆยฉลธรฅยพโ€ฆรงโ„ขยผ", + ["Presence of Mind"]="รฅล โ€บรฉโ€กยรงลกโ€žรจยญโ€ฐรฆหœลฝ", + ["Primal Fury"]="รฅลฝลธรฅยงโ€นรงโ€นโ€šรฆโ‚ฌโ€™", + ["Prowl"]="รฆยฝโ€บรจยกล’", + ["Psychic Scream"]="รฅยฟฦ’รฉยห†รฅยฐโ€“รฅหœยฏ", + ["Pummel"]="รฆโ€นยณรฆโ€œล ", + ["Purge"]="รฆยทยจรฅล’โ€“รจยกโ€œ", + ["Purification"]="รฆยทยจรฅล’โ€“", + ["Purify"]="รงยดโ€รฆยทยจรจยกโ€œ", + ["Pursuit of Justice"]="รฆยญยฃรงยพยฉรจยฟยฝรฆโ€œล ", + ["Pyroblast"]="รงโ€šลฝรงห†โ€ รจยกโ€œ", + ["Pyroclasm"]="รงยยซรงโ€žยฐรจยกยรฆโ€™ลพ", + ["Quick Shots"] = "รฅยฟยซรฉโ‚ฌลธรฅยฐโ€žรฆโ€œล ", + ["Quickness"]="รจยฟโ€ฆรฆยยท", + ["Rain of Fire"]="รงยยซรงโ€žยฐรคยนโ€นรฉโ€บยจ", + ["Rake"]="รฆลฝฦ’รฆโ€œล ", + ["Ram Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรงยพล ", + ["Ranged Weapon Specialization"]="รฉยย รงยจโ€นรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Rapid Concealment"]="รจยฟโ€ฆรฉโ‚ฌลธรฉลกยฑรจโ€ยฝ", + ["Rapid Fire"]="รฆโ‚ฌยฅรฉโ‚ฌลธรฅยฐโ€žรฆโ€œล ", + ["Raptor Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรจยฟโ€ฆรงล’โ€บรฉยพย", + ["Raptor Strike"]="รงล’โ€บรงยฆยฝรคยธโ‚ฌรฆโ€œล ", + ["Ravage"]="รฆยฏโ‚ฌรฆยปโ€ฆ", + ["Readiness"]="รฆยบโ€“รฅโ€šโ„ขรฅยฐยฑรงยทโ€™", + ["Rebirth"]="รจยคโ€กรงโ€ลธ", + ["Reckless Charge"]="รงโ€žยกรงโ€ขยรจยกยรฉโ€นโ€™", + ["Recklessness"]="รฉยญยฏรจลฝยฝ", + ["Reckoning"]="รฆยธโ€ฆรงยฎโ€”", + ["Redemption"]="รฆโ€ขโ€˜รจยดโ€“", + ["Redoubt"]="รงโ€บยพรงโ€ฐล’รฅยฃยรฅยฃหœ", + ["Reflection"]="รฅยยรฅยฐโ€ž", + ["Regeneration"]="รฅโ€ ยรงโ€ลธ", + ["Regrowth"]="รงโ„ขโ€™รฅยห†", + ["Reincarnation"]="รจยคโ€กรงโ€ลธรฆโ€ขห†รฆลพล“", + ["Rejuvenation"]="รฅโ€บลพรฆหœยฅรจยกโ€œ", + ["Relentless Strikes"]="รงโ€žยกรฆฦ’โ€ฆรฆโ€ฐโ€œรฆโ€œล ", + ["Remorseless"] = "รฅโ€ ยทรฉโ€ฆยท", + ["Remorseless Attacks"]="รฅโ€ ยทรฉโ€ฆยทรฆโ€ยปรฆโ€œล ", + ["Remove Curse"]="รจยงยฃรฉโ„ขยครจยฉโ€บรฅโ€™โ€™", + ["Remove Insignia"]="รจยงยฃรฉโ„ขยครฅยพยฝรจยจหœ", + ["Remove Lesser Curse"]="รจยงยฃรฉโ„ขยครฆยฌยกรงยดลกรจยฉโ€บรฅโ€™โ€™", + ["Rend"]="รฆโ€™โ€ขรจยฃโ€š", + ["Renew"]="รฆยยขรฅยพยฉ", + ["Repentance"]="รฆโ€กยบรฆโ€šโ€", + ["Resurrection"]="รฅยพยฉรฆยดยปรจยกโ€œ", + ["Retaliation"]="รฅยยรฆโ€œล รฉยขยจรฆลกยด", + ["Retribution Aura"]="รฆโ€กยฒรงยฝยฐรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Revenge Stun"]="รฅยพยฉรคยปโ€กรฆหœยรจยฟยท", + ["Revenge"]="รฅยพยฉรคยปโ€ก", + ["Reverberation"]="รจยฟยดรฉลธยฟ", + ["Revive Pet"]="รฅยพยฉรฆยดยปรฅยฏยตรงโ€ฐยฉ", +-- ["Righteous Defense"] = true, + ["Righteous Fury"]="รฆยญยฃรงยพยฉรคยนโ€นรฆโ‚ฌโ€™", + ["Rip"]="รฆโ€™โ€ขรฆโ€ฐยฏ", + ["Riposte"]="รฉโ€šโ€žรฆโ€œล ", + ["Ritual of Doom Effect"]="รฆล“ยซรฆโ€”ยฅรฅโ€žโ‚ฌรฅยผยรฆโ€ขห†รฆลพล“", + ["Ritual of Doom"]="รฆล“ยซรฆโ€”ยฅรฅโ€žโ‚ฌรฅยผย", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"]="รฅยยฌรฅโ€“ลกรฅโ€žโ‚ฌรฅยผย", + ["Rockbiter Weapon"]="รงลธยณรฅล’โ€“รฆยญยฆรฅโ„ขยจ", + ["Rogue Passive"]="Rogue Passive", + ["Rough Sharpening Stone"]="รฅล ยฃรจยณยชรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Ruin"]="รฆยฏโ‚ฌรฆยปโ€ฆ", + ["Rupture"]="รฅโ€ฐยฒรจยฃโ€š", + ["Ruthlessness"]="รงโ€žยกรฆฦ’โ€ฆ", + ["Sacrifice"]="รงล ยงรงโ€ฐยฒ", + ["Safe Fall"]="รฅยฎโ€ฐรฅโ€ฆยจรฉโ„ขยรจยยฝ", + ["Sanctity Aura"]="รจยโ€“รฆยฝโ€รฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Sap"]="รฆโ€šยถรฆยฃย", + ["Savage Fury"]="รฉโ€กลฝรจย ยปรฆลกยดรฆโ‚ฌโ€™", + ["Savage Strikes"]="รงล’โ€บรงฦ’ห†รฅยผยทรฆโ€œล ", + ["Scare Beast"]="รฆยยรฅลกโ€กรฉโ€กลฝรงยยธ", + ["Scatter Shot"]="รฉยฉโ€ฆรฆโ€ขยฃรฅยฐโ€žรฆโ€œล ", + ["Scorch"]="รงยยผรงโ€กโ€™", + ["Scorpid Poison"]="รจย ยรฆยฏโ€™", + ["Scorpid Sting"]="รฆยฏโ€™รจย ยรฉโ€กหœรฅห†ยบ", + ["Screech"]="รฅยฐโ€“รฅหœยฏ", + ["Seal Fate"]="รฅยฐยรฅยยฐรฅโ€˜ยฝรฉยโ€น", +-- ["Seal of Blood"] = true, + ["Seal of Command"]="รฅโ€˜ยฝรคยปยครจยโ€“รฅยยฐ", + ["Seal of Justice"]="รฅโ€ฆยฌรฆยญยฃรจยโ€“รฅยยฐ", + ["Seal of Light"]="รฅโ€ฆโ€ฐรฆหœลฝรจยโ€“รฅยยฐ", + ["Seal of Righteousness"]="รฆยญยฃรงยพยฉรจยโ€“รฅยยฐ", + ["Seal of Wisdom"]="รฆโ„ขยบรฆโ€ฆยงรจยโ€“รฅยยฐ", + ["Seal of the Crusader"]="รฅยยรฅยญโ€”รจยปยรจยโ€“รฅยยฐ", +-- ["Seal of Vengeance"] = true, + ["Searing Light"]="รงยยผรงโ€ ยฑรคยนโ€นรฅโ€ฆโ€ฐ", + ["Searing Pain"]="รงยยผรงโ€ ยฑรคยนโ€นรงโ€”โ€บ", + ["Searing Totem"]="รงยยผรงโ€ ยฑรฅล“โ€“รฉยจยฐ", +-- ["Second Wind"] = true, + ["Seduction"]="รจยชหœรฆฦ’โ€˜", +-- ["Seed of Corruption"] = true, + ["Sense Demons"]="รฆโ€žลธรงลธยฅรฆฦ’ยกรฉยญโ€", + ["Sense Undead"]="รฆโ€žลธรงลธยฅรคยธยรฆยญยปรงโ€ลธรงโ€ฐยฉ", + ["Sentry Totem"]="รฅยดโ€”รฅโ€œยจรฅล“โ€“รฉยจยฐ", + ["Serpent Sting"]="รฆยฏโ€™รจโ€บโ€กรฉโ€กหœรฅห†ยบ", + ["Setup"]="รจยชยฟรฆโ€ขยด", + ["Shackle Undead"]="รฆยลธรงยธโ€บรคยธยรฆยญยปรงโ€ลธรงโ€ฐยฉ", + ["Shadow Affinity"]="รฆลกโ€”รฅยฝยฑรจยฆยชรฅโ€™ล’", + ["Shadow Bolt"]="รฆลกโ€”รฅยฝยฑรงยฎยญ", + ["Shadow Focus"]="รฆลกโ€”รฅยฝยฑรฉโ€บโ€ รคยธยญ", + ["Shadow Mastery"]="รฆลกโ€”รฅยฝยฑรฅยฐห†รงยฒยพ", + ["Shadow Protection"]="รฆลกโ€”รฅยฝยฑรฉหœยฒรจยญยท", + ["Shadow Reach"]="รฆลกโ€”รฅยฝยฑรฅยปยถรคยผยธ", + ["Shadow Resistance Aura"]="รฆลกโ€”รฅยฝยฑรฆล โ€”รฆโ‚ฌยงรฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Shadow Resistance"]="รฆลกโ€”รฅยฝยฑรฆล โ€”รฆโ‚ฌยง", + ["Shadow Trance"]="รฆลกโ€”รฅยฝยฑรฅโ€ ยฅรฆโ‚ฌย", + ["Shadow Vulnerability"] = "รฆลกโ€”รฅยฝยฑรฆหœโ€œรฅโ€šยท", + ["Shadow Ward"]="รฉหœยฒรจยญยทรฆลกโ€”รฅยฝยฑรงยตยรงโ€ขล’", + ["Shadow Weaving"]="รฆลกโ€”รฅยฝยฑรคยนโ€นรฆยณยข", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"]="รฆลกโ€”รจยจโ‚ฌรจยกโ€œรฏยผลกรงโ€”โ€บ", + ["Shadowburn"]="รฆลกโ€”รฅยฝยฑรงยยผรงโ€กโ€™", +-- ["Shadowfiend"] = true, + ["Shadowform"]="รฆลกโ€”รฅยฝยฑรฅยฝยขรฆโ€ฆโ€น", +-- ["Shadowfury"] = true, + ["Shadowguard"]="รฆลกโ€”รฅยฝยฑรฅยฎห†รจยกโ€บ", + ["Shadowmeld Passive"]="รฅยฝยฑรฉยย", + ["Shadowmeld"]="รฅยฝยฑรฉยย", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"]="รฉโ€นโ€™รฅห†ยฉรงยยธรงห†ยช", + ["Shatter"]="รงยขลฝรฅโ€ ยฐ", + ["Sheep"]="รงยพล ", + ["Shell Shield"]="รงโ€ยฒรฆยฎยผรจยญยทรงโ€บยพ", + ["Shield Bash"]="รงโ€บยพรฆโ€œล ", + ["Shield Bash - Silenced"] = "รงโ€บยพรฆโ€œล  - รฆยฒห†รฉยปหœ", + ["Shield Block"]="รงโ€บยพรงโ€ฐล’รฆย ยผรฆโ€œโ€น", + ["Shield Slam"]="รงโ€บยพรงโ€ฐล’รงล’โ€บรฆโ€œล ", + ["Shield Specialization"]="รงโ€บยพรงโ€ฐล’รฅยฐห†รงยฒยพ", + ["Shield Wall"]="รงโ€บยพรงโ€ฐโ€ ", + ["Shield"]="รงโ€บยพรงโ€ฐล’", + ["Shoot Bow"]="รฅยผโ€œรฅยฐโ€žรฆโ€œล ", + ["Shoot Crossbow"]="รฅยผยฉรฅยฐโ€žรฆโ€œล ", + ["Shoot Gun"]="รฆยงยรฆยขยฐรฅยฐโ€žรฆโ€œล ", + ["Shoot"]="รฅยฐโ€žรฆโ€œล ", + ["Shred"]="รฆโ€™โ€ขรงยขลฝ", + ["Silence"]="รฆยฒโ€ฐรฉยปหœ", +-- ["Silencing Shot"] = true, + ["Silent Resolve"]="รงโ€žยกรจยยฒรฆยถห†รฉโ‚ฌโ‚ฌ", + ["Sinister Strike"]="รฉโ€šยชรฆฦ’ยกรฆโ€ยปรฆโ€œล ", + ["Siphon Life"]="รงโ€ลธรฅโ€˜ยฝรจโ„ขยนรฅยยธ", + ["Skinning"]="รฅโ€ฐยรงลกยฎ", + ["Slam"]="รงล’โ€บรฆโ€œล ", + ["Sleep"]="รฅโ€šยฌรงล“ย รจยกโ€œ", + ["Slice and Dice"]="รฅห†โ€กรฅโ€ฐยฒ", +-- ["Slow"] = true, + ["Slow Fall"]="รงยทยฉรจยยฝรจยกโ€œ", + ["Smelting"]="รงโ€ โ€รงโ€ฆโ€ฐ", + ["Smite"]="รฆโ€กยฒรฆโ€œล ", +-- ["Snake Trap"] = true, + ["Solid Sharpening Stone"]="รฅย โ€ฆรฅโ€บยบรงลกโ€žรงยฃยจรฅห†โ‚ฌรงลธยณ", + ["Soothe Animal"]="รฅยฎโ€ฐรฆโ€™ยซรฅโ€นโ€ขรงโ€ฐยฉ", + ["Soothing Kiss"]="รฅยฎโ€ฐรฆโ€™ยซรคยนโ€นรฅยยป", + ["Soul Fire"]="รฉยห†รฉยญโ€šรคยนโ€นรงยยซ", + ["Soul Link"]="รฉยห†รฉยญโ€šรฉยห†รงยตย", + ["Soul Siphon"] = "รฉยห†รฉยญโ€šรจโ„ขยนรฅยยธ", +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"]="รฉยห†รฉยญโ€šรงลธยณรฅยพยฉรฆยดยป", + ["Spell Lock"]="รฆยณโ€ขรจยกโ€œรฅยฐยรฉลฝโ€“", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"]="รฆยณโ€ขรจยกโ€œรจยญยทรจยกโ€บ", + ["Spirit Bond"]="รฉยห†รฉยญโ€šรจยยฏรงยตย", + ["Spirit Tap"]="รงยฒยพรงยฅลพรฅห†โ€ รฆยตย", + ["Spirit of Redemption"]="รฆโ€ขโ€˜รจยดโ€“รคยนโ€นรฉยญโ€š", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"]="รงยฒยพรงยฅลพรฉโ€บโ€ รคยธยญ", + ["Spiritual Guidance"]="รงยฒยพรงยฅลพรฅยฐลฝรฅยผโ€ข", + ["Spiritual Healing"]="รงยฒยพรงยฅลพรฆยฒยปรงโ„ขโ€š", + ["Sprint"]="รงโ€“ยพรจยทโ€˜", +-- ["Stance Mastery"] = true, + ["Starfire"]="รฆหœลธรงยยซรจยกโ€œ", + ["Starfire Stun"] = "รฆหœลธรงยยซรฆหœยรจยฟยท", + ["Starshards"]="รฆหœลธรจยพยฐรงยขลฝรงโ€ฐโ€ก", + ["Staves"]="รฆยณโ€ขรฆยโ€“", +-- ["Steady Shot"] = true, + ["Stealth"]="รฆยฝโ€บรจยกล’", + ["Stoneclaw Totem"]="รงลธยณรงห†ยชรฅล“โ€“รฉยจยฐ", + ["Stoneform"]="รงลธยณรฅฦ’ยรฅยฝยขรฆโ€ฆโ€น", + ["Stoneskin Totem"]="รงลธยณรงโ€ยฒรฅล“โ€“รฉยจยฐ", + ["Stormstrike"]="รฉยขยจรฆลกยดรฆโ€ฐโ€œรฆโ€œล ", + ["Strength of Earth Totem"]="รฅยคยงรฅล“ยฐรคยนโ€นรฅล โ€บรฅล“โ€“รฉยจยฐ", + ["Stuck"]="รฅยยกรฆยญยป", + ["Subtlety"]="รฅยพยฎรฅยฆโ„ข", + ["Suffering"]="รฅยโ€”รฉโ€บยฃ", + ["Summon Charger"]="รฅยยฌรฅโ€“ลกรฆห†ยฐรฉยฆยฌ", + ["Summon Dreadsteed"]="รฅยยฌรฅโ€“ลกรฆยยรฆโ€กยผรฆห†ยฐรฉยฆยฌ", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"]="รฅยยฌรฅโ€“ลกรฅล“ยฐรงยโ€žรงยยตรงล ยฌ", + ["Summon Felsteed"]="รฅยยฌรฅโ€“ลกรฅล“ยฐรงยโ€žรฆห†ยฐรฉยฆยฌ", + ["Summon Imp"]="รฅยยฌรฅโ€“ลกรฅยฐยรฉยฌยผ", + ["Summon Succubus"]="รฅยยฌรฅโ€“ลกรฉยญโ€ฆรฉยญโ€", + ["Summon Voidwalker"]="รฅยยฌรฅโ€“ลกรจโ„ขโ€บรงยฉยบรจยกล’รจโ‚ฌโ€ฆ", + ["Summon Warhorse"]="รฅยยฌรฅโ€“ลกรฆห†ยฐรฉยฆยฌ", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"]="รงย ยดรงโ€ยฒรฆโ€ยปรฆโ€œล ", + ["Suppression"]="รฉลฝยฎรฅยฃโ€œ", + ["Surefooted"]="รงยฉยฉรฅโ€บยบ", + ["Survivalist"]="รงโ€ลธรฅยญหœรฆล โ‚ฌรจฦ’ยฝรฅยฐห†รฅยฎยถ", + ["Sweeping Strikes"]="รฆยฉยซรฆลฝฦ’รฆโ€ยปรฆโ€œล ", + ["Swiftmend"] = "รจยฟโ€ฆรฆยยทรฆยฒยปรฆโ€žห†", + ["Swipe"]="รฆยยฎรฆโ€œล ", + ["Sword Specialization"]="รฅล ยรฉยกลพรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Tactical Mastery"]="รฆห†ยฐรจยกโ€œรฅยฐห†รงยฒยพ", + ["Tainted Blood"]="รจโ€ฆยรฅยฃลพรคยนโ€นรจยกโ‚ฌ", + ["Tailoring"]="รจยฃยรงยธยซ", + ["Tame Beast"]="รฉยฆยดรฆล“ยรฉโ€กลฝรงยยธ", + ["Tamed Pet Passive"]="รฉยฆยดรฆล“ยรฉโ€กลฝรงยยธรฏยผห†รจยขยซรฅโ€นโ€ขรฏยผโ€ฐ", + ["Taunt"]="รฅหœยฒรจยซยท", + ["Teleport: Darnassus"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฉยโ€รงยดยรจหœโ€กรฆโ€“ยฏ", + ["Teleport: Ironforge"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฉยยตรงห†ยรฅย ยก", + ["Teleport: Moonglade"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฆล“ห†รฅโ€ฆโ€ฐรฆลพโ€”รฅล“ยฐ", + ["Teleport: Orgrimmar"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฅยฅยงรฆย ยผรงโ€˜ยช", + ["Teleport: Stormwind"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฆลกยดรฉยขยจรฅลธลฝ", + ["Teleport: Thunder Bluff"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฉโ€บยทรฉล“โ€ รฅยดโ€“", + ["Teleport: Undercity"]="รฅโ€šยณรฉโ‚ฌยรฏยผลกรฅยนยฝรฆลกโ€”รฅลธลฝ", +-- ["The Beast Within"] = true, + ["The Human Spirit"]="รคยบยบรฉยกลพรงยฒยพรฉยญโ€š", + ["Thick Hide"]="รฅลฝลกรงลกยฎ", + ["Thorns"]="รจยล รฆยฃหœรจยกโ€œ", + ["Throw"]="รฆล โ€ขรฆโ€œยฒ", + ["Throwing Specialization"]="รฆล โ€ขรฆโ€œยฒรฅยฐห†รงยฒยพ", + ["Throwing Weapon Specialization"]="รฆล โ€ขรฆโ€œยฒรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Thrown"]="รฆล โ€ขรฆโ€œยฒ", + ["Thunder Clap"]="รฉโ€บยทรฉล“โ€ รคยธโ‚ฌรฆโ€œล ", + ["Thundering Strikes"]="รฉโ€บยทรฉยณยดรงล’โ€บรฆโ€œล ", + ["Thunderstomp"]="รฉโ€บยทรฉล“โ€ รจยธยรจยธย", + ["Tidal Focus"]="รฆยฝยฎรฆยฑยรฉโ€บโ€ รคยธยญ", + ["Tidal Mastery"]="รฆยฝยฎรฆยฑยรฅยฐห†รงยฒยพ", + ["Tiger Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรจยฑยน", + ["Tiger's Fury"]="รงล’โ€บรจโ„ขลฝรคยนโ€นรฆโ‚ฌโ€™", + ["Torment"]="รฆล หœรงยฃยจ", + ["Totem"]="รฅล“โ€“รฉยจยฐ", + -- ["Totem of Wrath"] = true, + ["Totemic Focus"]="รฅล“โ€“รฉยจยฐรฉโ€บโ€ รคยธยญ", + ["Touch of Weakness"]="รจโ„ขโ€บรฅยผยฑรคยนโ€นรจยงยธ", + ["Toughness"]="รฅย โ€ฆรฉลธล’", + ["Track Beasts"]="รจยฟยฝรจยนยครฉโ€กลฝรงยยธ", + ["Track Demons"]="รจยฟยฝรจยนยครฆฦ’ยกรฉยญโ€", + ["Track Dragonkin"]="รจยฟยฝรจยนยครฉยพยรฉยกลพ", + ["Track Elementals"]="รจยฟยฝรจยนยครฅโ€ฆฦ’รงยดย รงโ€ลธรงโ€ฐยฉ", + ["Track Giants"]="รจยฟยฝรจยนยครฅยทยจรคยบยบ", + ["Track Hidden"]="รจยฟยฝรจยนยครฉลกยฑรจโ€”ยรงโ€ลธรงโ€ฐยฉ", + ["Track Humanoids"]="รจยฟยฝรจยนยครคยบยบรฅลพโ€นรงโ€ลธรงโ€ฐยฉ", + ["Track Undead"]="รจยฟยฝรจยนยครคยบยกรฉยห†", + ["Tranquil Air Totem"]="รฅยฏยงรฉยล“รคยนโ€นรฉยขยจรฅล“โ€“รฉยจยฐ", + ["Tranquil Spirit"]="รฅยฏยงรฉยล“รคยนโ€นรฉยญโ€š", + ["Tranquility"]="รฅยฏยงรฉยล“", + ["Tranquilizing Shot"]="รฅยฏยงรงยฅลพรฅยฐโ€žรฆโ€œล ", + ["Trap Mastery"]="รฉโ„ขยทรฉหœยฑรฆลฝล’รฆยยก", + ["Travel Form"]="รฆโ€”โ€ฆรจยกล’รฅยฝยขรฆโ€ฆโ€น", +-- ["Tree of Life"] = true, + ["Tremor Totem"]="รฆห†ยฐรฆโ€ฆโ€žรฅล“โ€“รฉยจยฐ", + ["Tribal Leatherworking"]="รฉฦ’ยจรฆโ€”ยรจยฃยฝรงลกยฎ", + ["Trueshot Aura"]="รฅยผยทรฆโ€œล รฅโ€ฆโ€ฐรงโ€™ยฐ", + ["Turn Undead"]="รจยถโ€ฆรฆยธยกรคยธยรฆยญยปรงโ€ลธรงโ€ฐยฉ", + ["Two-Handed Axes and Maces"]="รฉโ€บโ„ขรฆโ€ฐโ€นรฆโ€“ยงรฅโ€™ล’รฉล’หœ", + ["Two-Handed Axes"]="รฉโ€บโ„ขรฆโ€ฐโ€นรฆโ€“ยง", + ["Two-Handed Maces"]="รฉโ€บโ„ขรฆโ€ฐโ€นรฉล’หœ", + ["Two-Handed Swords"]="รฉโ€บโ„ขรฆโ€ฐโ€นรฅล ย", + ["Two-Handed Weapon Specialization"]="รฉโ€บโ„ขรฆโ€ฐโ€นรฆยญยฆรฅโ„ขยจรฅยฐห†รงยฒยพ", + ["Unarmed"]="รฅยพโ€™รฆโ€ฐโ€น", + ["Unbreakable Will"]="รฅย โ€ฆรฅยฎลกรฆโ€žยรฅยฟโ€”", + ["Unbridled Wrath Effect"]="รฆโ‚ฌโ€™รคยธยรฅยยฏรฉยย", + ["Unbridled Wrath"]="รฆโ‚ฌโ€™รคยธยรฅยยฏรฉยย", + ["Undead Horsemanship"]="รฉยจลฝรจยกโ€œรฏยผลกรฉยชยธรฉยชยจรฆห†ยฐรฉยฆยฌ", + ["Underwater Breathing"]="รฆยฐยดรคยธโ€นรฅโ€˜ยผรฅยยธ", + ["Unending Breath"]="รฉยญโ€รฆยยฏรจยกโ€œ", + ["Unholy Power"]="รฉโ€šยชรฆฦ’ยกรฅยผยทรฅล’โ€“", + ["Unleashed Fury"]="รงโ€นโ€šรฆโ‚ฌโ€™รฉโ€กโ€นรฆโ€ยพ", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"]="รคยธยรฆยปโ€ฆรคยฟยกรคยปยฐ", + ["Vampiric Embrace"]="รฅยยธรจยกโ‚ฌรฉยฌยผรงลกโ€žรฆโ€œยรฆล ยฑ", + ["Vanish"]="รฆยถห†รฅยคยฑ", + ["Vanished"]="รฆยถห†รฅยคยฑ", +-- ["Vampiric Touch"] = true, + ["Vengeance"]="รฅยพยฉรคยปโ€ก", +-- ["Victory Rush"] = true, + ["Vigor"]="รงยฒยพรฅล โ€บ", + ["Vile Poisons"]="รฆฦ’ยกรฆโ‚ฌยงรฆยฏโ€™รจโ€”ยฅ", + ["Vindication"]="รจยพยฏรจยญยท", + ["Viper Sting"]="รจยยฎรจโ€บโ€กรฉโ€กหœรฅห†ยบ", + ["Volley"]="รคยบโ€šรฅยฐโ€ž", + ["Wand Specialization"]="รฉยญโ€รฆยโ€“รฅยฐห†รงยฒยพ", + ["Wands"]="รฉยญโ€รฆยโ€“", + ["War Stomp"]="รฆห†ยฐรงห†ยญรจยธยรจยธย", + ["Water Breathing"]="รฆยฐยดรคยธโ€นรฅโ€˜ยผรฅยยธ", +-- ["Water Shield"] = true, + ["Water Walking"]="รฆยฐยดรคยธล รจยกล’รจยตยฐ", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "รจโ„ขโ€บรฅยผยฑรฉยห†รฉยญโ€š", + ["Weaponsmith"]="รฆยญยฆรฅโ„ขยจรฉโ€˜โ€žรฉโ‚ฌย ", + ["Whirlwind"]="รฆโ€”โ€นรฉยขยจรฆโ€“ยฌ", + ["Will of the Forsaken"]="รคยบยกรฉยห†รฆโ€žยรฅยฟโ€”", + ["Windfury Totem"]="รฉยขยจรฆโ‚ฌโ€™รฅล“โ€“รฉยจยฐ", + ["Windfury Weapon"]="รฉยขยจรฆโ‚ฌโ€™รฆยญยฆรฅโ„ขยจ", + ["Windwall Totem"]="รฉยขยจรงโ€ฐโ€ รฅล“โ€“รฉยจยฐ", + ["Wing Clip"]="รฆโ€˜โ€รงยตโ€ ", + ["Winter's Chill"]="รฆยทยฑรฅโ€ ยฌรคยนโ€นรฅยฏโ€™", + ["Wisp Spirit"]="รงยฒยพรฉยห†รคยนโ€นรฉยญโ€š", + ["Wolf Riding"]="รฉยจลฝรจยกโ€œรฏยผลกรงโ€นยผ", + ["Wound Poison II"]="รจโ€กยดรฅโ€šยทรฆยฏโ€™รจโ€”ยฅ II", + ["Wound Poison III"]="รจโ€กยดรฅโ€šยทรฆยฏโ€™รจโ€”ยฅ III", + ["Wound Poison IV"]="รจโ€กยดรฅโ€šยทรฆยฏโ€™รจโ€”ยฅ IV", + ["Wound Poison"]="รจโ€กยดรฅโ€šยทรฆยฏโ€™รจโ€”ยฅ", + ["Wrath"]="รฆโ€ ยครฆโ‚ฌโ€™", + -- ["Wrath of Air Totem"] = true, + ["Wyvern Sting"]="รงยฟยผรฉยพยรฉโ€กหœรฅห†ยบ", + } +end) + +BabbleSpell:RegisterTranslations("koKR", function() + return { + ["Abolish Disease"] = "รฌยงห†รซยณโ€˜ รญโ€ขยดรฌย ล“", + ["Abolish Poison Effect"] = "รซยโ€ฆ รญโ€ขยดรฌย ล“ รญลกยจรชยณยผ", + ["Abolish Poison"] = "รซยโ€ฆ รญโ€ขยดรฌย ล“", + ["Activate MG Turret"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Adrenaline Rush"] = "รฌโ€ขโ€žรซโ€œล“รซย ห†รซโ€šย รซยฆยฐ รฌยดโ€ฐรฌยงโ€ž", + ["Aftermath"] = "รฌลพยฌรฌโ€ขโ„ขรฌยหœ รฌโ€”ยฌรญล’ล’", + ["Aggression"] = "รชยณยตรชยฒยฉรฌโ€žยฑ", + ["Aimed Shot"] = "รฌยกยฐรฌยคโ‚ฌ รฌโ€šยฌรชยฒยฉ", + ["Alchemy"] = "รฌโ€”ยฐรชยธห†รฌห†ย ", + ["Ambush"] = "รซยงยครซยณยต", + ["Amplify Curse"] = "รฌย โ‚ฌรฌยฃยผ รฌยฆยรญยยญ", + ["Amplify Magic"] = "รซยงห†รซยฒโ€ข รฌยฆยรญยยญ", + ["Ancestral Fortitude"] = "รฌโ€žย รฌยยธรฌยหœ รฌยยธรซโ€šยด", + ["Ancestral Healing"] = "รฌโ€žย รฌยยธรฌยหœ รฌยนหœรฌล“ย รซย ยฅ", + ["Ancestral Knowledge"] = "รฌโ€žย รฌยยธรฌยหœ รฌยงโ‚ฌรญหœล“", + ["Ancestral Spirit"] = "รชยณย รซล’โ‚ฌรฌยหœ รฌหœยรญหœยผ", +-- ["Anesthetic Poison"] = true, + ["Anger Management"] = "รซยถโ€žรซโ€ฆยธ รฌย ล“รฌโ€“ยด", + ["Anticipation"] = "รฌยงยรชยฐย", + ["Aquatic Form"] = "รซยฐโ€รซโ€นยครญโ€˜ล“รซยฒโ€ รซยณโ‚ฌรฌโ€นย ", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌยดยรซยชโ€ฆรญโ€ขยจ", + ["Arcane Concentration"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌย โ€ขรฌโ€นย รฌยงโ€˜รฌยคโ€˜", + ["Arcane Explosion"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รญยยญรซยฐล“", + ["Arcane Focus"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌยงโ€˜รฌยคโ€˜", + ["Arcane Instability"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รซยถห†รฌโ€ขห†รฌย โ€ขรฌโ€žยฑ", + ["Arcane Intellect"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌยงโ‚ฌรซล ยฅ", + ["Arcane Meditation"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รซยชโ€ฆรฌฦ’ย", + ["Arcane Mind"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌย โ€ขรฌโ€นย ", + ["Arcane Missiles"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รญโ„ขโ€รฌโ€šยด", + ["Arcane Power"] = "รฌโ€นย รซยนโ€žรฌยหœ รซยงห†รซยฒโ€ข รชยฐโ€ขรญโ„ขโ€", + ["Arcane Resistance"] = "รซยนโ€žรฌย โ€ž รฌย โ‚ฌรญโ€ขยญรซย ยฅ", + ["Arcane Shot"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌโ€šยฌรชยฒยฉ", + ["Arcane Subtlety"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รซยฏยธรซยฌหœรญโ€ขยจ", + ["Arctic Reach"] = "รญหœยนรญโ€ขล“รฌยหœ รฌโ€ ยรชยธยธ", + ["Armorsmith"] = "รซยฐยฉรฌโ€“ยดรชยตยฌรฌย ล“รฌลพโ€˜", + ["Aspect of the Beast"] = "รฌโ€ขยผรฌห†หœรฌยหœ รฌฦ’ย", + ["Aspect of the Cheetah"] = "รฌยนหœรญฦ’โ‚ฌรฌยหœ รฌฦ’ย", + ["Aspect of the Hawk"] = "รซยงยครฌยหœ รฌฦ’ย", + ["Aspect of the Monkey"] = "รฌโ€บยรฌห†ยญรฌยยดรฌยหœ รฌฦ’ย", + ["Aspect of the Pack"] = "รฌยนหœรญฦ’โ‚ฌ รซยฌยดรซยฆยฌรฌยหœ รฌฦ’ย", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌฦ’ย", + ["Astral Recall"] = "รฌหœยรญหœยผรฌยหœ รชยทโ‚ฌรญโ„ขหœ", + ["Attack"] = "รชยณยตรชยฒยฉ", + ["Attacking"] = "รญล’ล’รชยดยด รฌยคโ€˜", + ["Auto Shot"] = "รฌลพยรซยโ„ข รฌโ€šยฌรชยฒยฉ", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"] = "รซยโ€žรซยยผรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", +-- ["Backlash"] = true, + ["Backstab"] = "รชยธยฐรฌล ยต", + ["Bane"] = "รญล’ล’รซยฉยธ", + ["Banish"] = "รฌยถโ€รซยฐยฉ", + ["Barkskin Effect"] = "รซโ€šหœรซยฌยด รชยปยรฌยงห† รญลกยจรชยณยผ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Barkskin"] = "รซโ€šหœรซยฌยด รชยปยรฌยงห†", + ["Barrage"] = "รญฦ’โ€žรซยงโ€ฐ", + ["Bash"] = "รชยฐโ€ขรญฦ’โ‚ฌ", + ["Basic Campfire"] = "รฌลพโ€˜รฌยโ‚ฌ รซยชยจรซโ€นยฅรซยถห†", + ["Battle Shout"] = "รฌย โ€žรญห†ยฌรฌยหœ รฌโ„ขยธรฌยนยจ", + ["Battle Stance Passive"] = "รฌย โ€žรญห†ยฌ รญฦ’ล“รฌโ€žยธ", + ["Battle Stance"] = "รฌย โ€žรญห†ยฌ รญฦ’ล“รฌโ€žยธ", + ["Bear Form"] = "รชยณยฐ รซยณโ‚ฌรฌโ€นย ", + ["Beast Lore"] = "รฌโ€ขยผรฌห†หœ รฌโ€”ยฐรชยตยฌ", + ["Beast Slaying"] = "รฌโ€ขยผรฌห†หœ รฌโ€šยฌรซฦ’ยฅ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Beast Training"] = "รฌโ€ขยผรฌห†หœ รฌยกยฐรซย ยจ", + ["Benediction"] = "รฌยถโ€ขรซยณยตรฌยหœ รชยธยฐรซยโ€ž", + ["Berserker Rage"] = "รชยดโ€˜รฌย โ€žรฌโ€šยฌรฌยหœ รชยฒยฉรซโ€ฆยธ", + ["Berserker Stance Passive"] = "รชยดโ€˜รญยยญ รญฦ’ล“รฌโ€žยธ รฌยงโ‚ฌรฌโ€ ยรญลกยจรชยณยผ", + ["Berserker Stance"] = "รชยดโ€˜รญยยญ รญฦ’ล“รฌโ€žยธ", + ["Berserking"] = "รชยดโ€˜รญยยญรญโ„ขโ€", + ["Bestial Discipline"] = "รฌโ€ขยผรฌห†หœ รญโ€บห†รซย ยจ", + ["Bestial Swiftness"] = "รฌโ€ขยผรฌห†หœรฌยหœ รฌโ€นย รฌโ€ ยรญโ€ขยจ", + ["Bestial Wrath"] = "รฌโ€ขยผรฌห†หœรฌยหœ รชยฒยฉรซโ€ฆยธ", +-- ["Binding Heal"] = true, + ["Bite"] = "รซยฌยผรชยธยฐ", + ["Black Arrow"] = "รชยฒโ‚ฌรฌยโ‚ฌ รญโ„ขโ€รฌโ€šยด", + ["Blackout"] = "รฌยหœรฌโ€นย รฌฦ’ยรฌโ€นยค", + ["Blacksmithing"] = "รซล’โ‚ฌรฌลพยฅรชยธยฐรฌห†ย ", + ["Blade Flurry"] = "รญยยญรญโ€™ยรฌยหœ รฌยนยผรซโ€šย ", + ["Blast Wave"] = "รญโ„ขโ€รฌโ€”ยผ รญยยญรญโ€™ย", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"] = "รฌยถโ€ขรซยณยตรซยฐโ€บรฌยโ‚ฌ รญลกล’รซยณยตรซย ยฅ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Blessing of Freedom"] = "รฌลพยรฌล“ย รฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Kings"] = "รฌโ„ขโ€ขรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Light"] = "รซยนโ€บรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Might"] = "รญลพหœรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Protection"] = "รซยณยดรญหœยธรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Sacrifice"] = "รญยยฌรฌฦ’ยรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Salvation"] = "รชยตยฌรฌโ€บยรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Sanctuary"] = "รฌโ€žยฑรฌโ€”ยญรฌยหœ รฌยถโ€ขรซยณยต", + ["Blessing of Wisdom"] = "รฌยงโ‚ฌรญหœล“รฌยหœ รฌยถโ€ขรซยณยต", + ["Blind"] = "รฌโ€นยครซยชโ€ฆ", + ["Blinding Powder"] = "รฌโ€นยครซยชโ€ฆ รชยฐโ‚ฌรซยฃยจ", + ["Blink"] = "รฌย ยรซยฉยธ", + ["Blizzard"] = "รซห†ห†รซยณยดรซยยผ", + ["Block"] = "รซยฐยฉรฌโ€“ยด", + ["Blood Craze"] = "รญโ€ยผรฌยหœ รชยดโ€˜รชยธยฐ", + ["Blood Frenzy"] = "รญโ€ยผรฌยหœ รชยดโ€˜รชยธยฐ", + ["Blood Fury"] = "รญโ€ยผรฌยหœ รชยฒยฉรซโ€ฆยธ", + ["Blood Pact"] = "รญโ€ยผรฌยหœ รฌโ€žล“รฌโ€ขยฝ", +-- ["Bloodlust"] = true, + ["Bloodrage"] = "รญโ€ยผรฌยหœ รซยถโ€žรซโ€ฆยธ", + ["Bloodthirst"] = "รญโ€ยผรฌยหœ รชยฐห†รฌยฆย", + ["Booming Voice"] = "รฌลกยฐรซย ยรฌยฐยฌ รฌยล’รฌโ€žยฑ", + ["Bow Specialization"] = "รญโ„ขล“รซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Bows"] = "รญโ„ขล“", + ["Bright Campfire"] = "รซยฐยรฌยโ‚ฌ รซยชยจรซโ€นยฅรซยถห†", + ["Brutal Impact"] = "รฌโ€ขยผรฌห†หœรฌยหœ รฌล ยตรชยฒยฉ", + ["Burning Soul"] = "รซยถห†รญฦ’โ‚ฌรซล โ€ รฌหœยรญหœยผ", + ["Call Pet"] = "รฌโ€ขยผรฌห†หœ รซยถโ‚ฌรซยฅยดรชยธยฐ", + ["Call of Flame"] = "รซยถห†รชยฝฦ’รฌยหœ รซยถโ‚ฌรซยฆโ€ž", + ["Call of Thunder"] = "รฌยฒล“รซโ€˜ยฅรฌยหœ รซยถโ‚ฌรซยฆโ€ž", + ["Camouflage"] = "รฌล“โ€žรฌลพยฅรฌห†ย ", + ["Cannibalize"] = "รฌโ€นล“รฌยฒยดรซยจยนรชยธยฐ", + ["Cat Form"] = "รญโ€˜ล“รซยฒโ€ รซยณโ‚ฌรฌโ€นย ", + ["Cataclysm"] = "รฌลพยฌรฌโ€ขโ„ข", + ["Chain Heal"] = "รฌโ€”ยฐรฌโ€กโ€ž รฌยนหœรฌล“ย ", + ["Chain Lightning"] = "รฌโ€”ยฐรฌโ€กโ€ž รซยฒห†รชยฐล“", + ["Challenging Roar"] = "รซยโ€žรฌย โ€žรฌยหœ รญยยฌรญลกยจ", + ["Challenging Shout"] = "รซยโ€žรฌย โ€žรฌยหœ รฌโ„ขยธรฌยนยจ", + ["Charge Rage Bonus Effect"] = "รซยณยดรซโ€žห†รฌล ยค รซยถโ€žรซโ€ฆยธ รฌยถยฉรฌย โ€ž รญลกยจรชยณยผ", + ["Charge"] = "รซยล’รฌยงโ€ž", + ["Charge Stun"] = "รซยล’รฌยงโ€ž รชยธยฐรฌย ห†", + ["Cheap Shot"] = "รซยนโ€žรฌโ€”ยดรญโ€ขล“ รฌล ยตรชยฒยฉ", + ["Chilled"] = "รซยนโ„ขรชยฒยฐ", +-- ["Circle of Healing"] = true, + ["Claw"] = "รญโ€ขย รญโ‚ฌยดรชยธยฐ", + ["Cleanse"] = "รฌย โ€ขรญโ„ขโ€", + ["Clearcasting"] = "รฌย โ€ขรฌโ€นย  รฌยงโ€˜รฌยคโ€˜", + ["Cleave"] = "รญลกล’รฌย โ€žรซยฒย รชยธยฐ", + ["Clever Traps"] = "รซยยซ รชยฐล“รซลธโ€ฐ", +-- ["Cloak of Shadows"] = true, + ["Closing"] = "รซโ€นยซรซล โ€ รฌยคโ€˜", + ["Cloth"] = "รฌยฒล“", + ["Coarse Sharpening Stone"] = "รฌยยผรซยฐหœ รฌห†ยซรซยล’", + ["Cobra Reflexes"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Cold Blood"] = "รซฦ’โ€ฐรญหœห†", + ["Cold Snap"] = "รซยงยครฌโ€žล“รฌลกยด รญโ€ขล“รญล’ล’", + ["Combat Endurance"] = "รฌย โ€žรญห†ยฌ รฌยงโ‚ฌรชยตยฌรซย ยฅ", + ["Combustion"] = "รซยฐล“รญโ„ขโ€", + ["Command"] = "รฌยงโ‚ฌรซยฐยฐ", +-- ["Commanding Shout"] = true, + ["Concentration Aura"] = "รฌยงโ€˜รฌยคโ€˜รฌยหœ รฌหœยครซยยผ", + ["Concussion Blow"] = "รฌยถยฉรชยฒยฉรฌยหœ รฌยยผรชยฒยฉ", + ["Concussion"] = "รฌยดโ€ฐรซยฐล“", + ["Concussive Shot"] = "รฌยถยฉรชยฒยฉรญยยฌ", + ["Cone of Cold"] = "รซฦ’โ€ฐรชยธยฐ รซยล’รญโ€™ย", + ["Conflagrate"] = "รฌย ยรญโ„ขโ€", + ["Conjure Food"] = "รฌยล’รฌโ€นย รฌยฐยฝรฌยกยฐ", + ["Conjure Mana Agate"] = "รซยงห†รซโ€šหœ รซยงห†รซโ€ฆยธ รฌยฐยฝรฌยกยฐ", + ["Conjure Mana Citrine"] = "รซยงห†รซโ€šหœ รญโ„ขยฉรฌห†หœรฌย โ€ข รฌยฐยฝรฌยกยฐ", + ["Conjure Mana Jade"] = "รซยงห†รซโ€šหœ รซยนโ€žรฌยทยจ รฌยฐยฝรฌยกยฐ", + ["Conjure Mana Ruby"] = "รซยงห†รซโ€šหœ รซยฃยจรซยนโ€ž รฌยฐยฝรฌยกยฐ", + ["Conjure Water"] = "รฌยล’รซยฃล’ รฌยฐยฝรฌยกยฐ", + ["Consecrated Sharpening Stone"] = "รฌโ€นย รฌโ€žยฑรญโ€ขล“ รฌห†ยซรซยล’", + ["Consecration"] = "รฌโ€นย รฌโ€žยฑรญโ„ขโ€", +-- ["Consume Magic"] = true, + ["Consume Shadows"] = "รฌโ€“ยดรซโ€˜ย  รญยยกรฌห†หœ", + ["Convection"] = "รชยธยฐรฌยหœ รญยยรซยฆโ€ž", + ["Conviction"] = "รฌลพยรชยฐย", + ["Cooking"] = "รฌลกโ€รซยฆยฌ", + ["Corruption"] = "รซยถโ‚ฌรญล’ยจ", + ["Counterattack"] = "รฌโ€”ยญรฌล ยต", + ["Counterspell"] = "รซยงห†รซยฒโ€ข รฌยฐยจรซโ€นยจ", + ["Counterspell - Silenced"] = "รซยงห†รซยฒโ€ข รฌยฐยจรซโ€นยจ - รฌยนยจรซยฌยต", + ["Cower"] = "รฌโ€บโ€ฆรญยยฌรซยฆยฌรชยธยฐ", + ["Create Firestone"] = "รญโ„ขโ€รฌโ€”ยผรฌโ€žย รฌยฐยฝรฌยกยฐ", + ["Create Firestone (Major)"] = "รญโ„ขโ€รฌโ€”ยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รฌฦ’ยรชยธโ€ฐ)", + ["Create Firestone (Greater)"] = "รญโ„ขโ€รฌโ€”ยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌฦ’ยรชยธโ€ฐ)", + ["Create Firestone (Lesser)"] = "รญโ„ขโ€รฌโ€”ยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รญโ€ขหœรชยธโ€ฐ)", + ["Create Healthstone"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌยฐยฝรฌยกยฐ", + ["Create Healthstone (Major)"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รฌฦ’ยรชยธโ€ฐ)", + ["Create Healthstone (Greater)"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌฦ’ยรชยธโ€ฐ)", + ["Create Healthstone (Lesser)"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌยฐยฝรฌยกยฐ (รญโ€ขหœรชยธโ€ฐ)", + ["Create Healthstone (Minor)"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รญโ€ขหœรชยธโ€ฐ)", + ["Create Soulstone"] = "รฌหœยรญหœยผรฌโ€žย รฌยฐยฝรฌยกยฐ", + ["Create Soulstone (Major)"] = "รฌหœยรญหœยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รฌฦ’ยรชยธโ€ฐ)", + ["Create Soulstone (Greater)"] = "รฌหœยรญหœยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌฦ’ยรชยธโ€ฐ)", + ["Create Soulstone (Lesser)"] = "รฌหœยรญหœยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รญโ€ขหœรชยธโ€ฐ)", + ["Create Soulstone (Minor)"] = "รฌหœยรญหœยผรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รญโ€ขหœรชยธโ€ฐ)", + ["Create Spellstone"] = "รฌยฃยผรซยฌยธรฌโ€žย รฌยฐยฝรฌยกยฐ", + ["Create Spellstone (Major)"] = "รฌยฃยผรซยฌยธรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌยตล“รฌฦ’ยรชยธโ€ฐ)", + ["Create Spellstone (Greater)"] = "รฌยฃยผรซยฌยธรฌโ€žย รฌยฐยฝรฌยกยฐ (รฌฦ’ยรชยธโ€ฐ)", + ["Crippling Poison II"] = "รฌโ€นย รชยฒยฝ รซยงห†รซยนโ€ž รซยโ€ฆ II", + ["Crippling Poison"] = "รฌโ€นย รชยฒยฝ รซยงห†รซยนโ€ž รซยโ€ฆ", + ["Critical Mass"] = "รญโ„ขโ€รฌโ€”ยผ รชยฒยฐรฌยงโ€˜", + ["Crossbows"] = "รฌโ€žยรชยถย", + ["Cruelty"] = "รซยฌยดรฌลพยรซยนโ€žรญโ€ขยจ", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"] = "รฌลพยฌรซยฐยฐ", + ["Cure Disease"] = "รฌยงห†รซยณโ€˜ รฌยนหœรซยฃล’", + ["Cure Poison"] = "รญโ€ขยดรซยโ€ฆ", + ["Curse of Agony"] = "รชยณย รญโ€ ยตรฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Doom Effect"] = "รญล’ล’รซยฉยธรฌยหœ รฌย โ‚ฌรฌยฃยผ รญลกยจรชยณยผ", + ["Curse of Doom"] = "รญล’ล’รซยฉยธรฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Exhaustion"] = "รญโ€ยผรซยกล“รฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Idiocy"] = "รซยฌยดรฌยงโ‚ฌรฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Recklessness"] = "รซยฌยดรซยชยจรญโ€ขยจรฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Shadow"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Tongues"] = "รฌโ€“ยธรฌโ€“ยดรฌยหœ รฌย โ‚ฌรฌยฃยผ", + ["Curse of Weakness"] = "รซยฌยดรซย ยฅรญโ„ขโ€ รฌย โ‚ฌรฌยฃยผ", + ["Curse of the Elements"] = "รฌโ€บยรฌโ€ ล’รฌยหœ รฌย โ‚ฌรฌยฃยผ", +-- ["Cyclone"] = true, + ["Dagger Specialization"] = "รซโ€นยจรชยฒโ‚ฌรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Daggers"] = "รซโ€นยจรชยฒโ‚ฌ", + ["Dampen Magic"] = "รซยงห†รซยฒโ€ข รชยฐยรฌโ€กย ", + ["Dark Pact"] = "รฌโ€ขโ€รญยโ€˜รฌยหœ รชยณโ€žรฌโ€ขยฝ", + ["Darkness"] = "รฌโ€“ยดรซโ€˜ย ", + ["Dash"] = "รฌยงห†รฌยฃยผ", + ["Deadly Poison II"] = "รซยงยนรซยโ€ฆ II", + ["Deadly Poison III"] = "รซยงยนรซยโ€ฆ III", + ["Deadly Poison IV"] = "รซยงยนรซยโ€ฆ IV", + ["Deadly Poison V"] = "รซยงยนรซยโ€ฆ V", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Deadly Poison"] = "รซยงยนรซยโ€ฆ", +-- ["Deadly Throw"] = true, + ["Death Coil"] = "รฌยฃยฝรฌยล’รฌยหœ รชยณย รซยฆยฌ", + ["Death Wish"] = "รฌยฃยฝรฌยล’รฌยหœ รฌโ€ ล’รฌโ€บย", + ["Deep Wounds"] = "รฌยนหœรซยชโ€ฆรฌฦ’ย", + ["Defense"] = "รซยฐยฉรฌโ€“ยด", + ["Defensive Stance Passive"] = "รซยฐยฉรฌโ€“ยด รญฦ’ล“รฌโ€žยธ รฌยงโ‚ฌรฌโ€ ยรญลกยจรชยณยผ", + ["Defensive Stance"] = "รซยฐยฉรฌโ€“ยด รญฦ’ล“รฌโ€žยธ", + ["Defensive State 2"] = "รซยฐยฉรฌโ€“ยด รฌฦ’ยรญฦ’ล“ 2", + ["Defensive State"] = "รซยฐยฉรฌโ€“ยด รฌฦ’ยรญฦ’ล“", + ["Defiance"] = "รซยโ€žรฌย โ€ž", + ["Deflection"] = "รฌลพยฌรซยนย รซยฅยธ รฌโ€ ยรซโ€ โ‚ฌรซยฆยผ", + ["Demon Armor"] = "รฌโ€ขโ€ฆรซยงห†รฌยหœ รชยฐโ€˜รฌหœยท", + ["Demon Skin"] = "รฌโ€ขโ€ฆรซยงห†รฌยหœ รญโ€ยผรซยถโ‚ฌ", + ["Demonic Embrace"] = "รฌโ€ขโ€ฆรซยงห†รฌยหœ รฌยโ‚ฌรฌยดย", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = "รฌโ€ขโ€ฆรฌยหœ รฌย ล“รซยฌยผ", + ["Demoralizing Roar"] = "รฌล“โ€žรญหœโ€˜รฌยหœ รญยยฌรญลกยจ", + ["Demoralizing Shout"] = "รฌโ€šยฌรชยธยฐรฌยหœ รฌโ„ขยธรฌยนยจ", + ["Dense Sharpening Stone"] = "รชยฐโ€ขรซยโ€ž รซโ€ โ€™รฌยโ‚ฌ รฌห†ยซรซยล’", + ["Desperate Prayer"] = "รชยตยฌรฌโ€บยรฌยหœ รชยธยฐรซยโ€ž", + ["Destructive Reach"] = "รญล’ล’รชยดยดรฌยหœ รญโ€ฆล’รซโ€˜ยรซยฆยฌ", + ["Detect Greater Invisibility"] = "รฌฦ’ยรชยธโ€ฐ รญห†ยฌรซยชโ€ฆรฌยฒยด รชยฐยรฌยงโ‚ฌ", + ["Detect Invisibility"] = "รญห†ยฌรซยชโ€ฆรฌยฒยด รชยฐยรฌยงโ‚ฌ", + ["Detect Lesser Invisibility"] = "รญโ€ขหœรชยธโ€ฐ รญห†ยฌรซยชโ€ฆรฌยฒยด รชยฐยรฌยงโ‚ฌ", + ["Detect Magic"] = "รซยงห†รซยฒโ€ข รชยฐยรฌยงโ‚ฌ", + ["Detect Traps"] = "รญโ€ขยจรฌย โ€ข รชยฐยรฌยงโ‚ฌ", + ["Detect"] = "รชยฐยรฌยงโ‚ฌ", + ["Deterrence"] = "รชยณยตรชยฒยฉ รฌย โ‚ฌรฌยงโ‚ฌ", +-- ["Devastate"] = true, + ["Devastation"] = "รญโ„ขยฉรญยย", + ["Devotion Aura"] = "รชยธยฐรฌโ€บยรฌยหœ รฌหœยครซยยผ", + ["Devour Magic Effect"] = "รซยงห†รซยฒโ€ข รฌโ€šยผรญโ€šยครชยธยฐ รญลกยจรชยณยผ", + ["Devour Magic"] = "รซยงห†รซยฒโ€ข รฌโ€šยผรญโ€šยครชยธยฐ", + ["Devouring Plague"] = "รญล’ล’รซยฉยธรฌยหœ รฌโ€”ยญรซยณโ€˜", + ["Diplomacy"] = "รฌโ„ขยธรชยตย", + ["Dire Bear Form"] = "รชยดโ€˜รญยยฌรญโ€ขล“ รชยณยฐ รซยณโ‚ฌรฌโ€นย ", + ["Disarm Trap"] = "รญโ€ขยจรฌย โ€ข รญโ€ขยดรฌย ล“", + ["Disarm"] = "รซยฌยดรฌลพยฅ รญโ€ขยดรฌย ล“", + ["Disease Cleansing Totem"] = "รฌยงห†รซยณโ€˜ รฌย โ€ขรญโ„ขโ€ รญโ€ ย รญโ€ฆล“", + ["Disenchant"] = "รซยงห†รซย ยฅ รฌยถโ€รฌยถล“", + ["Disengage"] = "รฌยฒย รฌห†หœ", + ["Dismiss Pet"] = "รฌโ€ขยผรฌห†หœ รฌโ€ ล’รญโ„ขหœรญโ€ขยดรฌย ล“", + ["Dispel Magic"] = "รซยงห†รซยฒโ€ข รซยฌยดรญลกยจรญโ„ขโ€", + ["Distract"] = "รญหœยผรซลพโ‚ฌ", + ["Distracting Shot"] = "รชยฒยฌรฌย ล“ รฌโ€šยฌรชยฒยฉ", + ["Dive"] = "รชยธโ€ฐรชยฐโ€ขรญโ€ขหœ", + ["Divine Favor"] = "รฌโ€นย รฌยหœ รฌยโ‚ฌรฌยดย", + ["Divine Fury"] = "รฌโ€นย รฌยหœ รชยฒยฉรซโ€ฆยธ", +-- ["Divine Illumination"] = true, + ["Divine Intellect"] = "รฌยฒล“รฌฦ’ยรฌยหœ รฌยงโ‚ฌรซล ยฅ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Divine Intervention"] = "รฌโ€žยฑรฌล ยครซลธยฌรฌลกยด รฌยคโ€˜รฌลพยฌ", + ["Divine Protection"] = "รฌโ€นย รฌยหœ รชยฐโ‚ฌรญหœยธ", + ["Divine Shield"] = "รฌยฒล“รฌฦ’ยรฌยหœ รซยณยดรญหœยธรซยงโ€ฐ", + ["Divine Spirit"] = "รฌยฒล“รฌฦ’ยรฌยหœ รฌย โ€ขรฌโ€นย ", + ["Divine Strength"] = "รฌยฒล“รฌฦ’ยรฌยหœ รญลพหœ", + ["Dodge"] = "รญลกล’รญโ€ยผ", +-- ["Dragon's Breath"] = true, + ["Dragonscale Leatherworking"] = "รฌลกยฉรซยนโ€žรซล หœ รชยฐโ‚ฌรฌยฃยฝรฌโ€žยธรชยณยต", + ["Drain Life"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รญยยกรฌห†หœ", + ["Drain Mana"] = "รซยงห†รซโ€šหœ รญยยกรฌห†หœ", + ["Drain Soul"] = "รฌหœยรญหœยผ รญยยกรฌห†หœ", + ["Drink"] = "รฌยล’รซยฃล’", + ["Dual Wield Specialization"] = "รฌล’ยรฌห†หœ รซยฌยดรชยธยฐ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Dual Wield"] = "รฌล’ยรฌห†หœ รซยฌยดรชยธยฐ", + ["Duel"] = "รฌยฃยผรซยฌยธ 7266", + ["Eagle Eye"] = "รซยโ€ฆรฌห†หœรซยฆยฌรฌยหœ รซห†ห†", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"] = "รซล’โ‚ฌรฌยงโ‚ฌ รฌยถยฉรชยฒยฉ", + ["Earthbind Totem"] = "รฌโ€ ยรซยฐโ€ขรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Efficiency"] = "รฌโ€šยฌรชยฒยฉรฌห†ย ", + ["Elemental Focus"] = "รฌย โ€ขรชยธยฐรฌยหœ รฌยงโ€˜รฌยคโ€˜", + ["Elemental Fury"] = "รฌลพยรฌโ€”ยฐรฌยหœ รชยฒยฉรซโ€ฆยธ", + ["Elemental Leatherworking"] = "รฌโ€บยรฌโ€ ล’ รชยฐโ‚ฌรฌยฃยฝรฌโ€žยธรชยณยต", + ["Elemental Mastery"] = "รฌย โ€ขรชยธยฐรฌยหœ รชยนยจรซโ€นยฌรฌยล’", + ["Elemental Sharpening Stone"] = "รฌโ€บยรฌโ€ ล’ รฌห†ยซรซยล’", + ["Elune's Grace"] = "รฌโ€”หœรซยฃยฌรฌยหœ รฌยโ‚ฌรฌยดย", + ["Elusiveness"] = "รฌโ€ขยฝรฌโ€šยญรซยนย รซยฆโ€ž", + ["Emberstorm"] = "รซยถห†รซยณยดรซยยผ", + ["Enamored Water Spirit"] = "รฌโ€šยฌรซยกล“รฌลพยกรญลพล’ รซยฌยผรฌยหœ รฌย โ€ขรซย ยน", + ["Enchanting"] = "รซยงห†รซยฒโ€ขรซยถโ‚ฌรฌโ€”ยฌ", + ["Endurance Training"] = "รฌยงโ‚ฌรชยตยฌรซย ยฅ รญโ€บห†รซย ยจ", + ["Endurance"] = "รฌยยธรซโ€šยดรซย ยฅ", + ["Engineering Specialization"] = "รชยธยฐรชยณโ€žรชยณยตรญโ€ขโ„ข รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Engineering"] = "รชยธยฐรชยณโ€žรชยณยตรญโ€ขโ„ข", + ["Enrage"] = "รชยฒยฉรซโ€ฆยธ", + ["Enriched Manna Biscuit"] = "รซยงโ€บรฌยขโ€นรฌยโ‚ฌ รซยงล’รซโ€šหœรซยนยต", + ["Enslave Demon"] = "รฌโ€ขโ€ฆรซยงห† รฌยงโ‚ฌรซยฐยฐ", + ["Entangling Roots"] = "รญล“หœรชยฐยรซล โ€ รซยฟล’รซยฆยฌ", + ["Entrapment"] = "รฌหœยฌรชยฐโ‚ฌรซยฏยธ", +-- ["Envenom"] = true, + ["Escape Artist"] = "รญฦ’ห†รฌยถล“รฌยหœ รซยชโ€ฆรฌห†หœ", + ["Evasion"] = "รญลกล’รญโ€ยผ", + ["Eventide"] = "รฌลพยรฌโ€”ยฐรฌยหœ รชยฐโ‚ฌรซยฅยดรฌยนยจ", + ["Eviscerate"] = "รฌย ห†รชยฐล“", + ["Evocation"] = "รญโ„ขหœรชยธยฐ", + ["Execute"] = "รซยงห†รซยฌยดรซยฆยฌ รฌยยผรชยฒยฉ", + ["Exorcism"] = "รญโ€กยดรซยงห†รฌห†ย ", + ["Expansive Mind"] = "รฌหœยรซยฆยฌรญโ€ขยจ", + ["Explosive Trap Effect"] = "รญยยญรซยฐล“รฌยหœ รซยยซ", + ["Explosive Trap"] = "รญยยญรซยฐล“รฌยหœ รซยยซ", + ["Expose Armor"] = "รฌโ€ขยฝรฌย ย รซโ€ฆยธรฌยถล“", + ["Eye for an Eye"] = "รซห†ห†รฌโ€”ยรซล โ€ รซห†ห†", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Eye of Kilrogg"] = "รญโ€šยฌรซยกล“รชยทยธรฌยหœ รซห†ห†", + ["Eyes of the Beast"] = "รฌโ€ขยผรฌห†หœรฌยหœ รซห†ห†", + ["Fade"] = "รฌโ€ ล’รฌโ€นยค", + ["Faerie Fire"] = "รฌลกโ€รฌย โ€ขรฌยหœ รซยถห†รชยฝฦ’", + ["Faerie Fire (Feral)"] = "รฌลกโ€รฌย โ€ขรฌยหœ รซยถห†รชยฝฦ’ (รฌโ€ขยผรฌโ€žยฑ)", + ["Far Sight"] = "รฌยฒล“รซยฆยฌรฌโ€ขห†", + ["Fear Ward"] = "รชยณยตรญยยฌรฌยหœ รฌห†หœรญหœยธรซยฌยผ", + ["Fear"] = "รชยณยตรญยยฌ", + ["Feed Pet"] = "รซยจยนรฌยยดรฌยฃยผรชยธยฐ", + ["Feedback"] = "รฌโ€”ยญรฌห†ล“รญโ„ขหœ", + ["Feign Death"] = "รฌยฃยฝรฌยโ‚ฌรฌยฒโ„ขรญโ€ขหœรชยธยฐ", + ["Feint"] = "รชยตยรซลพโ‚ฌ", +-- ["Fel Armor"] = true, + ["Fel Concentration"] = "รซยงห†รฌยหœ รฌย โ€ขรฌโ€นย รฌยงโ€˜รฌยคโ€˜", + ["Fel Domination"] = "รซยงห†รฌยหœ รฌยงโ‚ฌรซยฐยฐ", + ["Fel Intellect"] = "รซยงห†รฌยหœ รฌยงโ‚ฌรซล ยฅ", + ["Fel Stamina"] = "รซยงห†รฌยหœ รฌยฒยดรซย ยฅ", + ["Felfire"] = "รฌยงโ‚ฌรฌหœยฅรซยถห†", + ["Feline Grace"] = "รฌโ€šยดรฌยพยกรฌยยดรฌยหœ รฌลกยฐรฌโ€ขโ€žรญโ€ขยจ", + ["Feline Swiftness"] = "รฌโ€šยดรฌยพยกรฌยยดรฌยหœ รชยธยฐรซยฏยผรญโ€ขยจ", + ["Feral Aggression"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รชยณยตรชยฒยฉรฌโ€žยฑ", + ["Feral Charge"] = "รฌโ€ขยผรฌโ€žยฑรฌยหœ รซยล’รฌยงโ€ž", + ["Feral Instinct"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รซยณยธรซล ยฅ", + ["Ferocious Bite"] = "รญยโ€ฐรญยยฌรญโ€ขล“ รฌยยดรซยนยจ", + ["Ferocity"] = "รซยฏยธรฌโ€šยฌรฌลกยฉ รฌยฃยผรซยฌยธ", + ["Fetish"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Find Herbs"] = "รฌโ€ขยฝรฌยดห† รฌยฐยพรชยธยฐ", + ["Find Minerals"] = "รชยดโ€˜รซยฌยผ รฌยฐยพรชยธยฐ", + ["Find Treasure"] = "รซยณยดรซยฌยผ รฌยฐยพรชยธยฐ", + ["Fire Blast"] = "รญโ„ขโ€รฌโ€”ยผ รฌลพโ€˜รฌโ€”ยด", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = "รซยถห†รชยฝฦ’ รญลกล’รฌหœยครซยฆยฌ รญโ€ ย รญโ€ฆล“", + ["Fire Power"] = "รญโ„ขโ€รฌโ€”ยผ รซยงห†รซยฒโ€ข รชยฐโ€ขรญโ„ขโ€", + ["Fire Resistance Aura"] = "รญโ„ขโ€รฌโ€”ยผ รฌย โ‚ฌรญโ€ขยญรฌยหœ รฌหœยครซยยผ", + ["Fire Resistance Totem"] = "รญโ„ขโ€รฌโ€”ยผ รฌย โ‚ฌรญโ€ขยญ รญโ€ ย รญโ€ฆล“", + ["Fire Resistance"] = "รญโ„ขโ€รฌโ€”ยผ รซยงห†รซยฒโ€ข รฌย โ‚ฌรญโ€ขยญ", + ["Fire Shield"] = "รญโ„ขโ€รฌโ€”ยผ รซยณยดรญหœยธรซยงโ€ฐ", + ["Fire Vulnerability"] = "รญโ„ขโ€รฌโ€”ยผ รฌย โ‚ฌรญโ€ขยญรซย ยฅ รฌโ€ขยฝรญโ„ขโ€", + ["Fire Ward"] = "รญโ„ขโ€รฌโ€”ยผรชยณโ€ž รฌห†หœรญหœยธ", + ["Fireball"] = "รญโ„ขโ€รฌโ€”ยผรชยตยฌ", + ["Firebolt"] = "รซยถห†รญโ„ขโ€รฌโ€šยด", + ["First Aid"] = "รฌยโ€˜รชยธโ€ฐรฌยนหœรซยฃล’", -- CHECK + ["Fishing Poles"] = "รซโ€šลกรฌโ€นยฏรซล’โ‚ฌ", + ["Fishing"] = "รซโ€šลกรฌโ€นล“", + ["Fist Weapon Specialization"] = "รฌลพยฅรฌยฐยฉ รซยฌยดรชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Fist Weapons"] = "รฌลพยฅรฌยฐยฉ รซยฌยดรชยธยฐรซยฅหœ", + ["Flame Shock"] = "รญโ„ขโ€รฌโ€”ยผ รฌยถยฉรชยฒยฉ", + ["Flame Throwing"] = "รญโ„ขโ€รฌโ€”ยผ รซยฐล“รฌโ€šยฌ", + ["Flamestrike"] = "รซยถห†รชยธยฐรซโ€˜ยฅ", + ["Flamethrower"] = "รญโ„ขโ€รฌโ€”ยผรซยฐยฉรฌโ€šยฌรชยธยฐ", + ["Flametongue Totem"] = "รซยถห†รชยฝฦ’รฌยหœ รญโ€ ย รญโ€ฆล“", + ["Flametongue Weapon"] = "รซยถห†รชยฝฦ’รฌยหœ รซยฌยดรชยธยฐ", + ["Flare"] = "รฌโ€žยฌรชยดโ€˜", + ["Flash Heal"] = "รฌห†ล“รชยฐโ€ž รฌยนหœรฌล“ย ", + ["Flash of Light"] = "รซยนโ€บรฌยหœ รฌโ€žยฌรชยดโ€˜", +-- ["Flight Form"] = true, + ["Flurry"] = "รฌยงห†รญโ€™ย", + ["Focused Casting"] = "รฌยงโ€˜รฌยคโ€˜รซย ยฅ", + ["Food"] = "รฌยล’รฌโ€นย", + ["Forbearance"] = "รฌยฐยธรฌยโ€žรฌโ€žยฑ", +-- ["Force of Nature"] = true, + ["Force of Will"] = "รฌยหœรฌยงโ‚ฌรฌยหœ รญลพหœ", + ["Freezing Trap Effect"] = "รฌโ€“ยผรฌยล’รฌยหœ รซยยซ", + ["Freezing Trap"] = "รฌโ€“ยผรฌยล’รฌยหœ รซยยซ", + ["Frenzied Regeneration"] = "รชยดโ€˜รญยยฌรญโ€ขล“ รฌลพยฌรฌฦ’ยรซย ยฅ", + ["Frenzy"] = "รชยดโ€˜รชยธยฐ", + ["Frost Armor"] = "รซฦ’โ€ฐรชยธยฐ รชยฐโ€˜รฌหœยท", + ["Frost Channeling"] = "รซฦ’โ€ฐรชยธยฐรชยณโ€ž รฌย โ€ขรฌโ€นย รฌยงโ€˜รฌยคโ€˜", + ["Frost Nova"] = "รฌโ€“ยผรฌยล’ รญลกล’รฌหœยครซยฆยฌ", + ["Frost Resistance Aura"] = "รซฦ’โ€ฐรชยธยฐ รฌย โ‚ฌรญโ€ขยญรฌยหœ รฌหœยครซยยผ", + ["Frost Resistance Totem"] = "รซฦ’โ€ฐรชยธยฐ รฌย โ‚ฌรญโ€ขยญ รญโ€ ย รญโ€ฆล“", + ["Frost Resistance"] = "รซฦ’โ€ฐรชยธยฐ รซยงห†รซยฒโ€ข รฌย โ‚ฌรญโ€ขยญ", + ["Frost Shock"] = "รซฦ’โ€ฐรชยธยฐ รฌยถยฉรชยฒยฉ", + ["Frost Trap"] = "รซฦ’โ€ฐรชยธยฐรฌยหœ รซยยซ", + ["Frost Trap Aura"] = "รซฦ’โ€ฐรชยธยฐรฌยหœ รซยยซ", + ["Frost Ward"] = "รซฦ’โ€ฐรชยธยฐรชยณโ€ž รฌห†หœรญหœยธ", + ["Frostbite"] = "รซยโ„ขรฌฦ’ย", + ["Frostbolt"] = "รฌโ€“ยผรฌยล’ รญโ„ขโ€รฌโ€šยด", + ["Frostbrand Weapon"] = "รซฦ’โ€ฐรชยธยฐรฌยหœ รซยฌยดรชยธยฐ", + ["Furious Howl"] = "รฌโ€šยฌรซโ€šหœรฌลกยด รฌลกยธรฌยล’รฌโ€ ล’รซยฆยฌ", + ["Furor"] = "รชยดโ€˜รซลพโ‚ฌ", + ["Garrote"] = "รซยชยฉรฌยกยฐรซยฅยดรชยธยฐ", + ["Generic"] = "รฌยฃยผรซยฌยธ 2382", + ["Ghost Wolf"] = "รซล โ€˜รซล’โ‚ฌ รฌย โ€ขรซย ยน", + ["Ghostly Strike"] = "รชยทยธรซยฆยผรฌลพย รฌยยผรชยฒยฉ", + ["Gift of Life"] = true, + ["Gift of Nature"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌโ€žย รซยฌยผ", + ["Gift of the Wild"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌโ€žย รซยฌยผ", + ["Gouge"] = "รญโ€บโ€žรซย ยครฌยนหœรชยธยฐ", + ["Grace of Air Totem"] = "รฌยโ‚ฌรฌยดยรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Great Stamina"] = "รชยฐโ€ขรฌยยธรญโ€ขล“ รฌยฒยดรซย ยฅ", + ["Greater Blessing of Kings"] = "รฌฦ’ยรชยธโ€ฐ รฌโ„ขโ€ขรฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Blessing of Light"] = "รฌฦ’ยรชยธโ€ฐ รซยนโ€บรฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Blessing of Might"] = "รฌฦ’ยรชยธโ€ฐ รญลพหœรฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Blessing of Salvation"] = "รฌฦ’ยรชยธโ€ฐ รชยตยฌรฌโ€บยรฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Blessing of Sanctuary"] = "รฌฦ’ยรชยธโ€ฐ รฌโ€žยฑรฌโ€”ยญรฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Blessing of Wisdom"] = "รฌฦ’ยรชยธโ€ฐ รฌยงโ‚ฌรญหœล“รฌยหœ รฌยถโ€ขรซยณยต", + ["Greater Heal"] = "รฌฦ’ยรชยธโ€ฐ รฌยนหœรฌล“ย ", + ["Grim Reach"] = "รซฦ’โ€ฐรญหœยนรฌยหœ รญโ€ฆล’รซโ€˜ยรซยฆยฌ", + ["Grounding Totem"] = "รซยงห†รซยฒโ€ขรฌย โ€ขรญโ„ขโ€ รญโ€ ย รญโ€ฆล“", + ["Grovel"] = "รฌยฃยผรซยฌยธ 7267", + ["Growl"] = "รญยยฌรญลกยจ", + ["Guardian's Favor"] = "รฌห†หœรญหœยธรฌโ€นย รฌยหœ รฌยโ‚ฌรฌยดย", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Gun Specialization"] = "รฌยดยรชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Guns"] = "รฌยดย", + ["Hammer of Justice"] = "รฌโ€นยฌรญล’ยรฌยหœ รซยงยรฌยนหœ", + ["Hammer of Wrath"] = "รฌยยผรชยฒยฉ", + ["Hamstring"] = "รซยฌยดรซย ยฅรญโ„ขโ€", + ["Harass"] = "รชยดยดรซยกยญรญลพห†รชยธยฐ", + ["Hardiness"] = "รชยฐโ€ขรฌยยธรญโ€ขยจ", + ["Hawk Eye"] = "รซยงยครฌยหœ รซห†ห†", + ["Heal"] = "รฌยนหœรฌล“ย ", + ["Healing Focus"] = "รฌยนหœรฌล“ย รฌยหœ รฌย โ€ขรฌโ€นย  รฌยงโ€˜รฌยคโ€˜", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Healing Light"] = "รฌยนหœรฌล“ย รฌยหœ รซยนโ€บ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Healing Stream Totem"] = "รฌยนหœรฌล“ย รฌยหœ รญโ€ ย รญโ€ฆล“", + ["Healing Touch"] = "รฌยนหœรฌล“ย รฌยหœ รฌโ€ ยรชยธยธ", + ["Healing Wave"] = "รฌยนหœรฌล“ย รฌยหœ รซยฌยผรชยฒยฐ", + ["Healing Way"] = "รฌยนหœรฌล“ย รฌยหœ รชยธยธ", + ["Health Funnel"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รฌยงโ€˜รฌยคโ€˜", + ["Heart of the Wild"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌย โ€ขรฌห†หœ", + ["Heavy Sharpening Stone"] = "รซโ€นยจรซโ€นยจรญโ€ขล“ รฌห†ยซรซยล’", + ["Hellfire Effect"] = "รฌยงโ‚ฌรฌหœยฅรฌยหœ รซยถห†รชยธยธ รญลกยจรชยณยผ", + ["Hellfire"] = "รฌยงโ‚ฌรฌหœยฅรฌยหœ รซยถห†รชยธยธ", + ["Hemorrhage"] = "รชยณยผรซโ€นยครฌยถล“รญหœห†", + ["Herb Gathering"] = "รฌโ€ขยฝรฌยดห†รฌยฑโ€žรฌยงโ€˜", + ["Herbalism"] = "รฌโ€ขยฝรฌยดห† รฌยฑโ€žรฌยงโ€˜", + ["Heroic Strike"] = "รฌหœยรฌโ€บโ€ฆรฌยหœ รฌยยผรชยฒยฉ", +-- ["Heroism"] = true, + ["Hex of Weakness"] = "รซยฌยดรซย ยฅรฌยหœ รฌยฃยผรฌห†ย ", + ["Hibernate"] = "รชยฒยจรฌลกยธรฌลพย ", + ["Holy Fire"] = "รฌโ€นย รฌโ€žยฑรญโ€ขล“ รซยถห†รชยฝฦ’", + ["Holy Light"] = "รฌโ€žยฑรฌล ยครซลธยฌรฌลกยด รซยนโ€บ", + ["Holy Nova"] = "รฌโ€นย รฌโ€žยฑรญโ€ขล“ รญยยญรซยฐล“", + ["Holy Power"] = "รฌโ€นย รฌโ€žยฑ รซยงห†รซยฒโ€ข รชยฐโ€ขรญโ„ขโ€", + ["Holy Reach"] = "รฌโ€นย รฌโ€žยฑรญโ€ขล“ รญโ€ฆล’รซโ€˜ยรซยฆยฌ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Holy Shield"] = "รฌโ€นย รฌโ€žยฑ รซยณยดรญหœยธรซยงโ€ฐ", + ["Holy Shock"] = "รฌโ€นย รฌโ€žยฑ รฌยถยฉรชยฒยฉ", + ["Holy Specialization"] = "รฌโ€นย รฌโ€žยฑ รซยงห†รซยฒโ€ข รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Holy Wrath"] = "รฌโ€นย รฌยหœ รชยฒยฉรซโ€ฆยธ", + ["Honorless Target"] = "รซยชโ€ฆรฌหœห† รฌย ยรฌห†หœ รฌโ€”โ€ รฌยล’", + ["Horse Riding"] = "รซยงย รญฦ’โ‚ฌรชยธยฐ", + ["Howl of Terror"] = "รชยณยตรญยยฌรฌยหœ รฌลกยธรซยถโ‚ฌรฌยงโ€“รฌยล’", + ["Humanoid Slaying"] = "รฌยยธรชยฐโ€žรญหœโ€ข รฌโ€šยฌรซฦ’ยฅรฌห†ย ", + ["Hunter's Mark"] = "รฌโ€šยฌรซฦ’ยฅรชยพยผรฌยหœ รฌยงโ€ขรญโ€˜ล“", + ["Hurricane"] = "รญโ€”ห†รซยฆยฌรฌยผโ‚ฌรฌยยธ", + ["Ice Armor"] = "รฌโ€“ยผรฌยล’ รชยฐโ€˜รฌหœยท", + ["Ice Barrier"] = "รฌโ€“ยผรฌยล’ รซยณยดรญหœยธรซยงโ€ฐ", + ["Ice Block"] = "รฌโ€“ยผรฌยล’ รซยฐยฉรญล’ยจ", +-- ["Ice Lance"] = true, + ["Ice Shards"] = "รฌโ€“ยผรฌยล’ รญล’ล’รญลฝยธ", + ["Ignite"] = "รฌลพโ€˜รฌโ€”ยด", + ["Illumination"] = "รชยณโ€žรฌโ€นล“", + ["Immolate"] = "รฌย ล“รซยฌยผ", + ["Immolation Trap Effect"] = "รฌย ล“รซยฌยผรฌยหœ รซยยซ", + ["Immolation Trap"] = "รฌย ล“รซยฌยผรฌยหœ รซยยซ", + ["Impact"] = "รฌยถยฉรซยล’", + ["Impale"] = "รชยฟยฐรซลกยซรชยธยฐ", + ["Improved Ambush"] = "รซยงยครซยณยต รฌโ€”ยฐรซยงห†", + ["Improved Arcane Explosion"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รญยยญรซยฐล“ รฌโ€”ยฐรซยงห†", + ["Improved Arcane Missiles"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Arcane Shot"] = "รฌโ€นย รซยนโ€žรญโ€ขล“ รฌโ€šยฌรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Aspect of the Hawk"] = "รซยงยครฌยหœ รฌฦ’ย รฌโ€”ยฐรซยงห†", + ["Improved Aspect of the Monkey"] = "รฌโ€บยรฌห†ยญรฌยยดรฌยหœ รฌฦ’ย รฌโ€”ยฐรซยงห†", + ["Improved Backstab"] = "รชยธยฐรฌล ยต รฌโ€”ยฐรซยงห†", + ["Improved Battle Shout"] = "รฌย โ€žรญห†ยฌรฌยหœ รฌโ„ขยธรฌยนยจ รฌโ€”ยฐรซยงห†", + ["Improved Berserker Rage"] = "รชยดโ€˜รฌย โ€žรฌโ€šยฌรฌยหœ รชยฒยฉรซโ€ฆยธ รฌโ€”ยฐรซยงห†", + ["Improved Blessing of Might"] = "รญลพหœรฌยหœ รฌยถโ€ขรซยณยต รฌโ€”ยฐรซยงห†", + ["Improved Blessing of Wisdom"] = "รฌยงโ‚ฌรญหœล“รฌยหœ รฌยถโ€ขรซยณยต รฌโ€”ยฐรซยงห†", + ["Improved Blizzard"] = "รซห†ห†รซยณยดรซยยผ รฌโ€”ยฐรซยงห†", + ["Improved Bloodrage"] = "รญโ€ยผรฌยหœ รซยถโ€žรซโ€ฆยธ รฌโ€”ยฐรซยงห†", + ["Improved Chain Heal"] = "รฌโ€”ยฐรฌโ€กโ€ž รฌยนหœรฌล“ย  รฌโ€”ยฐรซยงห†", + ["Improved Chain Lightning"] = "รฌโ€”ยฐรฌโ€กโ€ž รซยฒห†รชยฐล“ รฌโ€”ยฐรซยงห†", + ["Improved Challenging Shout"] = "รซยโ€žรฌย โ€žรฌยหœ รฌโ„ขยธรฌยนยจ รฌโ€”ยฐรซยงห†", + ["Improved Charge"] = "รซยล’รฌยงโ€ž รฌโ€”ยฐรซยงห†", + ["Improved Cheap Shot"] = "รซยนโ€žรฌโ€”ยดรญโ€ขล“ รฌล ยตรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Cleave"] = "รญลกล’รฌย โ€žรซยฒย รชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Concentration Aura"] = "รฌยงโ€˜รฌยคโ€˜รฌยหœ รฌหœยครซยยผ รฌโ€”ยฐรซยงห†", + ["Improved Concussive Shot"] = "รฌยถยฉรชยฒยฉรญยยฌ รฌโ€”ยฐรซยงห†", + ["Improved Cone of Cold"] = "รซฦ’โ€ฐรชยธยฐ รซยล’รญโ€™ย รฌโ€”ยฐรซยงห†", + ["Improved Corruption"] = "รซยถโ‚ฌรญล’ยจ รฌโ€”ยฐรซยงห†", + ["Improved Counterspell"] = "รซยงห†รซยฒโ€ข รฌยฐยจรซโ€นยจ รฌโ€”ยฐรซยงห†", + ["Improved Curse of Agony"] = "รชยณย รญโ€ ยตรฌยหœ รฌย โ‚ฌรฌยฃยผ รฌโ€”ยฐรซยงห†", + ["Improved Curse of Exhaustion"] = "รญโ€ยผรซยกล“รฌยหœ รฌย โ‚ฌรฌยฃยผ รฌโ€”ยฐรซยงห†", + ["Improved Curse of Weakness"] = "รซยฌยดรซย ยฅรญโ„ขโ€ รฌย โ‚ฌรฌยฃยผ รฌโ€”ยฐรซยงห†", + ["Improved Dampen Magic"] = "รซยงห†รซยฒโ€ขรฌยหœ รฌยกยฐรญโ„ขโ€", + ["Improved Deadly Poison"] = "รซยงยนรซยโ€ฆ รฌโ€”ยฐรชยตยฌ", + ["Improved Demoralizing Shout"] = "รฌโ€šยฌรชยธยฐรฌยหœ รฌโ„ขยธรฌยนยจ รฌโ€”ยฐรซยงห†", + ["Improved Devotion Aura"] = "รชยธยฐรฌโ€บยรฌยหœ รฌหœยครซยยผ รฌโ€”ยฐรซยงห†", + ["Improved Disarm"] = "รซยฌยดรฌลพยฅ รญโ€ขยดรฌย ล“ รฌโ€”ยฐรซยงห†", + ["Improved Distract"] = "รญหœยผรซลพโ‚ฌ รฌโ€”ยฐรซยงห†", + ["Improved Drain Life"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รญยยกรฌห†หœ รฌโ€”ยฐรซยงห†", + ["Improved Drain Mana"] = "รซยงห†รซโ€šหœ รญยยกรฌห†หœ รฌโ€”ยฐรซยงห†", + ["Improved Drain Soul"] = "รฌหœยรญหœยผ รญยยกรฌห†หœ รฌโ€”ยฐรซยงห†", + ["Improved Enrage"] = "รซยถโ€žรซโ€ฆยธ รฌโ€”ยฐรซยงห†", + ["Improved Enslave Demon"] = "รฌโ€ขโ€ฆรซยงห† รฌยงโ‚ฌรซยฐยฐ รฌโ€”ยฐรซยงห†", + ["Improved Entangling Roots"] = "รญล“หœรชยฐยรซล โ€ รซยฟล’รซยฆยฌ รฌโ€”ยฐรซยงห†", + ["Improved Evasion"] = "รญลกล’รญโ€ยผ รฌโ€”ยฐรซยงห†", + ["Improved Eviscerate"] = "รฌย ห†รชยฐล“ รฌโ€”ยฐรซยงห†", + ["Improved Execute"] = "รซยงห†รซยฌยดรซยฆยฌ รฌยยผรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Expose Armor"] = "รฌโ€ขยฝรฌย ย รซโ€ฆยธรฌยถล“ รฌโ€”ยฐรซยงห†", + ["Improved Eyes of the Beast"] = "รฌโ€ขยผรฌห†หœรฌยหœ รซห†ห† รฌโ€”ยฐรซยงห†", + ["Improved Fade"] = "รฌโ€ ล’รฌโ€นยค รฌโ€”ยฐรซยงห†", + ["Improved Feign Death"] = "รฌยฃยฝรฌยโ‚ฌรฌยฒโ„ขรญโ€ขหœรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Fire Blast"] = "รญโ„ขโ€รฌโ€”ยผ รฌลพโ€˜รฌโ€”ยด รฌโ€”ยฐรซยงห†", + ["Improved Fire Nova Totem"] = "รซยถห†รฌยหœ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Fire Ward"] = "รญโ„ขโ€รฌโ€”ยผรชยณโ€ž รฌห†หœรญหœยธ รฌโ€”ยฐรซยงห†", + ["Improved Fireball"] = "รญโ„ขโ€รฌโ€”ยผรชยตยฌ รฌโ€”ยฐรซยงห†", + ["Improved Firebolt"] = "รซยถห†รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Firestone"] = "รญโ„ขโ€รฌโ€”ยผรฌโ€žย รฌโ€”ยฐรซยงห†", + ["Improved Flamestrike"] = "รซยถห†รชยธยฐรซโ€˜ยฅ รฌโ€”ยฐรซยงห†", + ["Improved Flametongue Weapon"] = "รซยถห†รชยฝฦ’รฌยหœ รซยฌยดรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Flash of Light"] = "รซยนโ€บรฌยหœ รฌโ€žยฌรชยดโ€˜ รฌโ€”ยฐรซยงห†", + ["Improved Frost Nova"] = "รฌโ€“ยผรฌยล’ รญลกล’รฌหœยครซยฆยฌ รฌโ€”ยฐรซยงห†", + ["Improved Frost Ward"] = "รซฦ’โ€ฐรชยธยฐรฌยหœ รฌห†หœรญหœยธ", + ["Improved Frostbolt"] = "รฌโ€“ยผรฌยล’ รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Frostbrand Weapon"] = "รซฦ’โ€ฐรชยธยฐรฌยหœ รซยฌยดรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Garrote"] = "รซยชยฉ รฌยกยฐรซยฅยดรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Ghost Wolf"] = "รซล โ€˜รซล’โ‚ฌ รฌย โ€ขรซย ยน รฌโ€”ยฐรซยงห†", + ["Improved Gouge"] = "รญโ€บโ€žรซย ยครฌยนหœรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Grace of Air Totem"] = "รฌยโ‚ฌรฌยดยรฌยหœ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Grounding Totem"] = "รซยงห†รซยฒโ€ขรฌย โ€ขรญโ„ขโ€ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Hammer of Justice"] = "รฌโ€นยฌรญล’ยรฌยหœ รซยงยรฌยนหœ รฌโ€”ยฐรซยงห†", + ["Improved Hamstring"] = "รซยฌยดรซย ยฅรญโ„ขโ€ รฌโ€”ยฐรซยงห†", + ["Improved Healing Stream Totem"] = "รฌยนหœรฌล“ย รฌยหœ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Healing Touch"] = "รฌยนหœรฌล“ย รฌยหœ รฌโ€ ยรชยธยธ รฌโ€”ยฐรซยงห†", + ["Improved Healing Wave"] = "รฌยนหœรฌล“ย รฌยหœ รซยฌยผรชยฒยฐ รฌโ€”ยฐรซยงห†", + ["Improved Healing"] = "รฌยนหœรฌล“ย  รฌโ€”ยฐรซยงห†", + ["Improved Health Funnel"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รฌยงโ€˜รฌยคโ€˜ รฌโ€”ยฐรซยงห†", + ["Improved Healthstone"] = "รฌฦ’ยรซยชโ€ฆรฌโ€žย รฌโ€”ยฐรซยงห†", + ["Improved Heroic Strike"] = "รฌหœยรฌโ€บโ€ฆรฌยหœ รฌยยผรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Hunter's Mark"] = "รฌโ€šยฌรซฦ’ยฅรชยพยผรฌยหœ รฌยงโ€ขรญโ€˜ล“ รฌโ€”ยฐรซยงห†", + ["Improved Immolate"] = "รฌย ล“รซยฌยผ รฌโ€”ยฐรซยงห†", + ["Improved Imp"] = "รฌลพโ€žรญโ€โ€ž รฌโ€”ยฐรซยงห†", + ["Improved Inner Fire"] = "รซโ€šยดรซยฉยดรฌยหœ รฌโ€”ยดรฌย โ€ข รฌโ€”ยฐรซยงห†", + ["Improved Instant Poison"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ รฌโ€”ยฐรชยตยฌ", + ["Improved Intercept"] = "รซยดโ€ฐรฌโ€กโ€ž รฌโ€”ยฐรซยงห†", + ["Improved Intimidating Shout"] = "รฌล“โ€žรญหœโ€˜รฌยหœ รฌโ„ขยธรฌยนยจ รฌโ€”ยฐรซยงห†", + ["Improved Judgement"] = "รฌโ€นยฌรญล’ย รฌโ€”ยฐรซยงห†", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Improved Kick"] = "รซยฐล“รฌยฐยจรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Kidney Shot"] = "รชยธโ€ฐรฌโ€ ล’ รชยฐโ‚ฌรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Lash of Pain"] = "รชยณย รญโ€ ยตรฌยหœ รฌยฑโ€žรฌยฐย รฌโ€”ยฐรซยงห†", + ["Improved Lay on Hands"] = "รฌโ€นย รฌยหœ รฌยถโ€ขรซยณยต รฌโ€”ยฐรซยงห†", + ["Improved Lesser Healing Wave"] = "รฌยนหœรฌล“ย รฌยหœ รฌยงโ€˜รฌยคโ€˜", + ["Improved Life Tap"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รฌย โ€žรญโ„ขหœ รฌโ€”ยฐรซยงห†", + ["Improved Lightning Bolt"] = "รซยฒห†รชยฐล“ รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Lightning Shield"] = "รซยฒห†รชยฐล“ รซยณยดรญหœยธรซยงโ€ฐ รฌโ€”ยฐรซยงห†", + ["Improved Magma Totem"] = "รฌลกยฉรฌโ€ขโ€ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Mana Burn"] = "รซยงห†รซโ€šหœ รฌโ€”ยฐรฌโ€ ล’ รฌโ€”ยฐรซยงห†", + ["Improved Mana Shield"] = "รซยงห†รซโ€šหœ รซยณยดรญหœยธรซยงโ€ฐ รฌโ€”ยฐรซยงห†", + ["Improved Mana Spring Totem"] = "รญลกล’รซยณยตรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Improved Mark of the Wild"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌยงโ€ขรญโ€˜ล“ รฌโ€”ยฐรซยงห†", + ["Improved Mend Pet"] = "รซยโ„ขรซยฌยผ รฌยนหœรซยฃล’ รฌโ€”ยฐรซยงห†", + ["Improved Mind Blast"] = "รฌย โ€ขรฌโ€นย  รซยถโ€žรฌโ€”ยด รฌโ€”ยฐรซยงห†", + ["Improved Moonfire"] = "รซโ€นยฌรซยนโ€บ รฌโ€žยฌรชยดโ€˜ รฌโ€”ยฐรซยงห†", + ["Improved Nature's Grasp"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌโ€ ยรฌโ€ขโ€žรชยทโ‚ฌ รฌโ€”ยฐรซยงห†", + ["Improved Overpower"] = "รฌย ล“รฌโ€ขโ€ข รฌโ€”ยฐรซยงห†", + ["Improved Power Word: Fortitude"] = "รฌโ€นย รฌยหœ รชยถล’รซล ยฅ: รฌยยธรซโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Power Word: Shield"] = "รฌโ€นย รฌยหœ รชยถล’รซล ยฅ: รซยณยดรญหœยธรซยงโ€ฐ รฌโ€”ยฐรซยงห†", + ["Improved Prayer of Healing"] = "รฌยนหœรฌล“ย รฌยหœ รชยธยฐรฌโ€บย รฌโ€”ยฐรซยงห†", + ["Improved Psychic Scream"] = "รฌหœยรญหœยผรฌยหœ รฌย ห†รชยทล“ รฌโ€”ยฐรซยงห†", + ["Improved Pummel"] = "รฌลพยรซยฃยจ รชยณยตรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Regrowth"] = "รฌลพยฌรฌฦ’ย รฌโ€”ยฐรซยงห†", + ["Improved Reincarnation"] = "รฌล“ยครญลกล’ รฌโ€”ยฐรซยงห†", + ["Improved Rejuvenation"] = "รญลกล’รซยณยต รฌโ€”ยฐรซยงห†", + ["Improved Rend"] = "รซยถโ€žรฌโ€กโ€ž รฌโ€”ยฐรซยงห†", + ["Improved Renew"] = "รฌโ€ ล’รฌฦ’ย รฌโ€”ยฐรซยงห†", + ["Improved Retribution Aura"] = "รฌยโ€˜รซยณยดรฌยหœ รฌหœยครซยยผ รฌโ€”ยฐรซยงห†", + ["Improved Revenge"] = "รซยณยตรฌห†หœ รฌโ€”ยฐรซยงห†", + ["Improved Revive Pet"] = "รฌโ€ขยผรฌห†หœ รซยหœรฌโ€šยดรซยฆยฌรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Righteous Fury"] = "รฌย โ€ขรฌยหœรฌยหœ รชยฒยฉรซโ€ฆยธ รฌโ€”ยฐรซยงห†", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Improved Rockbiter Weapon"] = "รซล’โ‚ฌรฌยงโ‚ฌรฌยหœ รซยฌยดรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Rupture"] = "รญล’ล’รฌโ€”ยด รฌโ€”ยฐรซยงห†", + ["Improved Sap"] = "รชยธยฐรฌย ห†รฌโ€นล“รญโ€šยครชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Scorch"] = "รซยถห†รญฦ’ล“รฌลกยฐรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Scorpid Sting"] = "รฌย โ€žรชยฐห† รฌยยรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Seal of Righteousness"] = "รฌย โ€ขรฌยหœรฌยหœ รซยฌยธรฌลพยฅ รฌโ€”ยฐรซยงห†", + ["Improved Seal of the Crusader"] = "รฌโ€žยฑรฌย โ€žรฌโ€šยฌรฌยหœ รซยฌยธรฌลพยฅ รฌโ€”ยฐรซยงห†", + ["Improved Searing Pain"] = "รซยถห†รญฦ’โ‚ฌรซล โ€ รชยณย รญโ€ ยต รฌโ€”ยฐรซยงห†", + ["Improved Searing Totem"] = "รซยถห†รญฦ’โ‚ฌรซล โ€ รญโ€ ย รญโ€ฆล“ รฌโ€”ยฐรซยงห†", + ["Improved Serpent Sting"] = "รซยโ€ฆรฌโ€šยฌ รฌยยรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Shadow Bolt"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Shadow Word: Pain"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รชยถล’รซล ยฅ: รชยณย รญโ€ ยต รฌโ€”ยฐรซยงห†", + ["Improved Shield Bash"] = "รซยฐยฉรญล’ยจ รชยฐโ‚ฌรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Shield Block"] = "รซยฐยฉรญล’ยจ รซยงโ€ฐรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Shield Wall"] = "รซยฐยฉรญล’ยจรฌยหœ รซยฒยฝ รฌโ€”ยฐรซยงห†", + ["Improved Shred"] = "รฌยนยผรซโ€šย  รซยฐล“รญโ€ ยฑ รฌโ€”ยฐรซยงห†", + ["Improved Sinister Strike"] = "รฌโ€šยฌรฌโ€ขโ€ฆรญโ€ขล“ รฌยยผรชยฒยฉ รฌโ€”ยฐรซยงห†", + ["Improved Slam"] = "รชยฒยฉรซยล’ รฌโ€”ยฐรซยงห†", + ["Improved Slice and Dice"] = "รซโ€šล“รซยโ€žรฌยงห† รฌโ€”ยฐรซยงห†", + ["Improved Spellstone"] = "รฌยฃยผรซยฌยธรฌโ€žย รฌโ€”ยฐรซยงห†", + ["Improved Sprint"] = "รฌย โ€žรซย ยฅ รฌยงห†รฌยฃยผ รฌโ€”ยฐรซยงห†", + ["Improved Starfire"] = "รซยณโ€žรซยนโ€บ รญโ„ขโ€รฌโ€šยด รฌโ€”ยฐรซยงห†", + ["Improved Stoneclaw Totem"] = "รซล’โ‚ฌรฌยงโ‚ฌรฌยหœ รฌหœยฌรชยฐโ‚ฌรซยฏยธ", + ["Improved Stoneskin Totem"] = "รฌห†หœรญหœยธรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Improved Strength of Earth Totem"] = "รชยฐโ€ขรญโ„ขโ€รฌยหœ รญโ€ ย รญโ€ฆล“", + ["Improved Succubus"] = "รฌโ€žล“รญยยรซยฒโ€žรฌล ยค รฌโ€”ยฐรซยงห†", + ["Improved Sunder Armor"] = "รซยฐยฉรฌโ€“ยดรชยตยฌ รชยฐโ‚ฌรซยฅยดรชยธยฐ รฌโ€”ยฐรซยงห†", + ["Improved Taunt"] = "รซยโ€žรซยฐล“ รฌโ€”ยฐรซยงห†", + ["Improved Thorns"] = "รชยฐโ‚ฌรฌโ€นล“ รฌโ€”ยฐรซยงห†", + ["Improved Thunder Clap"] = "รฌยฒล“รซโ€˜ยฅรซยฒยผรซยยฝ รฌโ€”ยฐรซยงห†", + ["Improved Tranquility"] = "รญยโ€ฐรฌหœยจ รฌโ€”ยฐรซยงห†", + ["Improved Vampiric Embrace"] = "รญยยกรญหœห†รฌยหœ รฌโ€žย รซยฌยผ รฌโ€”ยฐรซยงห†", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Improved Vanish"] = "รฌโ€ ล’รซยฉยธ รฌโ€”ยฐรซยงห†", + ["Improved Voidwalker"] = "รซยณยดรฌยยดรซโ€œล“รฌโ€บล’รฌยปยค รฌโ€”ยฐรซยงห†", + ["Improved Windfury Weapon"] = "รฌลพยรฌโ€”ยฐรฌยหœ รซยฌยดรชยธยฐ", + ["Improved Wing Clip"] = "รซโ€šย รชยฐล“ รฌย ห†รซโ€นยจ รฌโ€”ยฐรซยงห†", + ["Improved Wrath"] = "รฌยฒล“รซยฒล’ รฌโ€”ยฐรซยงห†", + ["Incinerate"] = "รฌโ€ ล’รชยฐย", + ["Inferno"] = "รซยถห†รฌยงโ‚ฌรฌหœยฅ", + ["Initiative"] = "รฌโ€žย รฌย ล“ รชยณยตรชยฒยฉ", + ["Inner Fire"] = "รซโ€šยดรซยฉยดรฌยหœ รฌโ€”ยดรฌย โ€ข", + ["Inner Focus"] = "รซโ€šยดรซยฉยดรฌยหœ รฌยงโ€˜รฌยคโ€˜รซย ยฅ", + ["Innervate"] = "รฌโ€นย รฌโ€ ยรญโ€ขล“ รฌยนหœรฌล“ย ", + ["Insect Swarm"] = "รชยณยครฌยถยฉ รซโ€“ยผ", + ["Inspiration"] = "รฌโ€นย รฌยหœ รชยณโ€žรฌโ€นล“", + ["Instant Poison II"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ II", + ["Instant Poison III"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ III", + ["Instant Poison IV"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ IV", + ["Instant Poison V"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ V", + ["Instant Poison VI"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ VI", + ["Instant Poison"] = "รฌห†ล“รชยฐโ€ž รญลกยจรชยณยผ รซยโ€ฆ", + ["Intensity"] = "รชยฒยฉรซย ยฌ", + ["Intercept"] = "รซยดโ€ฐรฌโ€กโ€ž", + ["Intercept Stun"] = "รซยดโ€ฐรฌโ€กโ€ž รชยธยฐรฌย ห†", +-- ["Intervene"] = true, + ["Intimidating Shout"] = "รฌล“โ€žรญหœโ€˜รฌยหœ รฌโ„ขยธรฌยนยจ", + ["Intimidation"] = "รฌล“โ€žรญหœโ€˜", +-- ["Invisibility"] = true, + ["Iron Will"] = "รชยฐโ€ขรชยฑยดรญโ€ขล“ รฌยหœรฌยงโ‚ฌ", + ["Judgement of Command"] = "รฌยงโ‚ฌรญล“หœรฌยหœ รฌโ€นยฌรญล’ย", + ["Judgement of Justice"] = "รฌย โ€ขรฌยหœรฌยหœ รฌโ€นยฌรญล’ย", + ["Judgement of Light"] = "รซยนโ€บรฌยหœ รฌโ€นยฌรญล’ย", + ["Judgement of Righteousness"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Judgement of Wisdom"] = "รฌยงโ‚ฌรญหœล“รฌยหœ รฌโ€นยฌรญล’ย", + ["Judgement of the Crusader"] = "รฌโ€žยฑรฌย โ€žรฌโ€šยฌรฌยหœ รฌโ€นยฌรญล’ย", + ["Judgement"] = "รฌโ€นยฌรญล’ย", + ["Kick"] = "รซยฐล“รฌยฐยจรชยธยฐ", + ["Kick - Silenced"] = "รซยฐล“รฌยฐยจรชยธยฐ - รฌยนยจรซยฌยต", + ["Kidney Shot"] = "รชยธโ€ฐรฌโ€ ล’ รชยฐโ‚ฌรชยฒยฉ", +-- ["Kill Command"] = true, + ["Killer Instinct"] = "รฌโ€šยดรฌห†หœรฌยหœ รซยณยธรซล ยฅ", + ["Kodo Riding"] = "รฌยฝโ€รซยโ€ž รญฦ’โ‚ฌรชยธยฐ", +-- ["Lacerate"] = true, + ["Lash of Pain"] = "รชยณย รญโ€ ยตรฌยหœ รฌยฑโ€žรฌยฐย", + ["Last Stand"] = "รฌยตล“รญโ€บโ€žรฌยหœ รฌย โ‚ฌรญโ€ขยญ", + ["Lasting Judgement"] = "รฌหœยรฌโ€บยรญโ€ขล“ รฌโ€นยฌรญล’ย", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Lay on Hands"] = "รฌโ€นย รฌยหœ รฌยถโ€ขรซยณยต", + ["Leader of the Pack"] = "รซยฌยดรซยฆยฌรฌยหœ รฌลกยฐรซโ€˜ยรซยจยธรซยฆยฌ", + ["Leather"] = "รชยฐโ‚ฌรฌยฃยฝ", + ["Leatherworking"] = "รชยฐโ‚ฌรฌยฃยฝ รฌโ€žยธรชยณยต", + ["Lesser Heal"] = "รญโ€ขหœรชยธโ€ฐ รฌยนหœรฌล“ย ", + ["Lesser Healing Wave"] = "รญโ€ขหœรชยธโ€ฐ รฌยนหœรฌล“ย รฌยหœ รซยฌยผรชยฒยฐ", + ["Lesser Invisibility"] = "รญโ€ขหœรชยธโ€ฐ รญห†ยฌรซยชโ€ฆรญโ„ขโ€", + ["Lethal Shots"] = "รฌย โ€ขรซยฐโ‚ฌรญโ€ขล“ รฌโ€šยฌรชยฒยฉ", + ["Lethality"] = "รฌยนหœรซยชโ€ฆรฌฦ’ย", + ["Levitate"] = "รชยณยตรฌยคโ€˜ รซยถโ‚ฌรฌโ€“โ€˜", + ["Libram"] = "รฌโ€žยฑรฌโ€žล“", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย +-- ["Lifebloom"] = true, + ["Life Tap"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รฌย โ€žรญโ„ขหœ", + ["Lifegiving Gem"] = true, + ["Lightning Bolt"] = "รซยฒห†รชยฐล“ รญโ„ขโ€รฌโ€šยด", + ["Lightning Breath"] = "รซยฒห†รชยฐล“ รฌห†ยจรชยฒยฐ", + ["Lightning Mastery"] = "รซยฒห†รชยฐล“ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Lightning Reflexes"] = "รซยฒห†รชยฐล“รชยฐโ„ขรฌยโ‚ฌ รซยฐหœรฌโ€šยฌ รฌโ€นย รชยฒยฝ", + ["Lightning Shield"] = "รซยฒห†รชยฐล“ รซยณยดรญหœยธรซยงโ€ฐ", + ["Lightwell Renew"] = "รซยนโ€บรฌฦ’หœรฌยหœ รฌโ€ ล’รฌฦ’ย", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Lightwell"] = "รซยนโ€บรฌฦ’หœ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Lockpicking"] = "รฌลพยรซยฌยผรฌโ€กย  รซโ€ยฐรชยธยฐ", + ["Long Daze"] = "รฌหœยครซลพล“ รซยฉยรญโ€ขยดรฌยงย", + ["Mace Specialization"] = "รซโ€˜โ€รชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Mace Stun Effect"] = "รฌยฒย รญโ€กยด รชยธยฐรฌย ห† รญลกยจรชยณยผ", + ["Mage Armor"] = "รซยงห†รซยฒโ€ขรฌโ€šยฌ รชยฐโ€˜รฌหœยท", + ["Magma Totem"] = "รฌลกยฉรฌโ€ขโ€ รญโ€ ย รญโ€ฆล“", + ["Mail"] = "รฌโ€šยฌรฌล ยฌ", +-- ["Maim"] = true, + ["Malice"] = "รฌโ€บยรญโ€ขล“", + ["Mana Burn"] = "รซยงห†รซโ€šหœ รฌโ€”ยฐรฌโ€ ล’", + ["Mana Shield"] = "รซยงห†รซโ€šหœ รซยณยดรญหœยธรซยงโ€ฐ", + ["Mana Spring Totem"] = "รซยงห†รซโ€šหœรฌฦ’หœ รญโ€ ย รญโ€ฆล“", + ["Mana Tide Totem"] = "รซยงห†รซโ€šหœ รญโ€ขยดรฌยยผ รญโ€ ย รญโ€ฆล“", + ["Mangle"] = "รฌยงโ€œรฌยยดรชยธยฐรชยธยฐ", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌยงโ€ขรญโ€˜ล“", + ["Martyrdom"] = "รญโ€”ล’รฌโ€นย ", +-- ["Mass Dispel"] = true, + ["Master Demonologist"] = "รฌโ€ขโ€ฆรซย ยนรฌห†ย รฌยหœ รซล’โ‚ฌรชยฐโ‚ฌ", + ["Master Summoner"] = "รฌโ€ ล’รญโ„ขหœรฌยหœ รซล’โ‚ฌรชยฐโ‚ฌ", + ["Master of Deception"] = "รฌโ€ ยรฌลพโ€žรฌห†หœรฌยหœ รซล’โ‚ฌรชยฐโ‚ฌ", + ["Maul"] = "รญโ€บโ€žรซย ยครฌยนหœรชยธยฐ", + ["Mechanostrider Piloting"] = "รชยธยฐรชยณโ€žรญฦ’โ‚ฌรฌยกยฐ รฌยกยฐรฌยขโ€ฆ", + ["Meditation"] = "รซยชโ€ฆรฌฦ’ย", + ["Melee Specialization"] = "รชยทยผรฌย โ€˜ รซยฌยดรชยธยฐ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Mend Pet"] = "รซยโ„ขรซยฌยผ รฌยนหœรซยฃล’", + ["Mental Agility"] = "รซยงห†รฌยล’รฌยหœ รชยธยฐรซยฏยผรญโ€ขยจ", + ["Mental Strength"] = "รฌย โ€ขรฌโ€นย รซย ยฅ", + ["Mind Blast"] = "รฌย โ€ขรฌโ€นย  รซยถโ€žรฌโ€”ยด", + ["Mind Control"] = "รฌย โ€ขรฌโ€นย  รฌยงโ‚ฌรซยฐยฐ", + ["Mind Flay"] = "รฌย โ€ขรฌโ€นย รฌยหœ รฌยฑโ€žรฌยฐย", + ["Mind Soothe"] = "รญยโ€ฐรฌย โ€ข", + ["Mind Vision"] = "รซยงห†รฌยล’รฌยหœ รซห†ห†", + ["Mind-numbing Poison II"] = "รฌย โ€ขรฌโ€นย  รซยงห†รซยนโ€ž รซยโ€ฆ II", + ["Mind-numbing Poison III"] = "รฌย โ€ขรฌโ€นย  รซยงห†รซยนโ€ž รซยโ€ฆ III", + ["Mind-numbing Poison"] = "รฌย โ€ขรฌโ€นย  รซยงห†รซยนโ€ž รซยโ€ฆ", + ["Mining"] = "รฌยฑโ€žรชยดโ€˜", +-- ["Misdirection"] = true, + ["Mocking Blow"] = "รซยโ€žรซยฐล“รฌยหœ รฌยยผรชยฒยฉ", +-- ["Molten Armor"] = true, + ["Mongoose Bite"] = "รฌโ€šยดรฌยพยกรฌยยดรฌยหœ รฌยยดรซยนยจ", + ["Monster Slaying"] = "รซยชยฌรฌล ยครญโ€žยฐ รฌโ€šยฌรซฦ’ยฅรฌห†ย ", + ["Moonfire"] = "รซโ€นยฌรซยนโ€บ รฌโ€žยฌรชยดโ€˜", + ["Moonfury"] = "รซโ€นยฌรฌยหœ รซยถโ€žรซโ€ฆยธ", + ["Moonglow"] = "รซโ€นยฌรซยนโ€บ", + ["Moonkin Aura"] = "รซโ€นยฌรซยนโ€บรฌโ€ขยผรฌห†หœ รฌหœยครซยยผ", + ["Moonkin Form"] = "รซโ€นยฌรซยนโ€บรฌโ€ขยผรฌห†หœ รซยณโ‚ฌรฌโ€นย ", + ["Mortal Shots"] = "รฌยฃยฝรฌยล’รฌยหœ รฌโ€šยฌรชยฒยฉ", + ["Mortal Strike"] = "รฌยฃยฝรฌยล’รฌยหœ รฌยยผรชยฒยฉ", + ["Multi-Shot"] = "รฌยยผรฌย ล“ รฌโ€šยฌรชยฒยฉ", + ["Murder"] = "รญโ€ขโ„ขรฌโ€šยด", +-- ["Mutilate"] = true, + ["Natural Armor"] = "รซยฌยดรฌโ€กย  รชยฐโ‚ฌรฌยฃยฝ", + ["Natural Shapeshifter"] = "รซยณโ‚ฌรฌโ€นย รฌยหœ รซล’โ‚ฌรชยฐโ‚ฌ", + ["Natural Weapons"] = "รฌลพยรฌโ€”ยฐรฌยหœ รซยฌยดรชยธยฐ", + ["Nature Resistance Totem"] = "รฌลพยรฌโ€”ยฐ รฌย โ‚ฌรญโ€ขยญ รญโ€ ย รญโ€ฆล“", + ["Nature Resistance"] = "รฌลพยรฌโ€”ยฐ รซยงห†รซยฒโ€ข รฌย โ‚ฌรญโ€ขยญ", + ["Nature's Focus"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌย โ€ขรฌโ€นย  รฌยงโ€˜รฌยคโ€˜", + ["Nature's Grace"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌยโ‚ฌรญหœล“", + ["Nature's Grasp"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌโ€ ยรฌโ€ขโ€žรชยทโ‚ฌ", + ["Nature's Reach"] = "รฌลพยรฌโ€”ยฐรฌยหœ รญโ€ฆล’รซโ€˜ยรซยฆยฌ", + ["Nature's Swiftness"] = "รฌลพยรฌโ€”ยฐรฌยหœ รฌโ€นย รฌโ€ ยรญโ€ขยจ", + ["Nightfall"] = "รฌยยผรซยชยฐ", + ["Omen of Clarity"] = "รฌยฒยญรซยชโ€ฆรฌยหœ รฌย โ€žรฌยกยฐ", + ["One-Handed Axes"] = "รญโ€ขล“รฌโ€ ย รซยโ€žรซยยผ", + ["One-Handed Maces"] = "รญโ€ขล“รฌโ€ ย รฌยฒย รญโ€กยด", + ["One-Handed Swords"] = "รญโ€ขล“รฌโ€ ย รชยฒโ‚ฌ", + ["One-Handed Weapon Specialization"] = "รญโ€ขล“รฌโ€ ย รซยฌยดรชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Opening - No Text"] = "รฌโ€”ยดรชยธยฐ", + ["Opening"] = "รฌโ€”ยดรชยธยฐ", + ["Opportunity"] = "รชยธยฐรญลกล’ รญยยฌรฌยฐยฉ", + ["Overpower"] = "รฌย ล“รฌโ€ขโ€ข", +-- ["Pain Suppression"] = true, + ["Paranoia"] = "รซยงยรฌฦ’ย", + ["Parry"] = "รซยฌยดรชยธยฐ รซยงโ€ฐรชยธยฐ", + ["Pathfinding"] = "รชยธยธ รฌยฐยพรชยธยฐ", + ["Perception"] = "รฌยงยรชยดโ‚ฌรซย ยฅ", + ["Permafrost"] = "รฌหœยรชยตยฌ รชยฒยฐรซยนโ„ข", + ["Pet Aggression"] = "รฌโ€ขยผรฌห†หœรฌยหœ รชยณยตรชยฒยฉรฌโ€žยฑ", + ["Pet Hardiness"] = "รฌโ€ขยผรฌห†หœรฌยหœ รชยฐโ€ขรฌยยธรญโ€ขยจ", + ["Pet Recovery"] = "รฌโ€ขยผรฌห†หœรฌยหœ รญลกล’รซยณยตรซย ยฅ", + ["Pet Resistance"] = "รฌโ€ขยผรฌห†หœรฌยหœ รฌย โ‚ฌรญโ€ขยญรซย ยฅ", + ["Phase Shift"] = "รฌล“โ€žรฌฦ’ย รซยณโ‚ฌรญโ„ขโ€", + ["Pick Lock"] = "รฌลพยรซยฌยผรฌโ€กย  รซโ€ยฐรชยธยฐ", + ["Pick Pocket"] = "รญโ€บโ€รฌยนหœรชยธยฐ", + ["Piercing Howl"] = "รซโ€šย รฌยนยดรซยกล“รฌลกยด รชยณย รญโ€ขยจ", + ["Piercing Ice"] = "รฌโ€šยฌรซยฌยดรฌยนหœรซล โ€ รซฦ’โ€ฐรชยธยฐ", + ["Plate Mail"] = "รญล’ยรชยธห† รชยฐโ€˜รฌหœยท", + ["Poison Cleansing Totem"] = "รซยโ€ฆ รฌย โ€ขรญโ„ขโ€ รญโ€ ย รญโ€ฆล“", + ["Poisons"] = "รซยโ€ฆ รฌยกยฐรฌย ล“", + ["Polearm Specialization"] = "รฌลพยฅรฌยฐยฝรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Polearms"] = "รฌลพยฅรฌยฐยฝรซยฅหœ", + ["Polymorph"] = "รซยณโ‚ฌรฌยยด", + ["Polymorph: Pig"] = "รซยณโ‚ฌรฌยยด: รซยยผรฌยงโ‚ฌ", + ["Polymorph: Turtle"] = "รซยณโ‚ฌรฌยยด: รชยฑยฐรซยถยรฌยยด", + ["Portal: Darnassus"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รซโ€นยครซยฅยดรซโ€šหœรฌโ€žล“รฌล ยค", + ["Portal: Ironforge"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รฌโ€ขโ€žรฌยยดรฌโ€“ยธรญยยฌรฌยงโ‚ฌ", + ["Portal: Orgrimmar"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รฌหœยครชยทยธรซยฆยฌรซยงห†", + ["Portal: Stormwind"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รฌล ยครญโ€ ยฐรฌล“ห†รซโ€œล“", + ["Portal: Thunder Bluff"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รฌยยฌรซยโ€ รซยธโ€รซลธยฌรญโ€โ€ž", + ["Portal: Undercity"] = "รฌยฐยจรฌโ€บยรฌยหœ รซยฌยธ: รฌโ€“ยธรซยโ€รฌโ€นล“รญโ€นยฐ", + ["Pounce Bleed"] = "รฌโ€ขโ€รฌล ยต รญโ€ยผรญโ€ขยด", + ["Pounce"] = "รฌโ€ขโ€รฌล ยต", + ["Power Infusion"] = "รซยงห†รซย ยฅ รฌยฃยผรฌลพโ€ฆ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Power Word: Fortitude"] = "รฌโ€นย รฌยหœ รชยถล’รซล ยฅ: รฌยยธรซโ€šยด", + ["Power Word: Shield"] = "รฌโ€นย รฌยหœ รชยถล’รซล ยฅ: รซยณยดรญหœยธรซยงโ€ฐ", + ["Prayer of Fortitude"] = "รฌยยธรซโ€šยดรฌยหœ รชยธยฐรฌโ€บย", + ["Prayer of Healing"] = "รฌยนหœรฌล“ย รฌยหœ รชยธยฐรฌโ€บย", +-- ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"] = "รฌโ€ขโ€รญยโ€˜ รซยณยดรญหœยธรฌยหœ รชยธยฐรฌโ€บย", + ["Prayer of Spirit"] = "รฌย โ€ขรฌโ€นย รซย ยฅรฌยหœ รชยธยฐรฌโ€บย", + ["Precision"] = "รฌย โ€ขรซยฐโ‚ฌรญโ€ขยจ", + ["Predatory Strikes"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รญยยฌรฌโ€นยรฌลพย", + ["Premeditation"] = "รฌโ€šยฌรฌย โ€žรชยณโ€žรญลกย", + ["Preparation"] = "รซยงห†รฌยล’รชยฐโ‚ฌรฌยงย", + ["Presence of Mind"] = "รซฦ’โ€ฐรฌย โ€ข", + ["Primal Fury"] = "รฌโ€ขยผรฌห†หœรฌยหœ รซยถโ€žรซโ€ฆยธ", + ["Prowl"] = "รฌห†ยจรชยธยฐ", + ["Psychic Scream"] = "รฌหœยรญหœยผรฌยหœ รฌย ห†รชยทล“", + ["Pummel"] = "รฌลพยรซยฃยจ รชยณยตรชยฒยฉ", + ["Purge"] = "รฌย โ€ขรญโ„ขโ€", + ["Purification"] = "รฌโ€นยฌรฌโ€นย รฌยหœ รฌย โ€ขรญโ„ขโ€", + ["Purify"] = "รฌห†ล“รญโ„ขโ€", + ["Pursuit of Justice"] = "รฌโ€นยฌรญล’ยรฌยหœ รฌยถโ€รชยฒยฉ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Pyroblast"] = "รซยถห†รซยยฉรฌยยด รฌลพโ€˜รฌโ€”ยด", + ["Pyroclasm"] = "รญโ„ขโ€รฌโ€”ยผ รญล’ล’รฌโ€”ยด", + ["Quick Shots"] = "รฌโ€นย รฌโ€ ย รฌโ€šยฌรชยฒยฉ", + ["Quickness"] = "รซยฏยผรฌยฒยฉ", + ["Rain of Fire"] = "รซยถห†รฌยหœ รซยนโ€ž", + ["Rake"] = "รชยฐห†รญโ‚ฌยด รซยฐล“รญโ€ ยฑ", +-- ["Rampage"] = true, + ["Ram Riding"] = "รฌโ€šยฐรฌโ€“โ€˜ รญฦ’โ‚ฌรชยธยฐ", + ["Ranged Weapon Specialization"] = "รฌโ€บยรชยฑยฐรซยฆยฌ รซยฌยดรชยธยฐ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Rapid Concealment"] = "รฌยโ‚ฌรฌโ€นย รฌห†ย  รฌโ€”ยฐรซยงห†", + ["Rapid Fire"] = "รฌโ€ ยรฌโ€šยฌ", + ["Raptor Riding"] = "รซลพยฉรญโ€žยฐ รญฦ’โ‚ฌรชยธยฐ", + ["Raptor Strike"] = "รซลพยฉรญโ€žยฐรฌยหœ รฌยยผรชยฒยฉ", + ["Ravage"] = "รฌโ€ขยฝรญฦ’ห†", + ["Readiness"] = "รซยงล’รซยฐหœรฌยหœ รฌยคโ‚ฌรซยนโ€ž", + ["Rebirth"] = "รญโ„ขหœรฌฦ’ย", + ["Reckless Charge"] = "รซยฌยดรซยชยจรญโ€ขล“ รซยล’รฌยงโ€ž", + ["Recklessness"] = "รซยฌยดรซยชยจรญโ€ขล“ รญยยฌรฌฦ’ย", + ["Reckoning"] = "รฌยงโ€ขรซยฒล’", + ["Redemption"] = "รชยตยฌรฌโ€บย", + ["Redoubt"] = "รซยณยดรซยฃยจ", + ["Reflection"] = "รซยฐหœรฌโ€šยฌ", + ["Regeneration"] = "รฌลพยฌรฌฦ’ยรซย ยฅ", + ["Regrowth"] = "รฌลพยฌรฌฦ’ย", + ["Reincarnation"] = "รฌล“ยครญลกล’", + ["Rejuvenation"] = "รญลกล’รซยณยต", + ["Relentless Strikes"] = "รชยฐโ‚ฌรญหœยนรญโ€ขล“ รฌยยผรชยฒยฉ", + ["Remorseless"] = "รซฦ’โ€ฐรญหœยนรญโ€ขยจ", + ["Remorseless Attacks"] = "รซฦ’โ€ฐรญหœยนรญโ€ขยจ", + ["Remove Curse"] = "รฌย โ‚ฌรฌยฃยผ รญโ€ขยดรฌย ล“", + ["Remove Insignia"] = "รชยณโ€žรชยธโ€ฐรฌลพยฅ รฌย ล“รชยฑยฐ", + ["Remove Lesser Curse"] = "รญโ€ขหœรชยธโ€ฐ รฌย โ‚ฌรฌยฃยผ รญโ€ขยดรฌย ล“", + ["Rend"] = "รซยถโ€žรฌโ€กโ€ž", + ["Renew"] = "รฌโ€ ล’รฌฦ’ย", + ["Repentance"] = "รฌยฐยธรญลกล’", + ["Resurrection"] = "รซยถโ‚ฌรญโ„ขล“", + ["Retaliation"] = "รซยณยดรซยณยต", + ["Retribution Aura"] = "รฌยโ€˜รซยณยดรฌยหœ รฌหœยครซยยผ", + ["Revenge Stun"] = "รซยณยตรฌห†หœ รชยธยฐรฌย ห†", + ["Revenge"] = "รซยณยตรฌห†หœ", + ["Reverberation"] = "รฌโ€šยฐรฌลกยธรซยฆยผ", + ["Revive Pet"] = "รฌโ€ขยผรฌห†หœ รซยหœรฌโ€šยดรซยฆยฌรชยธยฐ", +-- ["Righteous Defense"] = true, + ["Righteous Fury"] = "รฌย โ€ขรฌยหœรฌยหœ รชยฒยฉรซโ€ฆยธ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Rip"] = "รซยโ€žรซย ยครซโ€šยดรชยธยฐ", + ["Riposte"] = "รซยฐหœรชยฒยฉ", + ["Ritual of Doom Effect"] = "รญล’ล’รซยฉยธรฌยหœ รฌยหœรฌโ€นย", + ["Ritual of Doom"] = "รญล’ล’รซยฉยธรฌยหœ รฌยหœรฌโ€นย", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = "รฌโ€ ล’รญโ„ขหœ รฌยหœรฌโ€นย", + ["Rockbiter Weapon"] = "รซล’โ‚ฌรฌยงโ‚ฌรฌยหœ รซยฌยดรชยธยฐ", + ["Rogue Passive"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Rough Sharpening Stone"] = "รฌยกยฐรฌลพยกรญโ€ขล“ รฌห†ยซรซยล’", + ["Ruin"] = "รซยถโ€ขรชยดยด", + ["Rupture"] = "รญล’ล’รฌโ€”ยด", + ["Ruthlessness"] = "รซยฌยดรฌย โ€ขรญโ€ขยจ", + ["Sacrifice"] = "รญยยฌรฌฦ’ย", + ["Safe Fall"] = "รซโ€šโ„ขรซยฒโ€ข", + ["Sanctity Aura"] = "รชยณย รชยฒยฐรฌยหœ รฌหœยครซยยผ", + ["Sap"] = "รชยธยฐรฌย ห†รฌโ€นล“รญโ€šยครชยธยฐ", + ["Savage Fury"] = "รซยงยนรซย ยฌรญโ€ขล“ รชยฒยฉรซโ€ฆยธ", + ["Savage Strikes"] = "รฌโ€ขยผรฌฦ’ยรฌยหœ รฌยยผรชยฒยฉ", + ["Scare Beast"] = "รฌโ€ขยผรฌห†หœ รชยฒยรฌยฃยผรชยธยฐ", + ["Scatter Shot"] = "รฌโ€šยฐรญฦ’โ€ž รฌโ€šยฌรชยฒยฉ", + ["Scorch"] = "รซยถห†รญฦ’ล“รฌลกยฐรชยธยฐ", + ["Scorpid Poison"] = "รฌย โ€žรชยฐห†รซยโ€ฆ", + ["Scorpid Sting"] = "รฌย โ€žรชยฐห† รฌยยรชยธยฐ", + ["Screech"] = "รซโ€šย รฌยนยดรซยกล“รฌลกยด รฌลกยธรฌยล’รฌโ€ ล’รซยฆยฌ", + ["Seal Fate"] = "รฌลกยดรซยชโ€ฆรฌยหœ รซโ€šโ„ขรฌยยธ", +-- ["Seal of Blood"] = true, + ["Seal of Command"] = "รฌยงโ‚ฌรญล“หœรฌยหœ รซยฌยธรฌลพยฅ", + ["Seal of Justice"] = "รฌโ€นยฌรญล’ยรฌยหœ รซยฌยธรฌลพยฅ", + ["Seal of Light"] = "รซยนโ€บรฌยหœ รซยฌยธรฌลพยฅ", + ["Seal of Righteousness"] = "รฌย โ€ขรฌยหœรฌยหœ รซยฌยธรฌลพยฅ", + ["Seal of Wisdom"] = "รฌยงโ‚ฌรญหœล“รฌยหœ รซยฌยธรฌลพยฅ", + ["Seal of the Crusader"] = "รฌโ€žยฑรฌย โ€žรฌโ€šยฌรฌยหœ รซยฌยธรฌลพยฅ", +-- ["Seal of Vengeance"] = true, + ["Searing Light"] = "รญฦ’โ‚ฌรฌหœยครซยฅยดรซล โ€ รซยนโ€บ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Searing Pain"] = "รซยถห†รญฦ’โ‚ฌรซล โ€ รชยณย รญโ€ ยต", + ["Searing Totem"] = "รซยถห†รญฦ’โ‚ฌรซล โ€ รญโ€ ย รญโ€ฆล“", +-- ["Second Wind"] = true, + ["Seduction"] = "รญหœโ€žรญหœยน", +-- ["Seed of Corruption"] = true, + ["Sense Demons"] = "รฌโ€ขโ€ฆรซยงห† รชยฐยรฌยงโ‚ฌ", + ["Sense Undead"] = "รฌโ€“ยธรซยยฐรซโ€œล“ รชยฐยรฌยงโ‚ฌ", + ["Sentry Totem"] = "รชยฐยรฌโ€นล“รฌยหœ รญโ€ ย รญโ€ฆล“", + ["Serpent Sting"] = "รซยโ€ฆรฌโ€šยฌ รฌยยรชยธยฐ", + ["Setup"] = "รฌโ€šยฌรฌย โ€ž รฌยคโ‚ฌรซยนโ€ž", + ["Shackle Undead"] = "รฌโ€“ยธรซยยฐรซโ€œล“ รฌโ€ ยรซยฐโ€ข", + ["Shadow Affinity"] = "รฌโ€ขโ€รญยโ€˜ รซยงห†รซยฒโ€ข รฌยนล“รญโ„ขโ€", + ["Shadow Bolt"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รญโ„ขโ€รฌโ€šยด", + ["Shadow Focus"] = "รฌโ€ขโ€รญยโ€˜ รซยงห†รซยฒโ€ข รฌยงโ€˜รฌยคโ€˜", + ["Shadow Mastery"] = "รฌโ€ขโ€รญยโ€˜ รซยงห†รซยฒโ€ข รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Shadow Protection"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รซยณยดรญหœยธ", + ["Shadow Reach"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รญโ€ฆล’รซโ€˜ยรซยฆยฌ", + ["Shadow Resistance Aura"] = "รฌโ€ขโ€รญยโ€˜ รฌย โ‚ฌรญโ€ขยญรฌยหœ รฌหœยครซยยผ", + ["Shadow Resistance"] = "รฌโ€ขโ€รญยโ€˜ รซยงห†รซยฒโ€ข รฌย โ‚ฌรญโ€ขยญ", + ["Shadow Trance"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รซยฌยดรฌโ€ขโ€žรฌยงโ‚ฌรชยฒยฝ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Shadow Vulnerability"] = "รฌโ€ขโ€รญยโ€˜ รฌย โ‚ฌรญโ€ขยญรซย ยฅ รฌโ€ขยฝรญโ„ขโ€", + ["Shadow Ward"] = "รฌโ€ขโ€รญยโ€˜รชยณโ€ž รฌห†หœรญหœยธ", + ["Shadow Weaving"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รซยงยครซโ€œยญ", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รชยถล’รซล ยฅ: รชยณย รญโ€ ยต", + ["Shadowburn"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รฌโ€”ยฐรฌโ€ ล’", +-- ["Shadowfiend"] = true, + ["Shadowform"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รญหœโ€ขรฌฦ’ย", +-- ["Shadowfury"] = true, + ["Shadowguard"] = "รฌโ€“ยดรซโ€˜ย รฌยหœ รฌห†หœรญหœยธ", + ["Shadowmeld Passive"] = "รชยทยธรซยฆยผรฌลพย รฌห†ยจรชยธยฐ", + ["Shadowmeld"] = "รชยทยธรซยฆยผรฌลพย รฌห†ยจรชยธยฐ", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = "รซโ€šย รฌยนยดรซยกล“รฌลกยด รซยฐล“รญโ€ ยฑ", + ["Shatter"] = "รฌโ€šยฐรฌโ€šยฐรฌยกยฐรชยฐย", + ["Sheep"] = "รซยณโ‚ฌรฌยยด", + ["Shell Shield"] = "รชยปยรฌยงห† รซยฐยฉรญล’ยจ", + ["Shield Bash"] = "รซยฐยฉรญล’ยจ รชยฐโ‚ฌรชยฒยฉ", + ["Shield Bash - Silenced"] = "รซยฐยฉรญล’ยจ รชยฐโ‚ฌรชยฒยฉ - รฌยนยจรซยฌยต", + ["Shield Block"] = "รซยฐยฉรญล’ยจ รซยงโ€ฐรชยธยฐ", + ["Shield Slam"] = "รซยฐยฉรญล’ยจ รซยฐโ‚ฌรฌยณยรซโ€šยดรชยธยฐ", + ["Shield Specialization"] = "รซยฐยฉรญล’ยจ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Shield Wall"] = "รซยฐยฉรญล’ยจรฌยหœ รซยฒยฝ", + ["Shield"] = "รซยฐยฉรญล’ยจ", +-- ["Shiv"] = true, + ["Shoot Bow"] = "รญโ„ขล“ รซยฐล“รฌโ€šยฌ", + ["Shoot Crossbow"] = "รฌโ€žยรชยถย รซยฐล“รฌโ€šยฌ", + ["Shoot Gun"] = "รฌยดย รซยฐล“รฌโ€šยฌ", + ["Shoot"] = "รซยงห†รซยฒโ€ขรซยดโ€ฐ รซยฐล“รฌโ€šยฌ", + ["Shred"] = "รฌย ห†รซโ€นยจ", + ["Silence"] = "รฌยนยจรซยฌยต", +-- ["Silencing Shot"] = true, + ["Silent Resolve"] = "รซยฌยดรฌโ€“ยธรฌยหœ รชยฒยฐรฌโ€นยฌ", + ["Sinister Strike"] = "รฌโ€šยฌรฌโ€ขโ€ฆรญโ€ขล“ รฌยยผรชยฒยฉ", + ["Siphon Life"] = "รฌฦ’ยรซยชโ€ฆรซย ยฅ รฌยฐยฉรฌยทยจ", + ["Skinning"] = "รซยฌยดรซโ€˜ยรฌยงห†", + ["Slam"] = "รชยฒยฉรซยล’", + ["Sleep"] = "รฌห†หœรซยฉยด", + ["Slice and Dice"] = "รซโ€šล“รซยโ€žรฌยงห†", +-- ["Slow"] = true, + ["Slow Fall"] = "รฌย โ‚ฌรฌโ€ ย รซโ€šโ„ขรญโ€ขหœ", + ["Smelting"] = "รฌย ล“รซย ยจรฌห†ย ", + ["Smite"] = "รฌโ€žยฑรฌล ยครซลธยฌรฌลกยด รฌยยผรชยฒยฉ", +-- ["Snake Trap"] = true, + ["Solid Sharpening Stone"] = "รชยฒยฌรชยณย รญโ€ขล“ รฌห†ยซรซยล’", + ["Soothe Animal"] = "รซยโ„ขรซยฌยผ รซโ€นยฌรซลพหœรชยธยฐ", + ["Soothing Kiss"] = "รฌล“ย รญหœยนรฌยหœ รฌลพโ€ฆรซยงลพรฌยถยค", + ["Soul Fire"] = "รฌหœยรญหœยผรฌยหœ รซยถห†รชยฝฦ’", + ["Soul Link"] = "รฌหœยรญหœยผรฌยหœ รชยณย รซยฆยฌ", + ["Soul Siphon"] = "รฌหœยรญหœยผ รฌยฐยฉรฌยทยจ", +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"] = "รฌหœยรญหœยผรฌโ€žย รซยถโ‚ฌรญโ„ขล“", + ["Spell Lock"] = "รฌยฃยผรซยฌยธ รฌลพย รชยธห†", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"] = "รฌยฃยผรซยฌยธ รฌห†หœรญหœยธ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Spirit Bond"] = "รฌย โ€ขรฌโ€นย รฌยหœ รชยฒยฐรฌโ€ ย", + ["Spirit Tap"] = "รฌย โ€ขรฌโ€นย รซย ยฅ รซห†โ€žรฌยถล“", + ["Spirit of Redemption"] = "รชยตยฌรฌโ€บยรฌยหœ รฌหœยรญหœยผ", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = "รฌหœยรฌย ยรฌยยธ รฌยงโ€˜รฌยคโ€˜รซย ยฅ", + ["Spiritual Guidance"] = "รฌหœยรญหœยผรฌยหœ รชยธยธรฌลพยกรฌยยด", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Spiritual Healing"] = "รฌหœยรญหœยผรฌยหœ รฌยนหœรฌล“ย ", + ["Sprint"] = "รฌย โ€žรซย ยฅ รฌยงห†รฌยฃยผ", +-- ["Stance Mastery"] = true, + ["Starfire"] = "รซยณโ€žรซยนโ€บ รญโ„ขโ€รฌโ€šยด", + ["Starfire Stun"] = "รซยณโ€žรซยนโ€บ รญโ„ขโ€รฌโ€šยด รชยธยฐรฌย ห†", + ["Starshards"] = "รซยณโ€žรฌยกยฐรชยฐย", + ["Staves"] = "รฌยงโ‚ฌรญล’ยกรฌยยด", +-- ["Steady Shot"] = true, + ["Stealth"] = "รฌยโ‚ฌรฌโ€นย ", + ["Stoneclaw Totem"] = "รซยล’รซยฐล“รญโ€ ยฑ รญโ€ ย รญโ€ฆล“", + ["Stoneform"] = "รฌโ€žยรญโ„ขโ€", + ["Stoneskin Totem"] = "รซยล’รชยฐโ‚ฌรฌยฃยฝ รญโ€ ย รญโ€ฆล“", + ["Stormstrike"] = "รญยยญรญโ€™ยรฌยหœ รฌยยผรชยฒยฉ", + ["Strength of Earth Totem"] = "รซล’โ‚ฌรฌยงโ‚ฌรซย ยฅ รญโ€ ย รญโ€ฆล“", + ["Stuck"] = "รชยณย รซยฆยฝ รฌฦ’ยรญฦ’ล“ รซยฒโ€”รฌโ€“ยดรซโ€šหœรชยธยฐ", + ["Subtlety"] = "รฌหœยรญหœยผรฌยหœ รชยธยธรฌลพยกรฌยยด", + ["Suffering"] = "รชยณย รญโ€ ยต", + ["Summon Charger"] = "รชยตยฐรซยงห† รฌโ€ ล’รญโ„ขหœ", + ["Summon Dreadsteed"] = "รชยณยตรญยยฌรซยงห† รฌโ€ ล’รญโ„ขหœ", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"] = "รฌยงโ‚ฌรฌหœยฅรฌโ€šยฌรซฦ’ยฅรชยฐล“ รฌโ€ ล’รญโ„ขหœ", + ["Summon Felsteed"] = "รฌยงโ‚ฌรฌหœยฅรซยงห† รฌโ€ ล’รญโ„ขหœ", + ["Summon Imp"] = "รฌลพโ€žรญโ€โ€ž รฌโ€ ล’รญโ„ขหœ", + ["Summon Succubus"] = "รฌโ€žล“รญยยรซยฒโ€žรฌล ยค รฌโ€ ล’รญโ„ขหœ", + ["Summon Voidwalker"] = "รซยณยดรฌยยดรซโ€œล“รฌโ€บล’รฌยปยค รฌโ€ ล’รญโ„ขหœ", + ["Summon Warhorse"] = "รชยตยฐรซยงห† รฌโ€ ล’รญโ„ขหœ", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"] = "รซยฐยฉรฌโ€“ยดรชยตยฌ รชยฐโ‚ฌรซยฅยดรชยธยฐ", + ["Suppression"] = "รฌโ€“ยตรฌย ล“", + ["Surefooted"] = "รฌยนยจรฌยฐยฉรญโ€ขยจ", + ["Survivalist"] = "รฌฦ’ยรฌยกยดรฌยหœ รซล’โ‚ฌรชยฐโ‚ฌ", + ["Sweeping Strikes"] = "รญล“ยฉรฌโ€œยธรชยธยฐ รฌยยผรชยฒยฉ", + ["Swiftmend"] = "รฌโ€นย รฌโ€ ยรญโ€ขล“ รฌยนหœรฌล“ย ", + ["Swipe"] = "รญล“หœรซโ€˜หœรซลธยฌรฌยนหœรชยธยฐ", + ["Sword Specialization"] = "รซยโ€žรชยฒโ‚ฌรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Tactical Mastery"] = "รฌย โ€žรฌห†ย  รฌห†โ„ขรซย ยจ", + ["Tainted Blood"] = "รฌโ€“ยผรซยฃยฉรฌยงโ€ž รญโ€ยผ", + ["Tailoring"] = "รฌลพยฌรซยดโ€ฐรฌห†ย ", + ["Tame Beast"] = "รฌโ€ขยผรฌห†หœ รชยธยธรซโ€œยครฌยยดรชยธยฐ", + ["Tamed Pet Passive"] = "", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Taunt"] = "รซยโ€žรซยฐล“", + ["Teleport: Darnassus"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รซโ€นยครซยฅยดรซโ€šหœรฌโ€žล“รฌล ยค", + ["Teleport: Ironforge"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รฌโ€ขโ€žรฌยยดรฌโ€“ยธรญยยฌรฌยงโ‚ฌ", + ["Teleport: Moonglade"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รซโ€นยฌรฌยหœ รฌห†ยฒ", + ["Teleport: Orgrimmar"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รฌหœยครชยทยธรซยฆยฌรซยงห†", + ["Teleport: Stormwind"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รฌล ยครญโ€ ยฐรฌล“ห†รซโ€œล“", + ["Teleport: Thunder Bluff"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รฌยยฌรซยโ€ รซยธโ€รซลธยฌรญโ€โ€ž", + ["Teleport: Undercity"] = "รฌห†ล“รชยฐโ€žรฌยยดรซยโ„ข: รฌโ€“ยธรซยโ€รฌโ€นล“รญโ€นยฐ", +-- ["The Beast Within"] = true, + ["The Human Spirit"] = "รฌยยธรชยฐโ€žรฌยหœ รฌย โ€ขรฌโ€นย รซย ยฅ", + ["Thick Hide"] = "รซโ€˜ยรชยบยผรฌลกยด รชยฐโ‚ฌรฌยฃยฝ", + ["Thorns"] = "รชยฐโ‚ฌรฌโ€นล“", + ["Throw"] = "รญห†ยฌรฌยฒโ„ข", + ["Throwing Specialization"] = "รญห†ยฌรฌยฒโ„ขรฌห†ย  รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Throwing Weapon Specialization"] = "รญห†ยฌรฌยฒโ„ข รซยฌยดรชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Thrown"] = "รญห†ยฌรฌยฒโ„ข", + ["Thunder Clap"] = "รฌยฒล“รซโ€˜ยฅรซยฒยผรซยยฝ", + ["Thundering Strikes"] = "รฌลกยฐรซย ห†รฌยหœ รฌยยผรชยฒยฉ", + ["Thunderstomp"] = "รฌยฒล“รซโ€˜ยฅ รซยฐล“รชยตยฌรซยฅยดรชยธยฐ", + ["Tidal Focus"] = "รญโ€ขยดรฌยยผรฌยหœ รฌยงโ€˜รฌยคโ€˜", + ["Tidal Mastery"] = "รญโ€ขยดรฌยยผรฌยหœ รชยนยจรซโ€นยฌรฌยล’", + ["Tiger Riding"] = "รญหœยธรซลพโ€˜รฌยยด รญฦ’โ‚ฌรชยธยฐ", + ["Tiger's Fury"] = "รซยงยนรชยณยตรชยฒยฉ", + ["Torment"] = "รชยณย รซยฌยธ", + ["Totem"] = "รญโ€ ย รญโ€ฆล“", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + -- ["Totem of Wrath"] = true, + ["Totemic Focus"] = "รญโ€ ย รญโ€ฆล“ รฌยงโ€˜รฌยคโ€˜", + ["Touch of Weakness"] = "รซยฌยดรซย ยฅรฌยหœ รฌโ€ ยรชยธยธ", + ["Toughness"] = "รชยฐโ€ขรฌยยธรญโ€ขยจ", + ["Track Beasts"] = "รฌโ€ขยผรฌห†หœ รฌยถโ€รฌย ย", + ["Track Demons"] = "รฌโ€ขโ€ฆรซยงห† รฌยถโ€รฌย ย", + ["Track Dragonkin"] = "รฌลกยฉรฌยกยฑ รฌยถโ€รฌย ย", + ["Track Elementals"] = "รฌย โ€ขรซย ยน รฌยถโ€รฌย ย", + ["Track Giants"] = "รชยฑยฐรฌยยธ รฌยถโ€รฌย ย", + ["Track Hidden"] = "รฌยโ‚ฌรฌโ€นย  รฌยถโ€รฌย ย", + ["Track Humanoids"] = "รฌยยธรชยฐโ€žรญหœโ€ข รฌยถโ€รฌย ย", + ["Track Undead"] = "รฌโ€“ยธรซยยฐรซโ€œล“ รฌยถโ€รฌย ย", + ["Tranquil Air Totem"] = "รญยโ€ฐรฌหœยจรฌยหœ รญโ€ ย รญโ€ฆล“", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Tranquil Spirit"] = "รญยโ€ฐรฌหœยจรญโ€ขล“ รฌย โ€ขรฌโ€นย ", + ["Tranquility"] = "รญยโ€ฐรฌหœยจ", + ["Tranquilizing Shot"] = "รญยโ€ฐรฌย โ€ขรฌยหœ รฌโ€šยฌรชยฒยฉ", + ["Trap Mastery"] = "รซยยซ รฌห†โ„ขรซย ยจ", + ["Travel Form"] = "รฌยนหœรญฦ’โ‚ฌ รซยณโ‚ฌรฌโ€นย ", +-- ["Tree of Life"] = true, + ["Tremor Totem"] = "รฌยงโ€žรซยโ„ขรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Tribal Leatherworking"] = "รฌย โ€žรญโ€ ยต รชยฐโ‚ฌรฌยฃยฝรฌโ€žยธรชยณยต", + ["Trueshot Aura"] = "รฌย โ€ขรฌยกยฐรฌยคโ‚ฌ รฌหœยครซยยผ", + ["Turn Undead"] = "รฌโ€“ยธรซยยฐรซโ€œล“ รญโ€กยดรฌยนหœ", + ["Two-Handed Axes and Maces"] = "รฌโ€“โ€˜รฌโ€ ย รซยโ€žรซยยผรซยฅหœ รซยฐย รซโ€˜โ€รชยธยฐรซยฅหœ", + ["Two-Handed Axes"] = "รฌโ€“โ€˜รฌโ€ ย รซยโ€žรซยยผ", + ["Two-Handed Maces"] = "รฌโ€“โ€˜รฌโ€ ย รฌยฒย รญโ€กยด", + ["Two-Handed Swords"] = "รฌโ€“โ€˜รฌโ€ ย รชยฒโ‚ฌ", + ["Two-Handed Weapon Specialization"] = "รฌโ€“โ€˜รฌโ€ ย รซยฌยดรชยธยฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Unarmed"] = "รซยงยจรฌโ€ ย", + ["Unbreakable Will"] = "รชยตยณรฌยโ‚ฌ รฌยหœรฌยงโ‚ฌ", + ["Unbridled Wrath Effect"] = "รซยถโ€žรซโ€ฆยธ รญโ€ขยดรซยฐยฉ", + ["Unbridled Wrath"] = "รซยถโ€žรซโ€ฆยธ รญโ€ขยดรซยฐยฉ", + ["Undead Horsemanship"] = "รฌโ€“ยธรซยยฐรซโ€œล“ รฌล ยนรซยงห†รฌห†ย ", + ["Underwater Breathing"] = "รฌห†หœรฌยคโ€˜ รญหœยธรญยยก", + ["Unending Breath"] = "รฌหœยรฌโ€บยรฌยหœ รฌห†ยจรชยฒยฐ", + ["Unholy Power"] = "รซยถโ‚ฌรฌย โ€ขรฌยหœ รญลพหœ", + ["Unleashed Fury"] = "รชยฒยฉรซโ€ฆยธ รญยยญรซยฐล“", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"] = "รชยตยณรฌยโ‚ฌ รฌโ€นย รซโ€ฆย", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Vampiric Embrace"] = "รญยยกรญหœห†รฌยหœ รฌโ€žย รซยฌยผ", + ["Vanish"] = "รฌโ€ ล’รซยฉยธ", + ["Vanished"] = "รฌโ€ ล’รซยฉยธ", +-- ["Vampiric Touch"] = true, + ["Vengeance"] = "รซยณยตรฌห†หœ", +-- ["Victory Rush"] = true, + ["Vigor"] = "รชยฐโ€ขรญโ€ขล“ รฌยฒยดรซย ยฅ", + ["Vile Poisons"] = "รฌยนหœรซยชโ€ฆรฌย ยรฌยยธ รซยโ€ฆ", + ["Vindication"] = "รซยนโ€žรญหœยธ", --รญโ„ขโ€ขรฌยยธ รฌลกโ€รซยงย + ["Viper Sting"] = "รฌโ€šยดรซยฌยดรฌโ€šยฌ รฌยยรชยธยฐ", + ["Volley"] = "รฌโ€”ยฐรซยฐล“ รฌโ€šยฌรชยฒยฉ", + ["Wand Specialization"] = "รซยงห†รซยฒโ€ขรซยดโ€ฐรซยฅหœ รฌย โ€žรซยฌยธรญโ„ขโ€", + ["Wands"] = "รซยงห†รซยฒโ€ขรซยดโ€ฐ", + ["War Stomp"] = "รฌย โ€žรญห†ยฌ รซยฐล“รชยตยฌรซยฅยดรชยธยฐ", + ["Water Breathing"] = "รฌห†หœรฌยคโ€˜ รญหœยธรญยยก", +-- ["Water Shield"] = true, + ["Water Walking"] = "รฌห†หœรซยฉยด รชยฑยทรชยธยฐ", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "รฌโ€ขยฝรญโ„ขโ€รซยล“ รฌหœยรญหœยผ", + ["Weaponsmith"] = "รซยฌยดรชยธยฐรฌย ล“รฌลพโ€˜", + ["Whirlwind"] = "รฌโ€ ล’รฌลกยฉรซยล’รฌยยด", + ["Will of the Forsaken"] = "รญยยฌรฌโ€žยธรฌยยดรญยยฐรฌยหœ รฌยหœรฌยงโ‚ฌ", + ["Windfury Totem"] = "รฌยงห†รญโ€™ยรฌยหœ รญโ€ ย รญโ€ฆล“", + ["Windfury Weapon"] = "รฌยงห†รญโ€™ยรฌยหœ รซยฌยดรชยธยฐ", + ["Windwall Totem"] = "รซยฐโ€รซลพล’รซยงโ€ฐรฌยยด รญโ€ ย รญโ€ฆล“", + ["Wing Clip"] = "รซโ€šย รชยฐล“ รฌย ห†รซโ€นยจ", + ["Winter's Chill"] = "รญหœยนรญโ€ขล“รฌยหœ รฌยถโ€รฌล“โ€ž", + ["Wisp Spirit"] = "รฌล“โ€žรฌล ยตรฌยหœ รฌหœยรญหœยผ", + ["Wolf Riding"] = "รซล โ€˜รซล’โ‚ฌ รญฦ’โ‚ฌรชยธยฐ", + ["Wound Poison II"] = "รฌฦ’ยรฌยฒหœ รชยฐยรฌโ€”ยผ รซยโ€ฆ II", + ["Wound Poison III"] = "รฌฦ’ยรฌยฒหœ รชยฐยรฌโ€”ยผ รซยโ€ฆ III", + ["Wound Poison IV"] = "รฌฦ’ยรฌยฒหœ รชยฐยรฌโ€”ยผ รซยโ€ฆ IV", + ["Wound Poison"] = "รฌฦ’ยรฌยฒหœ รชยฐยรฌโ€”ยผ รซยโ€ฆ", + ["Wrath"] = "รฌยฒล“รซยฒล’", + -- ["Wrath of Air Totem"] = true, + ["Wyvern Sting"] = "รซยนโ€žรซยฃยก รฌยยรชยธยฐ", + } +end) + +local spellIcons = { + ["Abolish Disease"] = "Spell_Nature_NullifyDisease", + ["Abolish Poison Effect"] = "Spell_Nature_NullifyPoison_02", + ["Abolish Poison"] = "Spell_Nature_NullifyPoison_02", + ["Activate MG Turret"] = "INV_Weapon_Rifle_10", + ["Adrenaline Rush"] = "Spell_Shadow_ShadowWordDominate", + ["Aftermath"] = "Spell_Fire_Fire", + ["Aggression"] = "Ability_Racial_Avatar", + ["Aimed Shot"] = "INV_Spear_07", + ["Alchemy"] = "Trade_Alchemy", + ["Ambush"] = "Ability_Rogue_Ambush", + ["Amplify Curse"] = "Spell_Shadow_Contagion", + ["Amplify Magic"] = "Spell_Holy_FlashHeal", + ["Ancestral Healing"] = "Spell_Nature_UndyingStrength", + ["Ancestral Knowledge"] = "Spell_Shadow_GrimWard", + ["Ancestral Spirit"] = "Spell_Nature_Regenerate", +-- ["Anesthetic Poison"] = true, + ["Anger Management"] = "Spell_Holy_BlessingOfStamina", +-- ["Anguish"] = true, + ["Anticipation"] = "Spell_Nature_MirrorImage", + ["Aquatic Form"] = "Ability_Druid_AquaticForm", +-- ["Arcane Blast"] = true, + ["Arcane Brilliance"] = "Spell_Holy_ArcaneIntellect", + ["Arcane Concentration"] = "Spell_Shadow_ManaBurn", + ["Arcane Explosion"] = "Spell_Nature_WispSplode", + ["Arcane Focus"] = "Spell_Holy_Devotion", + ["Arcane Instability"] = "Spell_Shadow_Teleport", + ["Arcane Intellect"] = "Spell_Holy_MagicalSentry", + ["Arcane Meditation"] = "Spell_Shadow_SiphonMana", + ["Arcane Mind"] = "Spell_Shadow_Charm", + ["Arcane Missiles"] = "Spell_Nature_StarFall", + ["Arcane Power"] = "Spell_Nature_Lightning", + ["Arcane Resistance"] = "Spell_Nature_StarFall", + ["Arcane Shot"] = "Ability_ImpalingBolt", + ["Arcane Subtlety"] = "Spell_Holy_DispelMagic", + ["Arctic Reach"] = "Spell_Shadow_DarkRitual", + ["Aspect of the Beast"] = "Ability_Mount_PinkTiger", + ["Aspect of the Cheetah"] = "Ability_Mount_JungleTiger", + ["Aspect of the Hawk"] = "Spell_Nature_RavenForm", + ["Aspect of the Monkey"] = "Ability_Hunter_AspectOfTheMonkey", + ["Aspect of the Pack"] = "Ability_Mount_WhiteTiger", +-- ["Aspect of the Viper"] = true, + ["Aspect of the Wild"] = "Spell_Nature_ProtectionformNature", + ["Astral Recall"] = "Spell_Nature_AstralRecal", + ["Attack"] = "Temp", + ["Attacking"] = "Temp", + ["Auto Shot"] = "Ability_Whirlwind", +-- ["Avenger's Shield"] = true, +-- ["Avenging Wrath"] = true, +-- ["Avoidance"] = true, + ["Axe Specialization"] = "INV_Axe_06", +-- ["Backlash"] = true, + ["Backstab"] = "Ability_BackStab", + ["Bane"] = "Spell_Shadow_DeathPact", + ["Banish"] = "Spell_Shadow_Cripple", + ["Barkskin Effect"] = "Spell_Nature_StoneClawTotem", + ["Barkskin"] = "Spell_Nature_StoneClawTotem", + ["Barrage"] = "Ability_UpgradeMoonGlaive", + ["Bash"] = "Ability_Druid_Bash", + ["Basic Campfire"] = "Spell_Fire_Fire", + ["Battle Shout"] = "Ability_Warrior_BattleShout", + ["Battle Stance Passive"] = "Ability_Warrior_OffensiveStance", + ["Battle Stance"] = "Ability_Warrior_OffensiveStance", + ["Bear Form"] = "Ability_Racial_BearForm", + ["Beast Lore"] = "Ability_Physical_Taunt", + ["Beast Slaying"] = "INV_Misc_Pelt_Bear_Ruin_02", + ["Beast Training"] = "Ability_Hunter_BeastCall02", + ["Benediction"] = "Spell_Frost_WindWalkOn", + ["Berserker Rage"] = "Spell_Nature_AncestralGuardian", + ["Berserker Stance Passive"] = "Ability_Racial_Avatar", + ["Berserker Stance"] = "Ability_Racial_Avatar", + ["Berserking"] = "Racial_Troll_Berserk", + ["Bestial Discipline"] = "Spell_Nature_AbolishMagic", + ["Bestial Swiftness"] = "Ability_Druid_Dash", + ["Bestial Wrath"] = "Ability_Druid_FerociousBite", +-- ["Binding Heal"] = true, + ["Bite"] = "Ability_Racial_Cannibalize", + ["Black Arrow"] = "Ability_TheBlackArrow", + ["Blackout"] = "Spell_Shadow_GatherShadows", + ["Blacksmithing"] = "Trade_BlackSmithing", + ["Blade Flurry"] = "Ability_Warrior_PunishingBlow", + ["Blast Wave"] = "Spell_Holy_Excorcism_02", +-- ["Blazing Speed"] = true, + ["Blessed Recovery"] = "Spell_Holy_BlessedRecovery", + ["Blessing of Freedom"] = "Spell_Holy_SealOfValor", + ["Blessing of Kings"] = "Spell_Magic_MageArmor", + ["Blessing of Light"] = "Spell_Holy_PrayerOfHealing02", + ["Blessing of Might"] = "Spell_Holy_FistOfJustice", + ["Blessing of Protection"] = "Spell_Holy_SealOfProtection", + ["Blessing of Sacrifice"] = "Spell_Holy_SealOfSacrifice", + ["Blessing of Salvation"] = "Spell_Holy_SealOfSalvation", + ["Blessing of Sanctuary"] = "Spell_Nature_LightningShield", + ["Blessing of Wisdom"] = "Spell_Holy_SealOfWisdom", + ["Blind"] = "Spell_Shadow_MindSteal", + ["Blinding Powder"] = "INV_Misc_Ammo_Gunpowder_02", + ["Blink"] = "Spell_Arcane_Blink", + ["Blizzard"] = "Spell_Frost_IceStorm", + ["Block"] = "Ability_Defend", + ["Blood Craze"] = "Spell_Shadow_SummonImp", + ["Blood Frenzy"] = "Ability_GhoulFrenzy", + ["Blood Fury"] = "Racial_Orc_BerserkerStrength", + ["Blood Pact"] = "Spell_Shadow_BloodBoil", +-- ["Bloodlust"] = true, + ["Bloodrage"] = "Ability_Racial_BloodRage", + ["Bloodthirst"] = "Spell_Nature_BloodLust", + ["Booming Voice"] = "Spell_Nature_Purge", + ["Bow Specialization"] = "INV_Weapon_Bow_12", + ["Bows"] = "INV_Weapon_Bow_05", + ["Bright Campfire"] = "Spell_Fire_Fire", + ["Brutal Impact"] = "Ability_Druid_Bash", + ["Burning Soul"] = "Spell_Fire_Fire", + ["Call Pet"] = "Ability_Hunter_BeastCall", + ["Call of Flame"] = "Spell_Fire_Immolation", + ["Call of Thunder"] = "Spell_Nature_CallStorm", + ["Camouflage"] = "Ability_Stealth", + ["Cannibalize"] = "Ability_Racial_Cannibalize", + ["Cat Form"] = "Ability_Druid_CatForm", + ["Cataclysm"] = "Spell_Fire_WindsofWoe", + ["Chain Heal"] = "Spell_Nature_HealingWaveGreater", + ["Chain Lightning"] = "Spell_Nature_ChainLightning", + ["Challenging Roar"] = "Ability_Druid_ChallangingRoar", + ["Challenging Shout"] = "Ability_BullRush", + ["Charge Rage Bonus Effect"] = "Ability_Warrior_Charge", + ["Charge"] = "Ability_Warrior_Charge", + ["Cheap Shot"] = "Ability_CheapShot", + ["Chilled"] = "Spell_Frost_IceStorm", +-- ["Circle of Healing"] = true, + ["Claw"] = "Ability_Druid_Rake", + ["Cleanse"] = "Spell_Holy_Renew", + ["Clearcasting"] = "Spell_Shadow_ManaBurn", + ["Cleave"] = "Ability_Warrior_Cleave", + ["Clever Traps"] = "Spell_Nature_TimeStop", +-- ["Cloak of Shadows"] = true, + ["Closing"] = "Temp", + ["Cloth"] = "INV_Chest_Cloth_21", + ["Cobra Reflexes"] = "Spell_Nature_GuardianWard", + ["Cold Blood"] = "Spell_Ice_Lament", + ["Cold Snap"] = "Spell_Frost_WizardMark", + ["Combat Endurance"] = "Spell_Nature_AncestralGuardian", + ["Combustion"] = "Spell_Fire_SealOfFire", + ["Command"] = "Ability_Warrior_WarCry", +-- ["Commanding Shout"] = true, + ["Concentration Aura"] = "Spell_Holy_MindSooth", + ["Concussion Blow"] = "Ability_ThunderBolt", + ["Concussion"] = "Spell_Fire_Fireball", + ["Concussive Shot"] = "Spell_Frost_Stun", + ["Cone of Cold"] = "Spell_Frost_Glacier", + ["Conflagrate"] = "Spell_Fire_Fireball", + ["Conjure Food"] = "INV_Misc_Food_10", + ["Conjure Mana Agate"] = "INV_Misc_Gem_Emerald_01", + ["Conjure Mana Citrine"] = "INV_Misc_Gem_Opal_01", + ["Conjure Mana Jade"] = "INV_Misc_Gem_Emerald_02", + ["Conjure Mana Ruby"] = "INV_Misc_Gem_Ruby_01", + ["Conjure Water"] = "INV_Drink_06", + ["Consecration"] = "Spell_Holy_InnerFire", +-- ["Consume Magic"] = true, + ["Consume Shadows"] = "Spell_Shadow_AntiShadow", + ["Convection"] = "Spell_Nature_WispSplode", + ["Conviction"] = "Spell_Holy_RetributionAura", + ["Cooking"] = "INV_Misc_Food_15", + ["Corruption"] = "Spell_Shadow_AbominationExplosion", + ["Counterattack"] = "Ability_Warrior_Challange", + ["Counterspell"] = "Spell_Frost_IceShock", + ["Cower"] = "Ability_Druid_Cower", + ["Create Firestone (Lesser)"]="INV_Ammo_FireTar", + ["Create Firestone"]="INV_Ammo_FireTar", + ["Create Firestone (Greater)"]="INV_Ammo_FireTar", + ["Create Firestone (Major)"]="INV_Ammo_FireTar", + ["Create Healthstone (Minor)"]="INV_Stone_04", + ["Create Healthstone (Lesser)"]="INV_Stone_04", + ["Create Healthstone"]="INV_Stone_04", + ["Create Healthstone (Greater)"]="INV_Stone_04", + ["Create Healthstone (Major)"]="INV_Stone_04", + ["Create Soulstone (Minor)"]="Spell_Shadow_SoulGem", + ["Create Soulstone (Lesser)"]="Spell_Shadow_SoulGem", + ["Create Soulstone"]="Spell_Shadow_SoulGem", + ["Create Soulstone (Greater)"]="Spell_Shadow_SoulGem", + ["Create Soulstone (Major)"]="Spell_Shadow_SoulGem", + ["Create Spellstone"]="INV_Misc_Gem_Sapphire_01", + ["Create Spellstone (Greater)"]="INV_Misc_Gem_Sapphire_01", + ["Create Spellstone (Major)"]="INV_Misc_Gem_Sapphire_01", + ["Crippling Poison II"] = "Ability_PoisonSting", + ["Crippling Poison"] = "Ability_PoisonSting", + ["Critical Mass"] = "Spell_Nature_WispHeal", + ["Crossbows"] = "INV_Weapon_Crossbow_01", + ["Cruelty"] = "Ability_Rogue_Eviscerate", +-- ["Crusader Aura"] = true, +-- ["Crusader Strike"] = true, + ["Cultivation"] = "INV_Misc_Flower_01", + ["Cure Disease"] = "Spell_Holy_NullifyDisease", + ["Cure Poison"] = "Spell_Nature_NullifyPoison", + ["Curse of Agony"] = "Spell_Shadow_CurseOfSargeras", + ["Curse of Doom Effect"] = "Spell_Shadow_AuraOfDarkness", + ["Curse of Doom"] = "Spell_Shadow_AuraOfDarkness", + ["Curse of Exhaustion"] = "Spell_Shadow_GrimWard", + ["Curse of Idiocy"] = "Spell_Shadow_MindRot", + ["Curse of Recklessness"] = "Spell_Shadow_UnholyStrength", + ["Curse of Shadow"] = "Spell_Shadow_CurseOfAchimonde", + ["Curse of Tongues"] = "Spell_Shadow_CurseOfTounges", + ["Curse of Weakness"] = "Spell_Shadow_CurseOfMannoroth", + ["Curse of the Elements"] = "Spell_Shadow_ChillTouch", +-- ["Cyclone"] = true, + ["Dagger Specialization"] = "INV_Weapon_ShortBlade_05", + ["Daggers"] = "Ability_SteelMelee", + ["Dampen Magic"] = "Spell_Nature_AbolishMagic", + ["Dark Pact"] = "Spell_Shadow_DarkRitual", + ["Darkness"] = "Spell_Shadow_Twilight", + ["Dash"] = "Ability_Druid_Dash", + ["Deadly Poison II"] = "Ability_Rogue_DualWeild", + ["Deadly Poison III"] = "Ability_Rogue_DualWeild", + ["Deadly Poison IV"] = "Ability_Rogue_DualWeild", + ["Deadly Poison V"] = "Ability_Rogue_DualWeild", + ["Deadly Poison"] = "Ability_Rogue_DualWeild", +-- ["Deadly Throw"] = true, + ["Death Coil"] = "Spell_Shadow_DeathCoil", + ["Death Wish"] = "Spell_Shadow_DeathPact", + ["Deep Wounds"] = "Ability_BackStab", + ["Defense"] = "Ability_Racial_ShadowMeld", + ["Defensive Stance Passive"] = "Ability_Warrior_DefensiveStance", + ["Defensive Stance"] = "Ability_Warrior_DefensiveStance", + ["Defensive State 2"] = "Ability_Defend", + ["Defensive State"] = "Ability_Defend", + ["Defiance"] = "Ability_Warrior_InnerRage", + ["Deflection"] = "Ability_Parry", + ["Demon Armor"] = "Spell_Shadow_RagingScream", + ["Demon Skin"] = "Spell_Shadow_RagingScream", + ["Demonic Embrace"] = "Spell_Shadow_Metamorphosis", +-- ["Demonic Frenzy"] = true, + ["Demonic Sacrifice"] = "Spell_Shadow_PsychicScream", + ["Demoralizing Roar"] = "Ability_Druid_DemoralizingRoar", + ["Demoralizing Shout"] = "Ability_Warrior_WarCry", + ["Desperate Prayer"] = "Spell_Holy_Restoration", + ["Destructive Reach"] = "Spell_Shadow_CorpseExplode", + ["Detect Greater Invisibility"] = "Spell_Shadow_DetectInvisibility", + ["Detect Invisibility"] = "Spell_Shadow_DetectInvisibility", + ["Detect Lesser Invisibility"] = "Spell_Shadow_DetectLesserInvisibility", + ["Detect Magic"] = "Spell_Holy_Dizzy", + ["Detect Traps"] = "Ability_Spy", + ["Detect"] = "Ability_Hibernation", + ["Deterrence"] = "Ability_Whirlwind", +-- ["Devastate"] = true, + ["Devastation"] = "Spell_Fire_FlameShock", + ["Devotion Aura"] = "Spell_Holy_DevotionAura", + ["Devour Magic Effect"] = "Spell_Nature_Purge", + ["Devour Magic"] = "Spell_Nature_Purge", + ["Devouring Plague"] = "Spell_Shadow_BlackPlague", + ["Diplomacy"] = "INV_Misc_Note_02", + ["Dire Bear Form"] = "Ability_Racial_BearForm", + ["Disarm Trap"] = "Spell_Shadow_GrimWard", + ["Disarm"] = "Ability_Warrior_Disarm", + ["Disease Cleansing Totem"] = "Spell_Nature_DiseaseCleansingTotem", + ["Disenchant"] = "Spell_Holy_RemoveCurse", + ["Disengage"] = "Ability_Rogue_Feint", + ["Dismiss Pet"] = "Spell_Nature_SpiritWolf", + ["Dispel Magic"] = "Spell_Holy_DispelMagic", + ["Distract"] = "Ability_Rogue_Distract", + ["Distracting Shot"] = "Spell_Arcane_Blink", + ["Dive"] = "Spell_Shadow_BurningSpirit", + ["Divine Favor"] = "Spell_Holy_Heal", + ["Divine Fury"] = "Spell_Holy_SealOfWrath", +-- ["Divine Illumination"] = true, +-- ["Divine Intellect"] = "Spell_Nature_Sleep", + ["Divine Intervention"] = "Spell_Nature_TimeStop", + ["Divine Protection"] = "Spell_Holy_Restoration", + ["Divine Shield"] = "Spell_Holy_DivineIntervention", + ["Divine Spirit"] = "Spell_Holy_DivineSpirit", + ["Divine Strength"] = "Ability_GolemThunderClap", + ["Dodge"] = "Spell_Nature_Invisibilty", +-- ["Dragon's Breath"] = true, +-- ["Dragonscale Leatherworking"] = true, + ["Drain Life"] = "Spell_Shadow_LifeDrain02", + ["Drain Mana"] = "Spell_Shadow_SiphonMana", + ["Drain Soul"] = "Spell_Shadow_Haunting", + ["Dual Wield Specialization"] = "Ability_DualWield", + ["Dual Wield"] = "Ability_DualWield", + ["Duel"] = "Temp", + ["Eagle Eye"] = "Ability_Hunter_EagleEye", +-- ["Earth Elemental Totem"] = true, +-- ["Earth Shield"] = true, + ["Earth Shock"] = "Spell_Nature_EarthShock", + ["Earthbind Totem"] = "Spell_Nature_StrengthOfEarthTotem02", + ["Efficiency"] = "Spell_Frost_WizardMark", + ["Elemental Focus"] = "Spell_Shadow_ManaBurn", + ["Elemental Fury"] = "Spell_Fire_Volcano", + ["Elemental Mastery"] = "Spell_Nature_WispHeal", + ["Elune's Grace"] = "Spell_Holy_ElunesGrace", + ["Elusiveness"] = "Spell_Magic_LesserInvisibilty", + ["Emberstorm"] = "Spell_Fire_SelfDestruct", + ["Enchanting"] = "Trade_Engraving", + ["Endurance Training"] = "Spell_Nature_Reincarnation", + ["Endurance"] = "Spell_Nature_UnyeildingStamina", + ["Engineering Specialization"] = "INV_Misc_Gear_01", + ["Engineering"] = "Trade_Engineering", + ["Enrage"] = "Ability_Druid_Enrage", + ["Enslave Demon"] = "Spell_Shadow_EnslaveDemon", + ["Entangling Roots"] = "Spell_Nature_StrangleVines", + ["Entrapment"] = "Spell_Nature_StrangleVines", +-- ["Envenom"] = true, + ["Escape Artist"] = "Ability_Rogue_Trip", + ["Evasion"] = "Spell_Shadow_ShadowWard", + ["Eventide"] = "Spell_Frost_Stun", + ["Eviscerate"] = "Ability_Rogue_Eviscerate", + ["Evocation"] = "Spell_Nature_Purge", + ["Execute"] = "INV_Sword_48", + ["Exorcism"] = "Spell_Holy_Excorcism_02", + ["Expansive Mind"] = "INV_Enchant_EssenceEternalLarge", + ["Explosive Trap Effect"] = "Spell_Fire_SelfDestruct", + ["Explosive Trap"] = "Spell_Fire_SelfDestruct", + ["Expose Armor"] = "Ability_Warrior_Riposte", + ["Eye for an Eye"] = "Spell_Holy_EyeforanEye", + ["Eye of Kilrogg"] = "Spell_Shadow_EvilEye", + ["Eyes of the Beast"] = "Ability_EyeOfTheOwl", + ["Fade"] = "Spell_Magic_LesserInvisibilty", + ["Faerie Fire"] = "Spell_Nature_FaerieFire", + ["Far Sight"] = "Spell_Nature_FarSight", + ["Fear Ward"] = "Spell_Holy_Excorcism", + ["Fear"] = "Spell_Shadow_Possession", + ["Feed Pet"] = "Ability_Hunter_BeastTraining", + ["Feedback"] = "Spell_Shadow_RitualOfSacrifice", + ["Feign Death"] = "Ability_Rogue_FeignDeath", + ["Feint"] = "Ability_Rogue_Feint", +-- ["Fel Armor"] = true, + ["Fel Concentration"] = "Spell_Shadow_FingerOfDeath", + ["Fel Domination"] = "Spell_Nature_RemoveCurse", + ["Fel Intellect"] = "Spell_Holy_MagicalSentry", + ["Fel Stamina"] = "Spell_Shadow_AntiShadow", + ["Felfire"] = "Spell_Fire_Fireball", + ["Feline Grace"] = "INV_Feather_01", + ["Feline Swiftness"] = "Spell_Nature_SpiritWolf", + ["Feral Aggression"] = "Ability_Druid_DemoralizingRoar", + ["Feral Charge"] = "Ability_Hunter_Pet_Bear", + ["Feral Instinct"] = "Ability_Ambush", + ["Ferocious Bite"] = "Ability_Druid_FerociousBite", + ["Ferocity"] = "INV_Misc_MonsterClaw_04", + ["Fetish"] = "INV_Misc_Horn_01", + ["Find Herbs"] = "INV_Misc_Flower_02", + ["Find Minerals"] = "Spell_Nature_Earthquake", + ["Find Treasure"] = "Racial_Dwarf_FindTreasure", + ["Fire Blast"] = "Spell_Fire_Fireball", +-- ["Fire Elemental Totem"] = true, + ["Fire Nova Totem"] = "Spell_Fire_SealOfFire", + ["Fire Power"] = "Spell_Fire_Immolation", + ["Fire Resistance Aura"] = "Spell_Fire_SealOfFire", + ["Fire Resistance Totem"] = "Spell_FireResistanceTotem_01", + ["Fire Resistance"] = "Spell_Fire_FireArmor", + ["Fire Shield"] = "Spell_Fire_FireArmor", + ["Fire Vulnerability"] = "Spell_Fire_SoulBurn", + ["Fire Ward"] = "Spell_Fire_FireArmor", + ["Fireball"] = "Spell_Fire_FlameBolt", + ["Firebolt"] = "Spell_Fire_FireBolt", + ["First Aid"] = "Spell_Holy_SealOfSacrifice", + ["Fishing Poles"] = "Trade_Fishing", + ["Fishing"] = "Trade_Fishing", + ["Fist Weapon Specialization"] = "INV_Gauntlets_04", + ["Fist Weapons"] = "INV_Gauntlets_04", + ["Flame Shock"] = "Spell_Fire_FlameShock", + ["Flame Throwing"] = "Spell_Fire_Flare", + ["Flamestrike"] = "Spell_Fire_SelfDestruct", + ["Flamethrower"] = "Spell_Fire_Incinerate", + ["Flametongue Totem"] = "Spell_Nature_GuardianWard", + ["Flametongue Weapon"] = "Spell_Fire_FlameTounge", + ["Flare"] = "Spell_Fire_Flare", + ["Flash Heal"] = "Spell_Holy_FlashHeal", + ["Flash of Light"] = "Spell_Holy_FlashHeal", +-- ["Flight Form"] = true, + ["Flurry"] = "Ability_GhoulFrenzy", + ["Focused Casting"] = "Spell_Arcane_Blink", +-- ["Forbearance"] = true, +-- ["Force of Nature"] = true, + ["Force of Will"] = "Spell_Nature_SlowingTotem", + ["Freezing Trap"] = "Spell_Frost_ChainsOfIce", + ["Frenzied Regeneration"] = "Ability_BullRush", + ["Frenzy"] = "INV_Misc_MonsterClaw_03", + ["Frost Armor"] = "Spell_Frost_FrostArmor02", + ["Frost Channeling"] = "Spell_Frost_Stun", + ["Frost Nova"] = "Spell_Frost_FrostNova", + ["Frost Resistance Aura"] = "Spell_Frost_WizardMark", + ["Frost Resistance Totem"] = "Spell_FrostResistanceTotem_01", + ["Frost Resistance"] = "Spell_Frost_FrostWard", + ["Frost Shock"] = "Spell_Frost_FrostShock", + ["Frost Trap"] = "Spell_Frost_FreezingBreath", + ["Frost Ward"] = "Spell_Frost_FrostWard", + ["Frostbite"] = "Spell_Frost_FrostArmor", + ["Frostbolt"] = "Spell_Frost_FrostBolt02", + ["Frostbrand Weapon"] = "Spell_Frost_FrostBrand", + ["Furious Howl"] = "Ability_Hunter_Pet_Wolf", + ["Furor"] = "Spell_Holy_BlessingOfStamina", + ["Garrote"] = "Ability_Rogue_Garrote", + ["Generic"] = "INV_Shield_09", + ["Ghost Wolf"] = "Spell_Nature_SpiritWolf", + ["Ghostly Strike"] = "Spell_Shadow_Curse", + ["Gift of Life"] = "INV_Misc_Gem_Pearl_05", + ["Gift of Nature"] = "Spell_Nature_ProtectionformNature", + ["Gift of the Wild"] = "Spell_Nature_Regeneration", + ["Gouge"] = "Ability_Gouge", + ["Grace of Air Totem"] = "Spell_Nature_InvisibilityTotem", + ["Great Stamina"] = "Spell_Nature_UnyeildingStamina", + ["Greater Blessing of Kings"] = "Spell_Magic_GreaterBlessingofKings", + ["Greater Blessing of Light"] = "Spell_Holy_GreaterBlessingofLight", + ["Greater Blessing of Might"] = "Spell_Holy_GreaterBlessingofKings", + ["Greater Blessing of Salvation"] = "Spell_Holy_GreaterBlessingofSalvation", + ["Greater Blessing of Sanctuary"] = "Spell_Holy_GreaterBlessingofSanctuary", + ["Greater Blessing of Wisdom"] = "Spell_Holy_GreaterBlessingofWisdom", + ["Greater Heal"] = "Spell_Holy_GreaterHeal", + ["Grim Reach"] = "Spell_Shadow_CallofBone", + ["Grounding Totem"] = "Spell_Nature_GroundingTotem", + ["Grovel"] = "Temp", + ["Growl"] = "Ability_Physical_Taunt", + ["Guardian's Favor"] = "Spell_Holy_SealOfProtection", + ["Gun Specialization"] = "INV_Musket_03", + ["Guns"] = "INV_Weapon_Rifle_01", + ["Hammer of Justice"] = "Spell_Holy_SealOfMight", + ["Hammer of Wrath"] = "Ability_ThunderClap", + ["Hamstring"] = "Ability_ShockWave", + ["Harass"] = "Ability_Hunter_Harass", + ["Hardiness"] = "INV_Helmet_23", + ["Hawk Eye"] = "Ability_TownWatch", + ["Heal"] = "Spell_Holy_Heal", + ["Healing Focus"] = "Spell_Holy_HealingFocus", + ["Healing Light"] = "Spell_Holy_HolyBolt", + ["Healing Stream Totem"] = "INV_Spear_04", + ["Healing Touch"] = "Spell_Nature_HealingTouch", + ["Healing Wave"] = "Spell_Nature_MagicImmunity", + ["Health Funnel"] = "Spell_Shadow_LifeDrain", + ["Heart of the Wild"] = "Spell_Holy_BlessingOfAgility", + ["Hellfire Effect"] = "Spell_Fire_Incinerate", + ["Hellfire"] = "Spell_Fire_Incinerate", + ["Hemorrhage"] = "Spell_Shadow_LifeDrain", + ["Herbalism"] = "Spell_Nature_NatureTouchGrow", + ["Heroic Strike"] = "Ability_Rogue_Ambush", +-- ["Heroism"] = true, + ["Hex of Weakness"] = "Spell_Shadow_FingerOfDeath", + ["Hibernate"] = "Spell_Nature_Sleep", + ["Holy Fire"] = "Spell_Holy_SearingLight", + ["Holy Light"] = "Spell_Holy_HolyBolt", + ["Holy Nova"] = "Spell_Holy_HolyNova", + ["Holy Power"] = "Spell_Holy_Power", + ["Holy Reach"] = "Spell_Holy_Purify", + ["Holy Shield"] = "Spell_Holy_BlessingOfProtection", + ["Holy Shock"] = "Spell_Holy_SearingLight", + ["Holy Specialization"] = "Spell_Holy_SealOfSalvation", + ["Holy Wrath"] = "Spell_Holy_Excorcism", + ["Honorless Target"] = "Spell_Magic_LesserInvisibilty", + ["Horse Riding"] = "Spell_Nature_Swiftness", + ["Howl of Terror"] = "Spell_Shadow_DeathScream", + ["Humanoid Slaying"] = "Spell_Holy_PrayerOfHealing", + ["Hunter's Mark"] = "Ability_Hunter_SniperShot", + ["Hurricane"] = "Spell_Nature_Cyclone", + ["Ice Armor"] = "Spell_Frost_FrostArmor02", + ["Ice Barrier"] = "Spell_Ice_Lament", + ["Ice Block"] = "Spell_Frost_Frost", +-- ["Ice Lance"] = true, + ["Ice Shards"] = "Spell_Frost_IceShard", + ["Ignite"] = "Spell_Fire_Incinerate", + ["Illumination"] = "Spell_Holy_GreaterHeal", + ["Immolate"] = "Spell_Fire_Immolation", + ["Immolation Trap Effect"] = "Spell_Fire_FlameShock", + ["Immolation Trap"] = "Spell_Fire_FlameShock", + ["Impact"] = "Spell_Fire_MeteorStorm", + ["Impale"] = "Ability_SearingArrow", + ["Improved Ambush"] = "Ability_Rogue_Ambush", + ["Improved Arcane Explosion"] = "Spell_Nature_WispSplode", + ["Improved Arcane Missiles"] = "Spell_Nature_StarFall", + ["Improved Arcane Shot"] = "Ability_ImpalingBolt", + ["Improved Aspect of the Hawk"] = "Spell_Nature_RavenForm", + ["Improved Aspect of the Monkey"] = "Ability_Hunter_AspectOfTheMonkey", + ["Improved Backstab"] = "Ability_BackStab", + ["Improved Battle Shout"] = "Ability_Warrior_BattleShout", + ["Improved Berserker Rage"] = "Spell_Nature_AncestralGuardian", + ["Improved Blessing of Might"] = "Spell_Holy_FistOfJustice", + ["Improved Blessing of Wisdom"] = "Spell_Holy_SealOfWisdom", + ["Improved Blizzard"] = "Spell_Frost_IceStorm", + ["Improved Bloodrage"] = "Ability_Racial_BloodRage", + ["Improved Chain Heal"] = "Spell_Nature_HealingWaveGreater", + ["Improved Chain Lightning"] = "Spell_Nature_ChainLightning", + ["Improved Challenging Shout"] = "Ability_Warrior_Challange", + ["Improved Charge"] = "Ability_Warrior_Charge", + ["Improved Cheap Shot"] = "Ability_CheapShot", + ["Improved Cleave"] = "Ability_Warrior_Cleave", + ["Improved Concentration Aura"] = "Spell_Holy_MindSooth", + ["Improved Concussive Shot"] = "Spell_Frost_Stun", + ["Improved Cone of Cold"] = "Spell_Frost_Glacier", + ["Improved Corruption"] = "Spell_Shadow_AbominationExplosion", + ["Improved Counterspell"] = "Spell_Frost_IceShock", + ["Improved Curse of Agony"] = "Spell_Shadow_CurseOfSargeras", + ["Improved Curse of Exhaustion"] = "Spell_Shadow_GrimWard", + ["Improved Curse of Weakness"] = "Spell_Shadow_CurseOfMannoroth", + ["Improved Dampen Magic"] = "Spell_Nature_AbolishMagic", + ["Improved Deadly Poison"] = "Ability_Rogue_DualWeild", + ["Improved Demoralizing Shout"] = "Ability_Warrior_WarCry", + ["Improved Devotion Aura"] = "Spell_Holy_DevotionAura", + ["Improved Disarm"] = "Ability_Warrior_Disarm", + ["Improved Distract"] = "Ability_Rogue_Distract", + ["Improved Drain Life"] = "Spell_Shadow_LifeDrain02", + ["Improved Drain Mana"] = "Spell_Shadow_SiphonMana", + ["Improved Drain Soul"] = "Spell_Shadow_Haunting", + ["Improved Enrage"] = "Ability_Druid_Enrage", + ["Improved Enslave Demon"] = "Spell_Shadow_EnslaveDemon", + ["Improved Entangling Roots"] = "Spell_Nature_StrangleVines", + ["Improved Evasion"] = "Spell_Shadow_ShadowWard", + ["Improved Eviscerate"] = "Ability_Rogue_Eviscerate", + ["Improved Execute"] = "INV_Sword_48", + ["Improved Expose Armor"] = "Ability_Warrior_Riposte", + ["Improved Eyes of the Beast"] = "Ability_EyeOfTheOwl", + ["Improved Fade"] = "Spell_Magic_LesserInvisibilty", + ["Improved Feign Death"] = "Ability_Rogue_FeignDeath", + ["Improved Fire Blast"] = "Spell_Fire_Fireball", + ["Improved Fire Nova Totem"] = "Spell_Fire_SealOfFire", + ["Improved Fire Ward"] = "Spell_Fire_FireArmor", + ["Improved Fireball"] = "Spell_Fire_FlameBolt", + ["Improved Firebolt"] = "Spell_Fire_FireBolt", + ["Improved Firestone"] = "INV_Ammo_FireTar", + ["Improved Flamestrike"] = "Spell_Fire_SelfDestruct", + ["Improved Flametongue Weapon"] = "Spell_Fire_FlameTounge", + ["Improved Flash of Light"] = "Spell_Holy_FlashHeal", + ["Improved Frost Nova"] = "Spell_Frost_FreezingBreath", + ["Improved Frost Ward"] = "Spell_Frost_FrostWard", + ["Improved Frostbolt"] = "Spell_Frost_FrostBolt02", + ["Improved Frostbrand Weapon"] = "Spell_Frost_FrostBrand", + ["Improved Garrote"] = "Ability_Rogue_Garrote", + ["Improved Ghost Wolf"] = "Spell_Nature_SpiritWolf", + ["Improved Gouge"] = "Ability_Gouge", + ["Improved Grace of Air Totem"] = "Spell_Nature_InvisibilityTotem", + ["Improved Grounding Totem"] = "Spell_Nature_GroundingTotem", + ["Improved Hammer of Justice"] = "Spell_Holy_SealOfMight", + ["Improved Hamstring"] = "Ability_ShockWave", + ["Improved Healing Stream Totem"] = "INV_Spear_04", + ["Improved Healing Touch"] = "Spell_Nature_HealingTouch", + ["Improved Healing Wave"] = "Spell_Nature_MagicImmunity", + ["Improved Healing"] = "Spell_Holy_Heal02", + ["Improved Health Funnel"] = "Spell_Shadow_LifeDrain", + ["Improved Healthstone"] = "INV_Stone_04", + ["Improved Heroic Strike"] = "Ability_Rogue_Ambush", + ["Improved Hunter's Mark"] = "Ability_Hunter_SniperShot", + ["Improved Immolate"] = "Spell_Fire_Immolation", + ["Improved Imp"] = "Spell_Shadow_SummonImp", + ["Improved Inner Fire"] = "Spell_Holy_InnerFire", + ["Improved Instant Poison"] = "Ability_Poisons", + ["Improved Intercept"] = "Ability_Rogue_Sprint", + ["Improved Intimidating Shout"] = "Ability_GolemThunderClap", + ["Improved Judgement"] = "Spell_Holy_RighteousFury", + ["Improved Kick"] = "Ability_Kick", + ["Improved Kidney Shot"] = "Ability_Rogue_KidneyShot", + ["Improved Lash of Pain"] = "Spell_Shadow_Curse", + ["Improved Lay on Hands"] = "Spell_Holy_LayOnHands", + ["Improved Lesser Healing Wave"] = "Spell_Nature_HealingWaveLesser", + ["Improved Life Tap"] = "Spell_Shadow_BurningSpirit", + ["Improved Lightning Bolt"] = "Spell_Nature_Lightning", + ["Improved Lightning Shield"] = "Spell_Nature_LightningShield", + ["Improved Magma Totem"] = "Spell_Fire_SelfDestruct", + ["Improved Mana Burn"] = "Spell_Shadow_ManaBurn", + ["Improved Mana Shield"] = "Spell_Shadow_DetectLesserInvisibility", + ["Improved Mana Spring Totem"] = "Spell_Nature_ManaRegenTotem", + ["Improved Mark of the Wild"] = "Spell_Nature_Regeneration", + ["Improved Mend Pet"] = "Ability_Hunter_MendPet", + ["Improved Mind Blast"] = "Spell_Shadow_UnholyFrenzy", + ["Improved Moonfire"] = "Spell_Nature_StarFall", + ["Improved Nature's Grasp"] = "Spell_Nature_NaturesWrath", + ["Improved Overpower"] = "INV_Sword_05", + ["Improved Power Word: Fortitude"] = "Spell_Holy_WordFortitude", + ["Improved Power Word: Shield"] = "Spell_Holy_PowerWordShield", + ["Improved Prayer of Healing"] = "Spell_Holy_PrayerOfHealing02", + ["Improved Psychic Scream"] = "Spell_Shadow_PsychicScream", + ["Improved Pummel"] = "INV_Gauntlets_04", + ["Improved Regrowth"] = "Spell_Nature_ResistNature", + ["Improved Reincarnation"] = "Spell_Nature_Reincarnation", + ["Improved Rejuvenation"] = "Spell_Nature_Rejuvenation", + ["Improved Rend"] = "Ability_Gouge", + ["Improved Renew"] = "Spell_Holy_Renew", + ["Improved Retribution Aura"] = "Spell_Holy_AuraOfLight", + ["Improved Revenge"] = "Ability_Warrior_Revenge", + ["Improved Revive Pet"] = "Ability_Hunter_BeastSoothe", + ["Improved Righteous Fury"] = "Spell_Holy_SealOfFury", + ["Improved Rockbiter Weapon"] = "Spell_Nature_RockBiter", + ["Improved Rupture"] = "Ability_Rogue_Rupture", + ["Improved Sap"] = "Ability_Sap", + ["Improved Scorch"] = "Spell_Fire_SoulBurn", + ["Improved Scorpid Sting"] = "Ability_Hunter_CriticalShot", + ["Improved Seal of Righteousness"] = "Ability_ThunderBolt", + ["Improved Seal of the Crusader"] = "Spell_Holy_HolySmite", + ["Improved Searing Pain"] = "Spell_Fire_SoulBurn", + ["Improved Searing Totem"] = "Spell_Fire_SearingTotem", + ["Improved Serpent Sting"] = "Ability_Hunter_Quickshot", + ["Improved Shadow Bolt"] = "Spell_Shadow_ShadowBolt", + ["Improved Shadow Word: Pain"] = "Spell_Shadow_ShadowWordPain", + ["Improved Shield Bash"] = "Ability_Warrior_ShieldBash", + ["Improved Shield Block"] = "Ability_Defend", + ["Improved Shield Wall"] = "Ability_Warrior_ShieldWall", + ["Improved Shred"] = "Spell_Shadow_VampiricAura", + ["Improved Sinister Strike"] = "Spell_Shadow_RitualOfSacrifice", + ["Improved Slam"] = "Ability_Warrior_DecisiveStrike", + ["Improved Slice and Dice"] = "Ability_Rogue_SliceDice", + ["Improved Spellstone"] = "INV_Misc_Gem_Sapphire_01", + ["Improved Sprint"] = "Ability_Rogue_Sprint", + ["Improved Starfire"] = "Spell_Arcane_StarFire", + ["Improved Stoneclaw Totem"] = "Spell_Nature_StoneClawTotem", + ["Improved Stoneskin Totem"] = "Spell_Nature_StoneSkinTotem", + ["Improved Strength of Earth Totem"] = "Spell_Nature_EarthBindTotem", + ["Improved Succubus"] = "Spell_Shadow_SummonSuccubus", + ["Improved Sunder Armor"] = "Ability_Warrior_Sunder", + ["Improved Taunt"] = "Spell_Nature_Reincarnation", + ["Improved Thorns"] = "Spell_Nature_Thorns", + ["Improved Thunder Clap"] = "Ability_ThunderClap", + ["Improved Tranquility"] = "Spell_Nature_Tranquility", + ["Improved Vampiric Embrace"] = "Spell_Shadow_ImprovedVampiricEmbrace", + ["Improved Vanish"] = "Ability_Vanish", + ["Improved Voidwalker"] = "Spell_Shadow_SummonVoidWalker", + ["Improved Windfury Weapon"] = "Spell_Nature_Cyclone", + ["Improved Wing Clip"] = "Ability_Rogue_Trip", + ["Improved Wrath"] = "Spell_Nature_AbolishMagic", + ["Incinerate"] = "Spell_Fire_FlameShock", + ["Inferno"] = "Spell_Shadow_SummonInfernal", + ["Initiative"] = "Spell_Shadow_Fumble", + ["Inner Fire"] = "Spell_Holy_InnerFire", + ["Inner Focus"] = "Spell_Frost_WindWalkOn", + ["Innervate"] = "Spell_Nature_Lightning", + ["Insect Swarm"] = "Spell_Nature_InsectSwarm", + ["Inspiration"] = "Spell_Holy_LayOnHands", + ["Instant Poison II"] = "Ability_Poisons", + ["Instant Poison III"] = "Ability_Poisons", + ["Instant Poison IV"] = "Ability_Poisons", + ["Instant Poison V"] = "Ability_Poisons", + ["Instant Poison VI"] = "Ability_Poisons", + ["Instant Poison"] = "Ability_Poisons", + ["Intensity"] = "Spell_Fire_LavaSpawn", + ["Intercept"] = "Ability_Rogue_Sprint", + ["Intimidating Shout"] = "Ability_GolemThunderClap", + ["Intimidation"] = "Ability_Devour", +-- ["Invisibility"] = true, + ["Iron Will"] = "Spell_Magic_MageArmor", + ["Judgement of Command"] = "Ability_Warrior_InnerRage", + ["Judgement of Justice"] = "Spell_Holy_SealOfWrath", + ["Judgement of Light"] = "Spell_Holy_HealingAura", + ["Judgement of Righteousness"] = "Ability_ThunderBolt", + ["Judgement of Wisdom"] = "Spell_Holy_RighteousnessAura", + ["Judgement of the Crusader"] = "Spell_Holy_HolySmite", + ["Judgement"] = "Spell_Holy_RighteousFury", + ["Kick"] = "Ability_Kick", + ["Kidney Shot"] = "Ability_Rogue_KidneyShot", +-- ["Kill Command"] = true, + ["Killer Instinct"] = "Spell_Holy_BlessingOfStamina", + ["Kodo Riding"] = "Spell_Nature_Swiftness", +-- ["Lacerate"] = true, + ["Lash of Pain"] = "Spell_Shadow_Curse", + ["Last Stand"] = "Spell_Holy_AshesToAshes", + ["Lasting Judgement"] = "Spell_Holy_HealingAura", + ["Lay on Hands"] = "Spell_Holy_LayOnHands", + ["Leader of the Pack"] = "Spell_Nature_UnyeildingStamina", + ["Leather"] = "INV_Chest_Leather_09", + ["Leatherworking"] = "INV_Misc_ArmorKit_17", + ["Lesser Heal"] = "Spell_Holy_LesserHeal", + ["Lesser Healing Wave"] = "Spell_Nature_HealingWaveLesser", + ["Lesser Invisibility"] = "Spell_Magic_LesserInvisibilty", + ["Lethal Shots"] = "Ability_SearingArrow", + ["Lethality"] = "Ability_CriticalStrike", + ["Levitate"] = "Spell_Holy_LayOnHands", + ["Libram"] = "INV_Misc_Book_11", +-- ["Lifebloom"] = true, + ["Life Tap"] = "Spell_Shadow_BurningSpirit", + ["Lifegiving Gem"] = "INV_Misc_Gem_Pearl_05", + ["Lightning Bolt"] = "Spell_Nature_Lightning", + ["Lightning Breath"] = "Spell_Nature_Lightning", + ["Lightning Mastery"] = "Spell_Lightning_LightningBolt01", + ["Lightning Reflexes"] = "Spell_Nature_Invisibilty", + ["Lightning Shield"] = "Spell_Nature_LightningShield", + ["Lightwell Renew"] = "Spell_Holy_SummonLightwell", + ["Lightwell"] = "Spell_Holy_SummonLightwell", + ["Long Daze"] = "Spell_Frost_Stun", + ["Mace Specialization"] = "INV_Mace_01", + ["Mace Stun Effect"] = "Spell_Frost_Stun", + ["Mage Armor"] = "Spell_MageArmor", + ["Magma Totem"] = "Spell_Fire_SelfDestruct", + ["Mail"] = "INV_Chest_Chain_05", +-- ["Maim"] = true, + ["Malice"] = "Ability_Racial_BloodRage", + ["Mana Burn"] = "Spell_Shadow_ManaBurn", + ["Mana Shield"] = "Spell_Shadow_DetectLesserInvisibility", + ["Mana Spring Totem"] = "Spell_Nature_ManaRegenTotem", + ["Mana Tide Totem"] = "Spell_Frost_SummonWaterElemental", + ["Mangle"] = "Ability_Druid_Mangle", +-- ["Mangle (Cat)"] = true, +-- ["Mangle (Bear)"] = true, + ["Mark of the Wild"] = "Spell_Nature_Regeneration", + ["Martyrdom"] = "Spell_Nature_Tranquility", +-- ["Mass Dispel"] = true, + ["Master Demonologist"] = "Spell_Shadow_ShadowPact", + ["Master Summoner"] = "Spell_Shadow_ImpPhaseShift", + ["Master of Deception"] = "Spell_Shadow_Charm", + ["Maul"] = "Ability_Druid_Maul", + ["Mechanostrider Piloting"] = "Spell_Nature_Swiftness", + ["Meditation"] = "Spell_Nature_Sleep", + ["Melee Specialization"] = "INV_Axe_02", + ["Mend Pet"] = "Ability_Hunter_MendPet", + ["Mental Agility"] = "Ability_Hibernation", + ["Mental Strength"] = "Spell_Nature_EnchantArmor", + ["Mind Blast"] = "Spell_Shadow_UnholyFrenzy", + ["Mind Control"] = "Spell_Shadow_ShadowWordDominate", + ["Mind Flay"] = "Spell_Shadow_SiphonMana", + ["Mind Soothe"] = "Spell_Holy_MindSooth", + ["Mind Vision"] = "Spell_Holy_MindVision", + ["Mind-numbing Poison II"] = "Spell_Nature_NullifyDisease", + ["Mind-numbing Poison III"] = "Spell_Nature_NullifyDisease", + ["Mind-numbing Poison"] = "Spell_Nature_NullifyDisease", + ["Mining"] = "Spell_Fire_FlameBlades", +-- ["Misdirection"] = true, + ["Mocking Blow"] = "Ability_Warrior_PunishingBlow", +-- ["Molten Armor"] = true, + ["Mongoose Bite"] = "Ability_Hunter_SwiftStrike", + ["Monster Slaying"] = "INV_Misc_Head_Dragon_Black", + ["Moonfire"] = "Spell_Nature_StarFall", + ["Moonfury"] = "Spell_Nature_MoonGlow", + ["Moonglow"] = "Spell_Nature_Sentinal", + ["Moonkin Aura"] = "Spell_Nature_MoonGlow", + ["Moonkin Form"] = "Spell_Nature_ForceOfNature", + ["Mortal Shots"] = "Ability_PierceDamage", + ["Mortal Strike"] = "Ability_Warrior_SavageBlow", + ["Multi-Shot"] = "Ability_UpgradeMoonGlaive", + ["Murder"] = "Spell_Shadow_DeathScream", +-- ["Mutilate"] = true, + ["Natural Armor"] = "Spell_Nature_SpiritArmor", + ["Natural Shapeshifter"] = "Spell_Nature_WispSplode", + ["Natural Weapons"] = "INV_Staff_01", + ["Nature Resistance Totem"] = "Spell_Nature_NatureResistanceTotem", + ["Nature Resistance"] = "Spell_Nature_ResistNature", + ["Nature's Focus"] = "Spell_Nature_HealingWaveGreater", + ["Nature's Grace"] = "Spell_Nature_NaturesBlessing", + ["Nature's Grasp"] = "Spell_Nature_NaturesWrath", + ["Nature's Reach"] = "Spell_Nature_NatureTouchGrow", + ["Nature's Swiftness"] = "Spell_Nature_RavenForm", + ["Nightfall"] = "Spell_Shadow_Twilight", + ["Omen of Clarity"] = "Spell_Nature_CrystalBall", + ["One-Handed Axes"] = "INV_Axe_01", + ["One-Handed Maces"] = "INV_Mace_01", + ["One-Handed Swords"] = "Ability_MeleeDamage", + ["One-Handed Weapon Specialization"] = "INV_Sword_20", + ["Opening - No Text"] = "Temp", + ["Opening"] = "Temp", + ["Opportunity"] = "Ability_Warrior_WarCry", + ["Overpower"] = "Ability_MeleeDamage", +-- ["Pain Suppression"] = true, + ["Paranoia"] = "Spell_Shadow_AuraOfDarkness", + ["Parry"] = "Ability_Parry", + ["Pathfinding"] = "Ability_Mount_JungleTiger", + ["Perception"] = "Spell_Nature_Sleep", + ["Permafrost"] = "Spell_Frost_Wisp", + ["Pet Aggression"] = "Ability_Druid_Maul", + ["Pet Hardiness"] = "Ability_BullRush", + ["Pet Recovery"] = "Ability_Hibernation", + ["Pet Resistance"] = "Spell_Holy_BlessingOfAgility", + ["Phase Shift"] = "Spell_Shadow_ImpPhaseShift", + ["Pick Lock"] = "Spell_Nature_MoonKey", + ["Pick Pocket"] = "INV_Misc_Bag_11", + ["Piercing Howl"] = "Spell_Shadow_DeathScream", + ["Piercing Ice"] = "Spell_Frost_Frostbolt", + ["Plate Mail"] = "INV_Chest_Plate01", + ["Poison Cleansing Totem"] = "Spell_Nature_PoisonCleansingTotem", + ["Poisons"] = "Trade_BrewPoison", + ["Polearm Specialization"] = "INV_Weapon_Halbard_01", + ["Polearms"] = "INV_Spear_06", + ["Polymorph"] = "Spell_Nature_Polymorph", + ["Polymorph: Pig"] = "Spell_Magic_PolymorphPig", + ["Polymorph: Turtle"] = "Ability_Hunter_Pet_Turtle", + ["Portal: Darnassus"] = "Spell_Arcane_PortalDarnassus", + ["Portal: Ironforge"] = "Spell_Arcane_PortalIronForge", + ["Portal: Orgrimmar"] = "Spell_Arcane_PortalOrgrimmar", + ["Portal: Stormwind"] = "Spell_Arcane_PortalStormWind", + ["Portal: Thunder Bluff"] = "Spell_Arcane_PortalThunderBluff", + ["Portal: Undercity"] = "Spell_Arcane_PortalUnderCity", + ["Pounce Bleed"] = "Ability_Druid_SupriseAttack", + ["Pounce"] = "Ability_Druid_SupriseAttack", + ["Power Infusion"] = "Spell_Holy_PowerInfusion", + ["Power Word: Fortitude"] = "Spell_Holy_WordFortitude", + ["Power Word: Shield"] = "Spell_Holy_PowerWordShield", + ["Prayer of Fortitude"] = "Spell_Holy_PrayerOfFortitude", + ["Prayer of Healing"] = "Spell_Holy_PrayerOfHealing02", +-- ["Prayer of Mending"] = true, + ["Prayer of Shadow Protection"] = "Spell_Holy_PrayerofShadowProtection", + ["Prayer of Spirit"] = "Spell_Holy_PrayerofSpirit", + ["Precision"] = "Ability_Marksmanship", + ["Predatory Strikes"] = "Ability_Hunter_Pet_Cat", + ["Premeditation"] = "Spell_Shadow_Possession", + ["Preparation"] = "Spell_Shadow_AntiShadow", + ["Presence of Mind"] = "Spell_Nature_EnchantArmor", + ["Primal Fury"] = "Ability_Racial_Cannibalize", + ["Prowl"] = "Ability_Druid_SupriseAttack", + ["Psychic Scream"] = "Spell_Shadow_PsychicScream", + ["Pummel"] = "INV_Gauntlets_04", + ["Purge"] = "Spell_Nature_Purge", + ["Purification"] = "Spell_Frost_WizardMark", + ["Purify"] = "Spell_Holy_Purify", + ["Pursuit of Justice"] = "Spell_Holy_PersuitofJustice", + ["Pyroblast"] = "Spell_Fire_Fireball02", + ["Pyroclasm"] = "Spell_Fire_Volcano", + ["Quickness"] = "Ability_Racial_ShadowMeld", + ["Rain of Fire"] = "Spell_Shadow_RainOfFire", + ["Rake"] = "Ability_Druid_Disembowel", +-- ["Rampage"] = true, + ["Ram Riding"] = "Spell_Nature_Swiftness", + ["Ranged Weapon Specialization"] = "INV_Weapon_Rifle_06", + ["Rapid Concealment"] = "Ability_Ambush", + ["Rapid Fire"] = "Ability_Hunter_RunningShot", + ["Raptor Riding"] = "Spell_Nature_Swiftness", + ["Raptor Strike"] = "Ability_MeleeDamage", + ["Ravage"] = "Ability_Druid_Ravage", +-- ["Readiness"] = "Spell_Nature_Sleep", + ["Rebirth"] = "Spell_Nature_Reincarnation", + ["Recklessness"] = "Ability_CriticalStrike", + ["Reckoning"] = "Spell_Holy_BlessingOfStrength", + ["Redemption"] = "Spell_Holy_Resurrection", + ["Redoubt"] = "Ability_Defend", + ["Reflection"] = "Spell_Frost_WindWalkOn", + ["Regeneration"] = "Spell_Nature_Regenerate", + ["Regrowth"] = "Spell_Nature_ResistNature", + ["Reincarnation"] = "Spell_Nature_Reincarnation", + ["Rejuvenation"] = "Spell_Nature_Rejuvenation", + ["Relentless Strikes"] = "Ability_Warrior_DecisiveStrike", + ["Remorseless Attacks"] = "Ability_FiegnDead", + ["Remove Curse"] = "Spell_Holy_RemoveCurse", + ["Remove Insignia"] = "Temp", + ["Remove Lesser Curse"] = "Spell_Nature_RemoveCurse", + ["Rend"] = "Ability_Gouge", + ["Renew"] = "Spell_Holy_Renew", + ["Repentance"] = "Spell_Holy_PrayerOfHealing", + ["Resurrection"] = "Spell_Holy_Resurrection", + ["Retaliation"] = "Ability_Warrior_Challange", + ["Retribution Aura"] = "Spell_Holy_AuraOfLight", + ["Revenge Stun"] = "Ability_Warrior_Revenge", + ["Revenge"] = "Ability_Warrior_Revenge", + ["Reverberation"] = "Spell_Frost_FrostWard", + ["Revive Pet"] = "Ability_Hunter_BeastSoothe", +-- ["Righteous Defense"] = true, + ["Righteous Fury"] = "Spell_Holy_SealOfFury", + ["Rip"] = "Ability_GhoulFrenzy", + ["Riposte"] = "Ability_Warrior_Challange", + ["Ritual of Doom Effect"] = "Spell_Arcane_PortalDarnassus", + ["Ritual of Doom"] = "Spell_Shadow_AntiMagicShell", +-- ["Ritual of Souls"] = true, + ["Ritual of Summoning"] = "Spell_Shadow_Twilight", + ["Rockbiter Weapon"] = "Spell_Nature_RockBiter", + ["Rogue Passive"] = "Ability_Stealth", + ["Ruin"] = "Spell_Shadow_ShadowWordPain", + ["Rupture"] = "Ability_Rogue_Rupture", + ["Ruthlessness"] = "Ability_Druid_Disembowel", + ["Sacrifice"] = "Spell_Shadow_SacrificialShield", + ["Safe Fall"] = "INV_Feather_01", + ["Sanctity Aura"] = "Spell_Holy_MindVision", + ["Sap"] = "Ability_Sap", + ["Savage Fury"] = "Ability_Druid_Ravage", + ["Savage Strikes"] = "Ability_Racial_BloodRage", + ["Scare Beast"] = "Ability_Druid_Cower", + ["Scatter Shot"] = "Ability_GolemStormBolt", + ["Scorch"] = "Spell_Fire_SoulBurn", + ["Scorpid Poison"] = "Ability_PoisonSting", + ["Scorpid Sting"] = "Ability_Hunter_CriticalShot", + ["Screech"] = "Ability_Hunter_Pet_Bat", + ["Seal Fate"] = "Spell_Shadow_ChillTouch", +-- ["Seal of Blood"] = true, + ["Seal of Command"] = "Ability_Warrior_InnerRage", + ["Seal of Justice"] = "Spell_Holy_SealOfWrath", + ["Seal of Light"] = "Spell_Holy_HealingAura", + ["Seal of Righteousness"] = "Ability_ThunderBolt", + ["Seal of Wisdom"] = "Spell_Holy_RighteousnessAura", + ["Seal of the Crusader"] = "Spell_Holy_HolySmite", +-- ["Seal of Vengeance"] = true, + ["Searing Light"] = "Spell_Holy_SearingLightPriest", + ["Searing Pain"] = "Spell_Fire_SoulBurn", + ["Searing Totem"] = "Spell_Fire_SearingTotem", +-- ["Second Wind"] = true, + ["Seduction"] = "Spell_Shadow_MindSteal", +-- ["Seed of Corruption"] = true, + ["Sense Demons"] = "Spell_Shadow_Metamorphosis", + ["Sense Undead"] = "Spell_Holy_SenseUndead", + ["Sentry Totem"] = "Spell_Nature_RemoveCurse", + ["Serpent Sting"] = "Ability_Hunter_Quickshot", + ["Setup"] = "Spell_Nature_MirrorImage", + ["Shackle Undead"] = "Spell_Nature_Slow", + ["Shadow Affinity"] = "Spell_Shadow_ShadowWard", + ["Shadow Bolt"] = "Spell_Shadow_ShadowBolt", + ["Shadow Focus"] = "Spell_Shadow_BurningSpirit", + ["Shadow Mastery"] = "Spell_Shadow_ShadeTrueSight", + ["Shadow Protection"] = "Spell_Shadow_AntiShadow", + ["Shadow Reach"] = "Spell_Shadow_ChillTouch", + ["Shadow Resistance Aura"] = "Spell_Shadow_SealOfKings", + ["Shadow Resistance"] = "Spell_Shadow_AntiShadow", + ["Shadow Trance"] = "Spell_Shadow_Twilight", + ["Shadow Ward"] = "Spell_Shadow_AntiShadow", + ["Shadow Weaving"] = "Spell_Shadow_BlackPlague", +-- ["Shadow Word: Death"] = true, + ["Shadow Word: Pain"] = "Spell_Shadow_ShadowWordPain", + ["Shadowburn"] = "Spell_Shadow_ScourgeBuild", +-- ["Shadowfiend"] = true, + ["Shadowform"] = "Spell_Shadow_Shadowform", +-- ["Shadowfury"] = true, + ["Shadowguard"] = "Spell_Nature_LightningShield", + ["Shadowmeld Passive"] = "Ability_Ambush", + ["Shadowmeld"] = "Ability_Ambush", +-- ["Shadowstep"] = true, +-- ["Shamanistic Rage"] = true, + ["Sharpened Claws"] = "INV_Misc_MonsterClaw_04", + ["Shatter"] = "Spell_Frost_FrostShock", + ["Shell Shield"] = "Ability_Hunter_Pet_Turtle", + ["Shield Bash"] = "Ability_Warrior_ShieldBash", + ["Shield Block"] = "Ability_Defend", + ["Shield Slam"] = "INV_Shield_05", + ["Shield Specialization"] = "INV_Shield_06", + ["Shield Wall"] = "Ability_Warrior_ShieldWall", + ["Shield"] = "INV_Shield_04", +-- ["Shiv"] = true, + ["Shoot Bow"] = "Ability_Marksmanship", + ["Shoot Crossbow"] = "Ability_Marksmanship", + ["Shoot Gun"] = "Ability_Marksmanship", + ["Shoot"] = "Ability_ShootWand", + ["Shred"] = "Spell_Shadow_VampiricAura", + ["Silence"] = "Spell_Shadow_ImpPhaseShift", +-- ["Silencing Shot"] = true, + ["Silent Resolve"] = "Spell_Nature_ManaRegenTotem", + ["Sinister Strike"] = "Spell_Shadow_RitualOfSacrifice", + ["Siphon Life"] = "Spell_Shadow_Requiem", + ["Skinning"] = "INV_Misc_Pelt_Wolf_01", + ["Slam"] = "Ability_Warrior_DecisiveStrike", + ["Slice and Dice"] = "Ability_Rogue_SliceDice", +-- ["Slow"] = true, + ["Slow Fall"] = "Spell_Magic_FeatherFall", + ["Smelting"] = "Spell_Fire_FlameBlades", + ["Smite"] = "Spell_Holy_HolySmite", +-- ["Snake Trap"] = true, + ["Soothe Animal"] = "Ability_Hunter_BeastSoothe", + ["Soothing Kiss"] = "Spell_Shadow_SoothingKiss", + ["Soul Fire"] = "Spell_Fire_Fireball02", + ["Soul Link"] = "Spell_Shadow_GatherShadows", +-- ["Soul Siphon"] = true, +-- ["Soulshatter"] = true, + ["Soulstone Resurrection"] = "INV_Misc_Orb_04", + ["Spell Lock"] = "Spell_Shadow_MindRot", +-- ["Spellsteal"] = true, +-- ["Spell Reflection"] = true, + ["Spell Warding"] = "Spell_Holy_SpellWarding", + ["Spirit Bond"] = "Ability_Druid_DemoralizingRoar", + ["Spirit Tap"] = "Spell_Shadow_Requiem", + ["Spirit of Redemption"] = "INV_Enchant_EssenceEternalLarge", +-- ["Spiritual Attunement"] = true, + ["Spiritual Focus"] = "Spell_Arcane_Blink", + ["Spiritual Guidance"] = "Spell_Holy_SpiritualGuidence", + ["Spiritual Healing"] = "Spell_Nature_MoonGlow", + ["Sprint"] = "Ability_Rogue_Sprint", +-- ["Stance Mastery"] = true, + ["Starfire"] = "Spell_Arcane_StarFire", + ["Starshards"] = "Spell_Arcane_StarFire", + ["Staves"] = "INV_Staff_08", +-- ["Steady Shot"] = true, + ["Stealth"] = "Ability_Stealth", + ["Stoneclaw Totem"] = "Spell_Nature_StoneClawTotem", + ["Stoneform"] = "Spell_Shadow_UnholyStrength", + ["Stoneskin Totem"] = "Spell_Nature_StoneSkinTotem", + ["Stormstrike"] = "Spell_Holy_SealOfMight", + ["Strength of Earth Totem"] = "Spell_Nature_EarthBindTotem", + ["Stuck"] = "Spell_Shadow_Teleport", + ["Subtlety"] = "Ability_EyeOfTheOwl", + ["Suffering"] = "Spell_Shadow_BlackPlague", + ["Summon Charger"] = "Ability_Mount_Charger", + ["Summon Dreadsteed"] = "Ability_Mount_Dreadsteed", +-- ["Summon Felguard"] = true, + ["Summon Felhunter"] = "Spell_Shadow_SummonFelHunter", + ["Summon Felsteed"] = "Spell_Nature_Swiftness", + ["Summon Imp"] = "Spell_Shadow_SummonImp", + ["Summon Succubus"] = "Spell_Shadow_SummonSuccubus", + ["Summon Voidwalker"] = "Spell_Shadow_SummonVoidWalker", + ["Summon Warhorse"] = "Spell_Nature_Swiftness", +-- ["Summon Water Elemental"] = true, + ["Sunder Armor"] = "Ability_Warrior_Sunder", + ["Suppression"] = "Spell_Shadow_UnsummonBuilding", + ["Surefooted"] = "Ability_Kick", + ["Survivalist"] = "Spell_Shadow_Twilight", + ["Sweeping Strikes"] = "Ability_Rogue_SliceDice", + ["Swipe"] = "INV_Misc_MonsterClaw_03", + ["Sword Specialization"] = "INV_Sword_27", + ["Tactical Mastery"] = "Spell_Nature_EnchantArmor", + ["Tailoring"] = "Trade_Tailoring", + ["Tainted Blood"] = "Spell_Shadow_LifeDrain", + ["Tame Beast"] = "Ability_Hunter_BeastTaming", + ["Tamed Pet Passive"] = "Ability_Mount_PinkTiger", + ["Taunt"] = "Spell_Nature_Reincarnation", + ["Teleport: Darnassus"] = "Spell_Arcane_TeleportDarnassus", + ["Teleport: Ironforge"] = "Spell_Arcane_TeleportIronForge", + ["Teleport: Moonglade"] = "Spell_Arcane_TeleportMoonglade", + ["Teleport: Orgrimmar"] = "Spell_Arcane_TeleportOrgrimmar", + ["Teleport: Stormwind"] = "Spell_Arcane_TeleportStormWind", + ["Teleport: Thunder Bluff"] = "Spell_Arcane_TeleportThunderBluff", + ["Teleport: Undercity"] = "Spell_Arcane_TeleportUnderCity", +-- ["The Beast Within"] = true, + ["The Human Spirit"] = "INV_Enchant_ShardBrilliantSmall", + ["Thick Hide"] = "INV_Misc_Pelt_Bear_03", + ["Thorns"] = "Spell_Nature_Thorns", + ["Throw"] = "Ability_Throw", + ["Throwing Specialization"] = "INV_ThrowingAxe_03", + ["Throwing Weapon Specialization"] = "INV_ThrowingKnife_01", + ["Thrown"] = "INV_ThrowingKnife_02", + ["Thunder Clap"] = "Spell_Nature_ThunderClap", + ["Thundering Strikes"] = "Ability_ThunderBolt", + ["Thunderstomp"] = "Ability_Hunter_Pet_Gorilla", + ["Tidal Focus"] = "Spell_Frost_ManaRecharge", + ["Tidal Mastery"] = "Spell_Nature_Tranquility", + ["Tiger Riding"] = "Spell_Nature_Swiftness", + ["Tiger's Fury"] = "Ability_Mount_JungleTiger", + ["Torment"] = "Spell_Shadow_GatherShadows", + ["Totem"] = "Spell_Nature_StoneClawTotem", + ["Totem of Wrath"] = "Spell_Fire_TotemOfWrath", + ["Totemic Focus"] = "Spell_Nature_MoonGlow", + ["Touch of Weakness"] = "Spell_Shadow_DeadofNight", + ["Toughness"] = "Spell_Holy_Devotion", + ["Track Beasts"] = "Ability_Tracking", + ["Track Demons"] = "Spell_Shadow_SummonFelHunter", + ["Track Dragonkin"] = "INV_Misc_Head_Dragon_01", + ["Track Elementals"] = "Spell_Frost_SummonWaterElemental", + ["Track Giants"] = "Ability_Racial_Avatar", + ["Track Hidden"] = "Ability_Stealth", + ["Track Humanoids"] = "Ability_Tracking", + ["Track Undead"] = "Spell_Shadow_DarkSummoning", + ["Tranquil Air Totem"] = "Spell_Nature_Brilliance", + ["Tranquil Spirit"] = "Spell_Holy_ElunesGrace", + ["Tranquility"] = "Spell_Nature_Tranquility", + ["Tranquilizing Shot"] = "Spell_Nature_Drowsy", + ["Trap Mastery"] = "Ability_Ensnare", + ["Travel Form"] = "Ability_Druid_TravelForm", +-- ["Tree of Life"] = true, + ["Tremor Totem"] = "Spell_Nature_TremorTotem", + ["Trueshot Aura"] = "Ability_TrueShot", + ["Turn Undead"] = "Spell_Holy_TurnUndead", + ["Two-Handed Axes and Maces"] = "INV_Axe_10", + ["Two-Handed Axes"] = "INV_Axe_04", + ["Two-Handed Maces"] = "INV_Mace_04", + ["Two-Handed Swords"] = "Ability_MeleeDamage", + ["Two-Handed Weapon Specialization"] = "INV_Axe_09", + ["Unarmed"] = "Ability_GolemThunderClap", + ["Unbreakable Will"] = "Spell_Magic_MageArmor", + ["Unbridled Wrath Effect"] = "Spell_Nature_StoneClawTotem", + ["Unbridled Wrath"] = "Spell_Nature_StoneClawTotem", + ["Undead Horsemanship"] = "Spell_Nature_Swiftness", + ["Underwater Breathing"] = "Spell_Shadow_DemonBreath", + ["Unending Breath"] = "Spell_Shadow_DemonBreath", + ["Unholy Power"] = "Spell_Shadow_ShadowWordDominate", + ["Unleashed Fury"] = "Ability_BullRush", +-- ["Unleashed Rage"] = true, +-- ["Unstable Affliction"] = true, + ["Unyielding Faith"] = "Spell_Holy_UnyieldingFaith", + ["Vampiric Embrace"] = "Spell_Shadow_UnsummonBuilding", + ["Vanish"] = "Ability_Vanish", + ["Vanished"] = "Ability_Vanish", +-- ["Vampiric Touch"] = true, + ["Vengeance"] = "Spell_Nature_Purge", +-- ["Victory Rush"] = true, + ["Vigor"] = "Spell_Nature_EarthBindTotem", + ["Vile Poisons"] = "Ability_Rogue_FeignDeath", + ["Vindication"] = "Spell_Holy_Vindication", + ["Viper Sting"] = "Ability_Hunter_AimedShot", + ["Volley"] = "Ability_Marksmanship", + ["Wand Specialization"] = "INV_Wand_01", + ["Wands"] = "Ability_ShootWand", + ["War Stomp"] = "Ability_WarStomp", + ["Water Breathing"] = "Spell_Shadow_DemonBreath", +-- ["Water Shield"] = true, + ["Water Walking"] = "Spell_Frost_WindWalkOn", +-- ["Waterbolt"] = true, + ["Weakened Soul"] = "Spell_Holy_AshesToAshes", + ["Whirlwind"] = "Ability_Whirlwind", + ["Will of the Forsaken"] = "Spell_Shadow_RaiseDead", + ["Windfury Totem"] = "Spell_Nature_Windfury", + ["Windfury Weapon"] = "Spell_Nature_Cyclone", + ["Windwall Totem"] = "Spell_Nature_EarthBind", + ["Wing Clip"] = "Ability_Rogue_Trip", + ["Winter's Chill"] = "Spell_Frost_ChillingBlast", + ["Wisp Spirit"] = "Spell_Nature_WispSplode", + ["Wolf Riding"] = "Spell_Nature_Swiftness", + ["Wound Poison II"] = "INV_Misc_Herb_16", + ["Wound Poison III"] = "INV_Misc_Herb_16", + ["Wound Poison IV"] = "INV_Misc_Herb_16", + ["Wound Poison"] = "INV_Misc_Herb_16", + ["Wrath"] = "Spell_Nature_AbolishMagic", + ["Wrath of Air Totem"] = "Spell_Nature_SlowingTotem", + ["Wyvern Sting"] = "INV_Spear_02", +} + +BabbleSpell:Debug() +BabbleSpell:SetStrictness(true) + +function BabbleSpell:GetSpellIcon(spell) + self:argCheck(spell, 2, "string") + local icon = spellIcons[spell] or spellIcons[self:HasReverseTranslation(spell) and self:GetReverseTranslation(spell) or false] + if not icon then + return nil + end + return "Interface\\Icons\\" .. icon +end + +function BabbleSpell:GetShortSpellIcon(spell) + self:argCheck(spell, 2, "string") + return spellIcons[spell] or spellIcons[self:HasReverseTranslation(spell) and self:GetReverseTranslation(spell) or false] +end + +AceLibrary:Register(BabbleSpell, MAJOR_VERSION, MINOR_VERSION) +BabbleSpell = nil diff --git a/Libs/Deformat-2.0/Deformat-2.0.lua b/Libs/Deformat-2.0/Deformat-2.0.lua new file mode 100644 index 0000000..901590c --- /dev/null +++ b/Libs/Deformat-2.0/Deformat-2.0.lua @@ -0,0 +1,343 @@ +--[[ +Name: Deformat-2.0 +Revision: $Rev: 6804 $ +Author(s): ckknight (ckknight@gmail.com) +Website: http://ckknight.wowinterface.com/ +Documentation: http://wiki.wowace.com/index.php/Deformat-2.0 +SVN: http://svn.wowace.com/root/trunk/Deformat/Deformat-2.0 +Description: A library to deformat format strings. +Dependencies: AceLibrary +]] + +local MAJOR_VERSION = "Deformat-2.0" +local MINOR_VERSION = "$Revision: 6804 $" + + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +local Deformat = {} + +do + local sequences = { + ["%d*d"] = "%%-?%%d+", + ["s"] = ".+", + ["[fg]"] = "%%-?%%d+%%.%%d+", + ["%%%.%d[fg]"] = "%%-?%%d+%%.?%%d*", + ["c"] = ".", + } + local curries = {} + + local function doNothing(item) + return item + end + local v = {} + + local function concat(a1, a2, a3, a4, a5) + local left, right + if not a2 then + return a1 + elseif not a3 then + left, right = a1, a2 + elseif not a4 then + return concat(concat(a1, a2), a3) + elseif not a5 then + return concat(concat(concat(a1, a2), a3), a4) + else + return concat(concat(concat(concat(a1, a2), a3), a4), a5) + end + if not string.find(left, "%%1%$") and not string.find(right, "%%1%$") then + return left .. right + elseif not string.find(right, "%%1%$") then + local i + for j = 9, 1, -1 do + if string.find(left, "%%" .. j .. "%$") then + i = j + break + end + end + while true do + local first + local firstPat + for x, y in pairs(sequences) do + local i = string.find(right, "%%" .. x) + if not first or (i and i < first) then + first = i + firstPat = x + end + end + if not first then + break + end + i = i + 1 + right = string.gsub(right, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1") + end + return left .. right + elseif not string.find(left, "%%1%$") then + local i = 1 + while true do + local first + local firstPat + for x, y in pairs(sequences) do + local i = string.find(left, "%%" .. x) + if not first or (i and i < first) then + first = i + firstPat = x + end + end + if not first then + break + end + i = i + 1 + left = string.gsub(left, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1") + end + return concat(left, right) + else + local i + for j = 9, 1, -1 do + if string.find(left, "%%" .. j .. "%$") then + i = j + break + end + end + local j + for k = 9, 1, -1 do + if string.find(right, "%%" .. k .. "%$") then + j = k + break + end + end + for k = j, 1, -1 do + right = string.gsub(right, "%%" .. k .. "%$", "%%" .. k + i .. "%$") + end + return left .. right + end + end + + local function Curry(a1, a2, a3, a4, a5) + local pattern = concat(a1, a2, a3, a4, a5) + if not string.find(pattern, "%%1%$") then + local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + local f = {} + local i = 0 + while true do + local first + local firstPat + for x, y in pairs(sequences) do + local i = string.find(unpattern, "%%%%" .. x) + if not first or (i and i < first) then + first = i + firstPat = x + end + end + if not first then + break + end + unpattern = string.gsub(unpattern, "%%%%" .. firstPat, "(" .. sequences[firstPat] .. ")", 1) + i = i + 1 + if firstPat == "c" or firstPat == "s" then + table.insert(f, doNothing) + else + table.insert(f, tonumber) + end + end + unpattern = "^" .. unpattern .. "$" + local _,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india + if i == 0 then + return + elseif i == 1 then + return function(text) + _,_,alpha = string.find(text, unpattern) + if alpha then + return f[1](alpha) + end + end + elseif i == 2 then + return function(text) + _,_,alpha, bravo = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo) + end + end + elseif i == 3 then + return function(text) + _,_,alpha, bravo, charlie = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie) + end + end + elseif i == 4 then + return function(text) + _,_,alpha, bravo, charlie, delta = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta) + end + end + elseif i == 5 then + return function(text) + _,_,alpha, bravo, charlie, delta, echo = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo) + end + end + elseif i == 6 then + return function(text) + _,_,alpha, bravo, charlie, delta, echo, foxtrot = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot) + end + end + elseif i == 7 then + return function(text) + _,_,alpha, bravo, charlie, delta, echo, foxtrot, golf = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf) + end + end + elseif i == 8 then + return function(text) + _,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel) + end + end + else + return function(text) + _,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india = string.find(text, unpattern) + if alpha then + return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel), f[9](india) + end + end + end + else + local o = {} + local f = {} + local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") + local i = 1 + while true do + local pat + for x, y in pairs(sequences) do + if not pat and string.find(unpattern, "%%%%" .. i .. "%%%$" .. x) then + pat = x + break + end + end + if not pat then + break + end + unpattern = string.gsub(unpattern, "%%%%" .. i .. "%%%$" .. pat, "(" .. sequences[pat] .. ")", 1) + if pat == "c" or pat == "s" then + table.insert(f, doNothing) + else + table.insert(f, tonumber) + end + i = i + 1 + end + i = 1 + string.gsub(pattern, "%%(%d)%$", function(w) o[i] = tonumber(w); i = i + 1; end) + v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = nil + for x, y in pairs(f) do + v[x] = f[y] + end + for x, y in pairs(v) do + f[x] = v[x] + end + unpattern = "^" .. unpattern .. "$" + i = i - 1 + if i == 0 then + return function(text) + return + end + elseif i == 1 then + return function(text) + _,_,v[1] = string.find(text, unpattern) + if v[1] then + return f[1](v[1]) + end + end + elseif i == 2 then + return function(text) + _,_,v[1],v[2] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]) + end + end + elseif i == 3 then + return function(text) + _,_,v[1],v[2],v[3] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]) + end + end + elseif i == 4 then + return function(text) + _,_,v[1],v[2],v[3],v[4] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]) + end + end + elseif i == 5 then + return function(text) + _,_,v[1],v[2],v[3],v[4],v[5] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]) + end + end + elseif i == 6 then + return function(text) + _,_,v[1],v[2],v[3],v[4],v[5],v[6] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]) + end + end + elseif i == 7 then + return function(text) + _,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]) + end + end + elseif i == 8 then + return function(text) + _,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]]) + end + end + else + return function(text) + _,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = string.find(text, unpattern) + if v[1] then + return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]]), f[9](v[o[9]]) + end + end + end + end + end + + function Deformat:Deformat(text, a1, a2, a3, a4, a5) + self:argCheck(text, 2, "string") + self:argCheck(a1, 3, "string") + local pattern = a1 + if a5 then + pattern = a1 .. a2 .. a3 .. a4 .. a5 + elseif a4 then + pattern = a1 .. a2 .. a3 .. a4 + elseif a3 then + pattern = a1 .. a2 .. a3 + elseif a2 then + pattern = a1 .. a2 + end + if curries[pattern] == nil then + curries[pattern] = Curry(a1, a2, a3, a4, a5) + end + return curries[pattern](text) + end +end + +local mt = getmetatable(Deformat) or {} +mt.__call = Deformat.Deformat +setmetatable(Deformat, mt) + +AceLibrary:Register(Deformat, MAJOR_VERSION, MINOR_VERSION) +Deformat = nil diff --git a/Libs/Gratuity-2.0/Gratuity-2.0.lua b/Libs/Gratuity-2.0/Gratuity-2.0.lua new file mode 100644 index 0000000..0cf3782 --- /dev/null +++ b/Libs/Gratuity-2.0/Gratuity-2.0.lua @@ -0,0 +1,220 @@ +--[[ +Name: Gratuity-2.0 +Revision: $Rev: 11053 $ +Author: Tekkub Stoutwrithe (tekkub@gmail.com) +Website: http://wiki.wowace.com/index.php/GratuityLib +Documentation: http://wiki.wowace.com/index.php/Gratuity-2.0_API_Documentation +SVN: svn://svn.wowace.com/root/trunk/GratuityLib/Gratuity-2.0 +Description: Tooltip parsing library +Dependencies: AceLibrary, (optional) Compost-2.0, (optional) Deformat-2.0 +]] + +local vmajor, vminor = "Gratuity-2.0", "$Revision: 11053 $" + +if not AceLibrary then error(vmajor .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(vmajor, vminor) then return end + +local lib = {} +local methods = { + "SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem", + "SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem", + "SetLootItem", "SetLootRollItem", "SetMerchantItem", "SetPetAction", "SetPlayerBuff", + "SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", "SetSendMailItem", "SetShapeshift", + "SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", "SetTradeTargetItem", + "SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff", +} + + +-- Activate a new instance of this library +local function activate(self, oldLib, oldDeactivate) + if oldLib then self.vars = oldLib.vars + else + self.vars = {} + self:CreateTooltip() + end + + self:CreateSetMethods() + + if oldDeactivate then oldDeactivate(oldLib) end +end + + +function lib:InitCompost() + if not self.vars.compost and AceLibrary:HasInstance("Compost-2.0") then self.vars.compost = AceLibrary("Compost-2.0") end +end + + +function lib:CreateTooltip() + local tt = CreateFrame("GameTooltip") + + self.vars.tooltip = tt + tt:SetOwner(tt, "ANCHOR_NONE") +-- tooltip:SetParent() + + self.vars.Llines, self.vars.Rlines = {}, {} + for i=1,30 do + self.vars.Llines[i], self.vars.Rlines[i] = tt:CreateFontString(), tt:CreateFontString() + self.vars.Llines[i]:SetFontObject(GameFontNormal) + self.vars.Rlines[i]:SetFontObject(GameFontNormal) + tt:AddFontStrings(self.vars.Llines[i], self.vars.Rlines[i]) + end +end + + +-- Clears the tooltip completely, none of this "erase left, hide right" crap blizzard does +function lib:Erase() + self.vars.tooltip:ClearLines() -- Ensures tooltip's NumLines is reset + for i=1,30 do self.vars.Rlines[i]:SetText() end -- Clear text from right side (ClearLines only hides them) + if not self.vars.tooltip:IsOwned(self.vars.tooltip) then self.vars.tooltip:SetOwner(self.vars.tooltip, "ANCHOR_NONE") end + self:assert(self.vars.tooltip:IsOwned(self.vars.tooltip), "Gratuity's tooltip is not scanable") +end + + +-- Get the number of lines +-- Arg: endln - If passed and tooltip's NumLines is higher, endln is returned back +function lib:NumLines(endln) + local num = self.vars.tooltip:NumLines() + return endln and num > endln and endln or num or 0 +end + +local FindDefault = function(str, pattern) + return string.find(str, pattern); +end; + +local FindExact = function(str, pattern) + if (str == pattern) then + return string.find(str, pattern); + end; +end; + +-- If text is found on tooltip then results of string.find are returned +-- Args: +-- txt - The text string to find +-- startln - First tooltip line to check, default 1 +-- endln - Last line to test, default 30 +-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored +-- exact - the compare will be an exact match vs the default behaviour of +function lib:Find(txt, startln, endln, ignoreleft, ignoreright, exact) + local searchFunction = FindDefault; + if (exact == true) then + searchFunction = FindExact; + end; + self:argCheck(txt, 2, "string", "number") + local t1, t2 = type(startln or 1), type(self:NumLines(endln)) + if (t1 ~= "number" or t2 ~= "number") then print(t1, t2, (startln or 1),self:NumLines(endln)) end + for i=(startln or 1),self:NumLines(endln) do + if not ignoreleft then + local txtl = self.vars.Llines[i]:GetText() + if (txtl and searchFunction(txtl, txt)) then return string.find(txtl, txt) end + end + + if not ignoreright then + local txtr = self.vars.Rlines[i]:GetText() + if (txtr and searchFunction(txtr, txt)) then return string.find(txtr, txt) end + end + end +end + + +-- Calls Find many times. +-- Args are passed directly to Find, t1-t10 replace the txt arg +-- Returns Find results for the first match found, if any +function lib:MultiFind(startln, endln, ignoreleft, ignoreright, t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) + self:argCheck(t1, 6, "string", "number") + if t1 and self:Find(t1, startln, endln, ignoreleft, ignoreright) then return self:Find(t1, startln, endln, ignoreleft, ignoreright) + elseif t2 then return self:MultiFind(startln, endln, ignoreleft, ignoreright, t2,t3,t4,t5,t6,t7,t8,t9,t10) end +end + + +local deformat +-- If text is found on tooltip then results of deformat:Deformat are returned +-- Args: +-- txt - The text string to deformat and serach for +-- startln - First tooltip line to check, default 1 +-- endln - Last line to test, default 30 +-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored +function lib:FindDeformat(txt, startln, endln, ignoreleft, ignoreright) + self:argCheck(txt, 2, "string", "number") + if not deformat then + self:assert(AceLibrary:HasInstance("Deformat-2.0"), "FindDeformat requires Deformat-2.0 to be available") + deformat = AceLibrary("Deformat-2.0") + end + + for i=(startln or 1),self:NumLines(endln) do + if not ignoreleft then + local txtl = self.vars.Llines[i]:GetText() + if (txtl and deformat(txtl, txt)) then return deformat(txtl, txt) end + end + + if not ignoreright then + local txtr = self.vars.Rlines[i]:GetText() + if (txtr and deformat(txtr, txt)) then return deformat(txtr, txt) end + end + end +end + + +-- Returns a table of strings pulled from the tooltip, or nil if no strings in tooltip +-- Args: +-- startln - First tooltip line to check, default 1 +-- endln - Last line to test, default 30 +-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored +function lib:GetText(startln, endln, ignoreleft, ignoreright) + self:InitCompost() + local retval + + for i=(startln or 1),(endln or 30) do + local txtl, txtr + if not ignoreleft then txtl = self.vars.Llines[i]:GetText() end + if not ignoreright then txtr = self.vars.Rlines[i]:GetText() end + if txtl or txtr then + if not retval then retval = self.vars.compost and self.vars.compost:Acquire() or {} end + local t = self.vars.compost and self.vars.compost:Acquire(txtl, txtr) or {txtl, txtr} + table.insert(retval, t) + end + end + + return retval +end + + +-- Returns the text from a specific line (both left and right unless second arg is true) +-- Args: +-- line - the line number you wish to retrieve +-- getright - if passed the right line will be returned, if not the left will be returned +function lib:GetLine(line, getright) + self:argCheck(line, 2, "number") + if self.vars.tooltip:NumLines() < line then return end + if getright then return self.vars.Rlines[line] and self.vars.Rlines[line]:GetText() + elseif self.vars.Llines[line] then + return self.vars.Llines[line]:GetText(), self.vars.Rlines[line]:GetText() + end +end + + +----------------------------------- +-- Set tooltip methods -- +----------------------------------- + +-- These methods are designed to immitate the GameTooltip API +local testmethods = { + SetAction = function(id) return HasAction(id) end, +} +local gettrue = function() return true end +function lib:CreateSetMethods() + for _,m in pairs(methods) do + local meth = m + local func = testmethods[meth] or gettrue + self[meth] = function(self,a1,a2,a3,a4) + self:Erase() + if not func(a1,a2,a3,a4) then return end + return self:pcall(self.vars.tooltip[meth], self.vars.tooltip,a1,a2,a3,a4) end + end +end + + +-------------------------------- +-- Load this bitch! -- +-------------------------------- +AceLibrary:Register(lib, vmajor, vminor, activate) +lib = nil diff --git a/Libs/SpellCache-1.0/SpellCache-1.0.lua b/Libs/SpellCache-1.0/SpellCache-1.0.lua new file mode 100644 index 0000000..140bb74 --- /dev/null +++ b/Libs/SpellCache-1.0/SpellCache-1.0.lua @@ -0,0 +1,304 @@ +--[[ +Name: SpellCache-1.0 +Revision: $Rev: 15969 $ +Author(s): Nightdew (denzsolnightdew@gmail.com) +Website: http://www.wowace.com/index.php/SpellCache-1.0 +Documentation: http://www.wowace.com/index.php/SpellCache-1.0 +SVN: http://svn.wowace.com/root/trunk/SpellCache/SpellCache-1.0 +Description: Library that caches spells to speed up look ups +Dependencies: AceLibrary, AceDebug-2.0, AceEvent-2.0, Deformat-2.0 +]] + +--, Gratuity-2.0 + +local MAJOR_VERSION = "SpellCache-1.0" +local MINOR_VERSION = "$Revision: 15969 $" + +if (not AceLibrary) then + error(MAJOR_VERSION .. " requires AceLibrary.") +elseif (not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION)) then + return +end + +local function CheckDependencies(dependencies) + for index, value in ipairs(dependencies) do + if (not AceLibrary:HasInstance(value)) then + error(format("%s requires %s to function properly", MAJOR_VERSION, value)) + end + end +end + +local dependencyLibraries = { + "AceDebug-2.0", + "AceEvent-2.0", + "Deformat-2.0", + --"Gratuity-2.0" +} + +CheckDependencies(dependencyLibraries) + +local aceDebug = AceLibrary("AceDebug-2.0") +local aceEvent = AceLibrary("AceEvent-2.0") +local deformat = AceLibrary("Deformat-2.0") + +--Create Library Object +local SpellCache = {} + +--Embed all needed mixins into the Library Object SpellCache +aceDebug:embed(SpellCache) +aceEvent:embed(SpellCache) + +-- +-- Initialization methods. +-- + +local function GetSpellRankPattern(self, spellRank) + local rankPattern, changeCount = string.gsub(spellRank, "%d+", "%%d") + if (changeCount > 0) then + self.RankPattern = rankPattern; + self.FullPattern = format("%s(%s)", "%s", rankPattern) + self:LevelDebug(2, "DetectRankPattern", spellRank, self.RankPattern, self.FullPattern) + return rankPattern + end +end + +local function GetSpellRankNumber(self, spellRank) + self:LevelDebug(3, "GetSpellRankNumber1", spellRank) + if (spellRank and (spellRank ~= "")) then + local rankPattern = self.RankPattern or GetSpellRankPattern(self, spellRank) + if (rankPattern) then + self:LevelDebug(3, "GetSpellRankNumber2", rankPattern, spellRank) + local spellRankNumber = self:GetRankNumber(spellRank) + return spellRankNumber + end + end +end + +local function ResetVariables(self) + if (not self:IsInitialized()) then + return + end + + --clear hash + setmetatable(self.hash, nil) + for k in pairs(self.hash) do + self.hash[k] = nil + end + table.setn(self.hash, 0); + + local spellTabCount = GetNumSpellTabs() + local tabName, tabTexture, tabStart, tabOffset = GetSpellTabInfo(spellTabCount) + local spellCount = tabStart + tabOffset + + self:LevelDebug(3, "ResetVariables", spellTabCount, tabName, tabTexture, tabStart, tabOffset, spellCount) + + local spellData, spellName, spellRank, spellNamePrevious, spellNameNew = nil; + for i = 1, spellCount do + spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL) + + spellNameNew = spellNamePrevious ~= spellName + spellNamePrevious = spellName + + spellData = self.data[spellName] or {} + + if (spellNameNew) then + self.hash[i] = spellName + self.data[spellName] = spellData + spellData.IdStart = i + else + self.hash[i] = spellData.IdStart + end + + spellData.IdStop = i + + spellData.Rank = GetSpellRankNumber(self, spellRank); + + self:LevelDebug(3, + spellData.IdStart, + spellData.IdStop, + spellData.Rank + ) + end + self:TriggerEvent("SpellCache_Updated") +end + +local function InitializeVariables(self) + --will collect spells as they are being cast. + --SpellName -> Data + self.data = {} + --SpellId -> SpellName or SpellId + self.hash = {} + + ResetVariables(self) +end + +-- +-- Event Registration +-- + +local function InitializeEventRegisters(self) + self:RegisterEvent("LEARNED_SPELL_IN_TAB") + self:RegisterEvent("PLAYER_ENTERING_WORLD", "LEARNED_SPELL_IN_TAB") + --Supposedly not needed, and will spam too much + --self:RegisterEvent("SPELLS_CHANGED", "LEARNED_SPELL_IN_TAB") +end + +--update whatever spells are there! +function SpellCache:LEARNED_SPELL_IN_TAB() + self.isInitialized = true + ResetVariables(self) +end + +function SpellCache:IsInitialized() + return self.isInitialized == true +end + +-- +-- Activate method +-- + +local function activate(self, oldLib, oldDeactivate) + --self:SetDebugLevel(3); + if (oldLib) then + oldLib:UnregisterAllEvents() + end + + --Default code to clean up the oldlib + if (oldDeactivate) then + oldDeactivate(oldLib) + end + + InitializeVariables(self) + InitializeEventRegisters(self) +end + +-- +-- Util Methods +-- + +-- +-- External Methods +-- + +function SpellCache:GetRankNumber(spellRankText) + self:LevelDebug(3, "SpellCache:GetRankNumber1", spellRankText) + self:argCheck(spellRankText, 2, "string") + local spellRankNumber = deformat:Deformat(spellRankText, self.RankPattern) + self:LevelDebug(3, "SpellCache:GetRankNumber2", spellRankText, self.RankPattern, spellRankNumber) + return spellRankNumber +end + +function SpellCache:GetRankText(spellRankNumber) + self:argCheck(spellRankNumber, 2, "number") + local spellRankText = format(self.RankPattern, spellRankNumber) + self:LevelDebug(2, "GetRankText", spellRankNumber, self.RankPattern, spellRankText) + return spellRankText +end + +function SpellCache:GetRanklessSpellName(spellName) + self:argCheck(spellName, 2, "string") + + --self:LevelDebug(2, "GetRanklessSpellName1", spellName) + --For those that like to cast spells with SpellName() lets take out the () + spellName = string.gsub(spellName, "%(%)$", "") + --self:LevelDebug(2, "GetRanklessSpellName2", spellName) + + if (self.FullPattern) then + local sName, sRank = deformat:Deformat(spellName, self.FullPattern) + self:LevelDebug(2, "GetRanklessSpellName", spellName, sName, sRank) + if (sName and sRank) then + return sName, sRank + end + end + return spellName +end + +function SpellCache:GetSpellNameText(spellName, spellRankNumber) + self:argCheck(spellName, 2, "string") + self:argCheck(spellRankNumber, 3, "number", "nil") + + local fullSpellName + if (not spellRankNumber) then + fullSpellName = spellName + else + fullSpellName = format(self.FullPattern, spellName, spellRankNumber) + end + self:LevelDebug(2, "GetSpellNameText", spellName, spellRankNumber, self.FullPattern, fullSpellName) + return fullSpellName +end + +-- 24, ignore all +-- Arcane Intellect, nil +-- Arcane Intellect, 3 +-- Arcane Intellect, Rank 3 +-- Arcane Intellect(Rank 2), nil +-- Arcane Intellect(Rank 2), 3 +-- Arcane Intellect(Rank 2), Rank 3 +function SpellCache:GetSpellData(spellNameOrId, spellRankNumberOrText) + self:argCheck(spellNameOrId, 2, "string", "number") + self:argCheck(spellRank, 3, "string", "number", "nil") + self:LevelDebug(2, ">GetSpellData", spellNameOrId, spellRankNumberOrText) + + local sId, sName, sRank + if (type(spellNameOrId) == "number") then + sId = tonumber(spellNameOrId) + sName = self.hash[sId] + --Doesnt exist + if (not sName) then + return + end + --sId > IdStart + if (type(sName) == "number") then + sName = self.hash[sName] + end + self:LevelDebug(2, "GetSpellData1", sId, sName) + else + sName, sRank = self:GetRanklessSpellName(spellNameOrId) + + if (not sRank) then + sRank = spellRankNumberOrText; + if (type(sRank) == "string") then + self:LevelDebug(2, "GetSpellData2", sRank) + sRank = GetSpellRankNumber(self, sRank); + self:LevelDebug(2, "GetSpellData3", sRank) + end + end + end + + --if we cant find any data + local spellData = self.data[sName] + if (not spellData) then + self:LevelDebug(1, " spellData.Rank)) then + sRank = spellData.Rank + elseif ((sRank) and (sRank < 1)) then + sRank = 1 + end + sId = sRank and spellData.IdStart + sRank -1 or spellData.IdStart + end + + local sRankText, sFullText + if (sRank) then + sRankText = self:GetRankText(sRank) + end + sFullText = self:GetSpellNameText(sName, sRank) + + self:LevelDebug(1, ">>> CastOriginal", + methodName, param1, param2, param3, + sId, sName, sRank, sFullName) + + ResetCastOriginal(self, sId, sName, sRank, sFullName) + + self:LevelDebug(3, "-> CastOriginal") + self.hooks[methodName](param1, param2, param3) + self:LevelDebug(3, "<- CastOriginal") + + TriggerFailureEvent(self) + if (not self.vars.AttemptCastFailure) then + AssignSpellData(self, sId, sName, sRank, sFullName) + end + + ResetCastOriginal(self, nil, nil, nil, nil) + + self:LevelDebug(1, "<<<< CastOriginal", + methodName, param1, param2, param3, + sId, sName, sRank, sFullName) +end + +function SpellStatus:CastSpellByName(spellName, onSelf) + self:LevelDebug(2, ">>>> CastSpellByName", spellName, onSelf) + + local sName, sId, sRank, sFullName + sName, sRank, sId, sFullName = spellcache:GetSpellData(spellName) + + CastOriginal(self, "CastSpellByName", spellName, onSelf, nil, sId, sName, sRank, sFullName) + + self:LevelDebug(2, "<<<< CastSpellByName2", spellName, onSelf) +end + +function SpellStatus:CastSpell(spellId, spellbookType) + self:LevelDebug(2, ">>>> CastSpell", spellId, spellbookType) + + local sId, sName, sRank, sFullName + if (spellbookType == BOOKTYPE_SPELL) then + sName, sRank, sId, sFullName = spellcache:GetSpellData(spellId) + end + + CastOriginal(self, "CastSpell", spellId, spellbookType, nil, sId, sName, sRank, sFullName) + + self:LevelDebug(2, "<<<< CastSpell", spellId, spellbookType) +end + +--When using UseAction through clicking an actiobar button, we need to get in +local function GetGratuitySpellData(self, slotId) + local spellName = gratuity:GetLine(1) + local spellRank = gratuity:GetLine(1, true) + --empty slot? + if (not spellName) then + return + end + + self:LevelDebug(3, "GetGratuitySpellData", spellName, spellRank) + local sName, sRank, sId, sFullName = spellcache:GetSpellData(spellName, spellRank) + if (sName) then + return sId, sName, sRank, sFullName + else + return nil, spellName, nil, nil + end +end + +function SpellStatus:UseAction(slotId, checkCursor, onSelf) + self:LevelDebug(1, ">>>> UseAction", slotId, checkCursor, onSelf) + + local actionText = GetActionText(slotId) + local isMacro = actionText ~= nil + --self:LevelDebug(2, "UseAction", actionText, tostring(isMacro)) + + if (isMacro) then + self.hooks["UseAction"](slotId, checkCursor, onSelf) + else + gratuity:SetAction(slotId) + local sId, sName, sRank, sFullName = GetGratuitySpellData(self, slotId) + if (sName) then + CastOriginal(self, "UseAction", slotId, checkCursor, onSelf, sId, sName, sRank, sFullName) + else + self.hooks["UseAction"](slotId, checkCursor, onSelf) + end + end + + self:LevelDebug(1, "<<<< UseAction", slotId, checkCursor, onSelf) +end + +function SpellStatus:CastShapeshiftForm(index) + self:LevelDebug(2, ">>>> CastShapeshiftForm", index) + + gratuity:SetShapeshift(index) + local sId, sName, sRank, sFullName = GetGratuitySpellData(self, slotId) + if (sName) then + CastOriginal(self, "CastShapeshiftForm", index, nil, nil, sId, sName, sRank, sFullName) + else + self.hooks["CastShapeshiftForm"](index) + end + + self:LevelDebug(2, "<<<< CastShapeshiftForm", index) +end + +local function GetItemLinkData(slotId, bagId) + local itemLink = nil + + if (bagId == nil) then + itemLink = GetInventoryItemLink("player", slotId) + else + itemLink = GetContainerItemLink(bagId, slotId) + end + + if (itemLink) then + local _, _, itemName = string.find(itemLink, "^.*%[(.*)%].*$") + return itemName, itemLink + end +end + +function SpellStatus:UseInventoryItem(slotId) + self:LevelDebug(2, ">>>> UseInventoryItem", slotId) + + local itemName, itemLink = GetItemLinkData(slotId) + + if (itemLink) then + CastOriginal(self, "UseInventoryItem", slotId, nil, nil, nil, itemName, nil, itemLink) + else + self.hooks["UseInventoryItem"](slotId) + end + + self:LevelDebug(2, "<<<< UseInventoryItem", slotId) +end + +function SpellStatus:UseContainerItem(bagId, slotId) + self:LevelDebug(2, ">>>> UseContainerItem", bagId, slotId) + + local itemName, itemLink = GetItemLinkData(slotId, bagId) + + if (itemLink) then + CastOriginal(self, "UseContainerItem", bagId, slotId, nil, nil, itemName, nil, itemLink) + else + self.hooks["UseContainerItem"](bagId, slotId) + end + + self:LevelDebug(2, "<<<< UseContainerItem", bagId, slotId) +end + +function SpellStatus:ToggleGameMenu() + --self:LevelDebug(3, "ToggleGameMenu1", SpellIsTargeting()) + + --If these hook is called and targeting, targeting will always be killed first + self.vars.CancelTargeting = SpellIsTargeting() + self.vars.CancelCasting = self.vars.Casting + self.vars.CancelChanneling = self.vars.Channeling + + self.hooks["ToggleGameMenu"]() + + self.vars.CancelTargeting = false + self.vars.CancelCasting = false + self.vars.CancelChanneling = false + + --self:LevelDebug(3, "ToggleGameMenu2", SpellIsTargeting()) +end + +function SpellStatus:SpellStopCasting() + self:LevelDebug(2, ">>>> SpellStopCasting") + if (self:IsCastingOrChanneling()) then + self.vars.SpellStopCastingActiveName = self.vars.ActiveName + end + self.hooks["SpellStopCasting"]() + self:LevelDebug(2, "<<<< SpellStopCasting") +end + +function SpellStatus:SPELLCAST_START(spellName, duration) + self:LevelDebug(1, "SPELLCAST_START", spellName, duration) + + self.vars.SpellStopCastingActiveName = nil + self.vars.Using = false + self.vars.Preparing = false + self.vars.Casting = true + + if (self.vars.ActiveName ~= spellName) then + ResetActiveVariables(self) + self.vars.ActiveName = spellName + self.vars.ActiveFullName = spellName + end + + + self.vars.ActiveCastStartTime = GetTime() + self.vars.ActiveCastDuration = duration + self.vars.ActiveCastStopTime = self.vars.ActiveCastStartTime + (self.vars.ActiveCastDuration/1000) + + self.vars.ActiveCastDelay = nil + self.vars.ActiveCastDelayTotal = nil + + self:TriggerEvent( + "SpellStatus_SpellCastCastingStart", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration + ) +end + +function SpellStatus:SPELLCAST_DELAYED(delay) + self:LevelDebug(1, "SPELLCAST_DELAYED", delay) + + if (self.vars.ActiveCastStopTime == nil) then + return + end + + self.vars.ActiveCastDelay = delay/1000 + self.vars.ActiveCastDelayTotal = (self.vars.ActiveCastDelayTotal or 0) + self.vars.ActiveCastDelay + self.vars.ActiveCastStopTime = self.vars.ActiveCastStopTime + self.vars.ActiveCastDelay + + self:TriggerEvent( + "SpellStatus_SpellCastCastingChange", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration, + self.vars.ActiveCastDelay, + self.vars.ActiveCastDelayTotal + ) +end + +function SpellStatus:SPELLCAST_STOP() + self:LevelDebug(1, "SPELLCAST_STOP") + + --If canceling targeting.. ignore stop! + if (self.vars.CancelTargeting or self.vars.CancelCasting or self.vars.CancelChanneling) then + return + end + + --if (self.vars.ActiveId == nil) then + if (self.vars.ActiveName == nil) then + return + end + + --Player probably moved initiating a client and server side SPELLCAST_STOP + if (not( self.vars.Using or + self.vars.Preparing or + self.vars.Casting or + self.vars.Channeling or + self.vars.AutoRepeating )) then + return + end + + if (TriggerFailureEvent(self)) then + return + end + + self.vars.Using = false + self.vars.Preparing = false + + --Second SPELLCAST_STOP received from server after SpellStopCasting was called + if ((not self.vars.Casting) and + self.vars.SpellStopCastingActiveName and + (self.vars.ActiveName == self.vars.SpellStopCastingActiveName)) then + self.vars.SpellStopCastingActiveName = nil + return + end + + local castingInstant = (not self.vars.Casting) and (not self.vars.Channeling) + self.vars.Casting = false + + --Generate Finish Event if not channeling + if (not self.vars.Channeling) then + local sD = castingInstant and self or self.vars.ActiveCastingData + + self.vars.ActiveCastStartTime = self.vars.ActiveCastStartTime or GetTime() + self.vars.ActiveCastStopTime = GetTime() + + self:TriggerEvent( + castingInstant and "SpellStatus_SpellCastInstant" or "SpellStatus_SpellCastCastingFinish", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration, + self.vars.ActiveCastDelayTotal + ) + --We cant reset because maybe we have a failure!!! + --ResetActiveVariables(self) + end +end + +function SpellStatus:SPELLCAST_CHANNEL_START(duration, action) + self:LevelDebug(2, "SPELLCAST_CHANNEL_START", duration, action) + + self.vars.SpellStopCastingActiveName = nil + self.vars.Using = false + self.vars.Preparing = false + self.vars.Channeling = true + + local sD = self.vars.ActiveChannelingData + + self.vars.ActiveCastStartTime = GetTime() + self.vars.ActiveCastDuration = duration / 1000 + self.vars.ActiveCastStopTime = self.vars.ActiveCastStartTime + self.vars.ActiveCastDuration + self.vars.ActiveAction = action + + self.vars.ActiveId = self.vars.ActiveId + self.vars.ActiveName = self.vars.ActiveName + self.vars.ActiveRank = self.vars.ActiveRank + self.vars.ActiveFullName = self.vars.ActiveFullName + + self.vars.ActiveCastDisruption = nil + self.vars.ActiveCastDisruptionTotal = nil + + self:TriggerEvent( + "SpellStatus_SpellCastChannelingStart", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration, + self.vars.ActiveAction + ) +end + +--Any changes while channeling will come through this event +function SpellStatus:SPELLCAST_CHANNEL_UPDATE(duration) + self:LevelDebug(2, "SPELLCAST_CHANNEL_UPDATE", duration) + + local sD = self.vars.ActiveChannelingData + + local timeStamp = GetTime() + + --New Duration + local spellCastDuration = duration / 1000 + self:LevelDebug(3, "spellCastDuration", spellCastDuration) + --Store old stop time + local spellCastStopTime = self.vars.ActiveCastStopTime + --Time Passed since Channeling + local spellCastTimePassed = timeStamp - self.vars.ActiveCastStartTime + self:LevelDebug(3, "spellCastTimePassed", spellCastTimePassed) + --What channel time did we loose + self.vars.ActiveCastDisruption = self.vars.ActiveCastDuration - spellCastDuration - spellCastTimePassed + self.vars.ActiveCastDisruptionTotal = (self.vars.ActiveCastDisruptionTotal or 0) + self.vars.ActiveCastDisruption + self.vars.ActiveCastStopTime = timeStamp + spellCastDuration + + self:TriggerEvent( + "SpellStatus_SpellCastChannelingChange", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration, + self.vars.ActiveAction, + self.vars.ActiveCastDisruption, + self.vars.ActiveCastDisruptionTotal + ) +end + +function SpellStatus:SPELLCAST_CHANNEL_STOP() + self:LevelDebug(2, "SPELLCAST_CHANNEL_STOP") + + self.vars.Using = false + self.vars.Preparing = false + self.vars.Channeling = false + + self.vars.ActiveCastStopTime = GetTime() + + self:TriggerEvent( + "SpellStatus_SpellCastChannelingFinish", + self.vars.ActiveId, + self.vars.ActiveName, + self.vars.ActiveRank, + self.vars.ActiveFullName, + self.vars.ActiveCastStartTime, + self.vars.ActiveCastStopTime, + self.vars.ActiveCastDuration, + self.vars.ActiveAction, + self.vars.ActiveCastDisruptionTotal + ) +end + +--Always thrown before CHAT_MSG_SPELL_FAILED_LOCALPLAYER which might be thrown +function SpellStatus:UI_ERROR_MESSAGE(message) + self:LevelDebug(2, "UI_ERROR_MESSAGE", message) + + self.vars.UIEM_Message = message +end + +local FAILUREMESSAGE = { + SPELLFAILCASTSELF, + SPELLFAILPERFORMSELF +} + +function SpellStatus:CHAT_MSG_SPELL_FAILED_LOCALPLAYER(message) + self:LevelDebug(2, "CHAT_MSG_SPELL_FAILED_LOCALPLAYER", message) + + table.foreach(FAILUREMESSAGE, + function(key, value) + local spellName, spellFailureMessage = deformat:Deformat(message, value) + if (spellName) then + self.vars.CMSFLP_SpellName = spellName + self.vars.CMSFLP_Message = spellFailureMessage + end + --if returning ~= nil the foreach will stop. + return spellName + end + ) +end + +local CHAT_MSG_SPELL_SELF_DAMAGEMESSAGES = { + IMMUNESPELLSELFOTHER, + SIMPLECASTSELFOTHER, + SIMPLEPERFORMSELFOTHER, + SPELLBLOCKEDSELFOTHER, + SPELLDODGEDSELFOTHER, + SPELLEVADEDSELFOTHER, + SPELLIMMUNESELFOTHER, + SPELLINTERRUPTSELFOTHER, + SPELLLOGABSORBSELFOTHER, + SPELLLOGABSORBSELFSELF, + SPELLLOGCRITSCHOOLSELFOTHER, + SPELLLOGCRITSCHOOLSELFSELF, + SPELLLOGCRITSELFOTHER, + SPELLLOGSCHOOLSELFOTHER, + SPELLLOGSCHOOLSELFSELF, + SPELLLOGSELFOTHER, + SPELLMISSSELFOTHER, + SPELLPARRIEDSELFOTHER, + SPELLREFLECTSELFOTHER, + SPELLRESISTSELFOTHER, + SPELLRESISTSELFSELF, + SPELLTERSEPERFORM_SELF, + SPELLTERSE_SELF +} + +local CHAT_MSG_SPELL_SELF_DAMAGEMESSAGETRAILERS = { + "", + ABSORB_TRAILER, + BLOCK_TRAILER, + CRUSHING_TRAILER, + GLANCING_TRAILER, + RESIST_TRAILER, + VULNERABLE_TRAILER +} + +function ParseCHAT_MSG_SPELL_SELF_DAMAGE(self, message, damageMessage, damageMessageTrailer) + local spellName = deformat:Deformat(message, damageMessage..damageMessageTrailer) + --self:LevelDebug(2, "ParseCHAT_MSG_SPELL_SELF_DAMAGE", self.vars.NextMeleeing, self.vars.NextMeleeName, spellName) + if (spellName and (spellName == self.vars.NextMeleeName)) then + self.vars.NextMeleeing = false + + self:TriggerEvent( + "SpellStatus_SpellCastInstant", + self.vars.NextMeleeId, + self.vars.NextMeleeName, + self.vars.NextMeleeRank, + self.vars.NextMeleeFullName + ) + end +end + +function SpellStatus:CHAT_MSG_SPELL_SELF_DAMAGE(message) + self:LevelDebug(2, "CHAT_MSG_SPELL_SELF_DAMAGE", message) + + if (not self.vars.NextMeleeing) then + return + end + + table.foreach( + CHAT_MSG_SPELL_SELF_DAMAGEMESSAGES, + function(_, damageMessage) + table.foreach( + CHAT_MSG_SPELL_SELF_DAMAGEMESSAGETRAILERS, + function(_, damageMessageTrailer) + ParseCHAT_MSG_SPELL_SELF_DAMAGE(self, message, damageMessage, damageMessageTrailer) + if (not self.vars.NextMeleeing) then + return true + end + end + ) + if (not self.vars.NextMeleeing) then + return true + end + end + ) +end + +function SpellStatus:CHAT_MSG_SPELL_AURA_GONE_SELF(message) + self:LevelDebug(2, "CHAT_MSG_SPELL_AURA_GONE_SELF", message) + + if (not(self.vars.Using or self.vars.Preparing or self.vars.Casting or self.vars.Channeling)) then + return + end + + local spellName = deformat:Deformat(message, AURAREMOVEDSELF) + if ((not spellName) or (spellName ~= self.vars.ActiveName)) then + return + end + + self.vars.Using = false + self.vars.Preparing = false + self.vars.Casting = false + self.vars.Channeling = false + + self:TriggerEvent( + "SpellStatus_SpellCastCancelAura", + self.vars.ActiveId, self.vars.ActiveName, self.vars.ActiveRank, + self.vars.ActiveFullName or self.vars.ActiveName, GetTime() + ) +end + +--Failed is called only when it was semi possible to cast the spell +function SpellStatus:SPELLCAST_INTERRUPTED() + self:LevelDebug(2, "SPELLCAST_INTERRUPTED") + + TriggerFailureEvent(self, true) +end + +function SpellStatus:SPELLCAST_FAILED() + self:LevelDebug(2, "SPELLCAST_FAILED") + + TriggerFailureEvent(self, true) +end + +function SpellStatus:START_AUTOREPEAT_SPELL() + self:LevelDebug(2, "START_AUTOREPEAT_SPELL") + + self.vars.AutoRepeating = true +end + +function SpellStatus:STOP_AUTOREPEAT_SPELL() + self:LevelDebug(2, "STOP_AUTOREPEAT_SPELL") + + self.vars.AutoRepeating = false +end + +function SpellStatus:PLAYER_ENTER_COMBAT() + self:LevelDebug(2, "PLAYER_ENTER_COMBAT") + + self.vars.Attacking = true +end + +function SpellStatus:PLAYER_LEAVE_COMBAT() + self:LevelDebug(2, "PLAYER_LEAVE_COMBAT") + + self.vars.Attacking = false +end + +function SpellStatus:PLAYER_REGEN_DISABLED() + self:LevelDebug(2, "PLAYER_REGEN_DISABLED") + + self.vars.Combating = true +end + +function SpellStatus:PLAYER_REGEN_ENABLED() + self:LevelDebug(2, "PLAYER_REGEN_ENABLED") + + self.vars.Combating = false +end + +function SpellStatus:CHAT_MSG_COMBAT_SELF_HITS(chatMessage) + self:LevelDebug(2, "CHAT_MSG_COMBAT_SELF_HITS", chatMessage) +end + +function SpellStatus:CHAT_MSG_COMBAT_SELF_MISSES(chatMessage) + self:LevelDebug(2, "CHAT_MSG_COMBAT_SELF_MISSES", chatMessage) +end + + +-- +-- Final Registration of the library. +-- +AceLibrary:Register(SpellStatus, MAJOR_VERSION, MINOR_VERSION, activate) +SpellStatus = AceLibrary(MAJOR_VERSION) + + diff --git a/TankBuddyEnh.lua b/TankBuddyEnh.lua index da088b3..eaa490e 100644 --- a/TankBuddyEnh.lua +++ b/TankBuddyEnh.lua @@ -9,6 +9,32 @@ - Kane from Magtherion EU (retired) - Contact: http://www.curse-gaming.com | USER NAME: Kane --]] +local L = AceLibrary("AceLocale-2.2"):new("TankBuddy") +local BS = AceLibrary("Babble-Spell-2.2") +TankBuddy = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0") + + +function TankBuddy:OnEnable() + local _, class = UnitClass("player") + local _, race = UnitRace("player") + + if class == "WARRIOR" or class == "DRUID" then + self:RegisterEvent("SpellStatus_SpellCastInstant") + end +end + +function TankBuddy:SpellStatus_SpellCastInstant(sId, sName, sRank, sFullName, sCastTime) + local TBAbility = ""; + if sName == BS["Challenging Shout"] then + TBAbility = TB_GUI_CS; + elseif sName == BS["Challenging Roar"] then + TBAbility = TB_GUI_CR; + end + + if (TBAbility and TBAbility ~= "") then + TB_Announce(TBAbility); + end +end -- Globals @@ -87,7 +113,7 @@ function TB_OnLoad() TB_EditboxRemoveBuffsInDefensiveBear:Hide(); end NUM_TB_TABS = getn(TB_Tabs); - MAX_TB_TABS = 8; + MAX_TB_TABS = 9; TankBuddyEnhFrame:RegisterEvent("VARIABLES_LOADED"); -- Jump to event function when variables are loaded diff --git a/TankBuddyEnh.toc b/TankBuddyEnh.toc index 2c49d58..5771e73 100644 --- a/TankBuddyEnh.toc +++ b/TankBuddyEnh.toc @@ -1,8 +1,26 @@ -## Interface: 20003 +## Interface: 11200 ## Title: Tank Buddy Enhanced ## Version: 3.0 ## Notes: Notices Party/Raid members when you use last stand, challenging shout/roar, shield wall, lifegiving gem or when your taunt/growl/mocking blow fails. It can also remove chosen buffs automatically, either always or only in defensive stance/bear form. ## Dependencies: ## SavedVariables: TBSettings -## OptionalDeps: CT_RaidAssist +## OptionalDeps: Ace2, CT_RaidAssist, SpellStatusLib, SpellCacheLib, GratuityLib, Deformat, Babble-2.2 +## X-Embeds: Ace2, Deformat, GratuityLib, SpellCacheLib, SpellStatusLib, Babble-2.2 + +Libs\AceLibrary\AceLibrary.lua +Libs\AceOO-2.0\AceOO-2.0.lua +Libs\AceAddon-2.0\AceAddon-2.0.lua +Libs\AceConsole-2.0\AceConsole-2.0.lua +Libs\AceHook-2.1\AceHook-2.1.lua +Libs\AceDB-2.0\AceDB-2.0.lua +Libs\AceEvent-2.0\AceEvent-2.0.lua +Libs\AceLocale-2.2\AceLocale-2.2.lua +Libs\AceDebug-2.0\AceDebug-2.0.lua + +Libs\Deformat-2.0\Deformat-2.0.lua +Libs\Gratuity-2.0\Gratuity-2.0.lua +Libs\Babble-Spell-2.2\Babble-Spell-2.2.lua +Libs\SpellCache-1.0\SpellCache-1.0.lua +Libs\SpellStatus-1.0\SpellStatus-1.0.lua + TankBuddyEnh.xml \ No newline at end of file diff --git a/TankBuddyEnh.xml b/TankBuddyEnh.xml index ba53f16..f376cfa 100644 --- a/TankBuddyEnh.xml +++ b/TankBuddyEnh.xml @@ -519,7 +519,7 @@ - + diff --git a/localization.lua b/localization.lua index 28bbd07..5313826 100644 --- a/localization.lua +++ b/localization.lua @@ -81,8 +81,8 @@ TB_defaultText = { [TB_GUI_MB] = "- My Mocking Blow failed against $tn! -"; [TB_GUI_CSP] = "Resisted counterspell"; [TB_GUI_BN] = "Resisted Banish"; - [TB_GUI_PM] = "Pummel missed"; - [TB_GUI_SB] = "Shield Bash missed"; + [TB_GUI_PM] = "Pummel on $tn"; + [TB_GUI_SB] = "Shield Bash on $tn"; [TB_GUI_KC] = "Kick on $tn"; [TB_GUI_LS] = "- I activated Last Stand! In $sec seconds I will lose $hpHP! -"; [TB_GUI_SW] = "- I activated Shield Wall and will be taking 75% less damage for $sec seconds! -"; @@ -203,8 +203,8 @@ if (GetLocale() == "frFR") then -- French [TB_GUI_PL] = "- My polymorph has been resisted by $tn! -"; [TB_GUI_CSP] = "Resisted counterspell"; [TB_GUI_BN] = "Resisted Banish"; - [TB_GUI_PM] = "Pummel missed"; - [TB_GUI_SB] = "Shield Bash missed"; + [TB_GUI_PM] = "Pummel on $tn"; + [TB_GUI_SB] = "Shield Bash on $tn"; [TB_GUI_KC] = "Kick on $tn"; [TB_GUI_MB] = "- Mon coup railleur a \195\169chou\195\169 contre $tn -"; [TB_GUI_LS] = "- J'ai activ\195\169 Dernier Rempart ! Dans $sec secondes, je perds $hp PV! -";