From 8a86f4ef473253af64a30e74d3b37c129b24834f Mon Sep 17 00:00:00 2001 From: Goranaws <569473+Goranaws@users.noreply.github.com> Date: Thu, 25 Feb 2021 09:26:18 -0600 Subject: [PATCH 1/2] latest update by Shadowed from Curse.com --- ActionBarSaver.lua | 1054 +++++++++++++++++++++-------------------- ActionBarSaver.toc | 30 +- CHANGES.txt | 18 + localization/deDE.lua | 5 + localization/enUS.lua | 76 +++ localization/esES.lua | 5 + localization/esMX.lua | 68 +++ localization/frFR.lua | 5 + localization/koKR.lua | 5 + localization/ptBR.lua | 5 + localization/ruRU.lua | 5 + localization/zhCN.lua | 5 + localization/zhTW.lua | 68 +++ 13 files changed, 812 insertions(+), 537 deletions(-) create mode 100644 CHANGES.txt create mode 100644 localization/deDE.lua create mode 100644 localization/enUS.lua create mode 100644 localization/esES.lua create mode 100644 localization/esMX.lua create mode 100644 localization/frFR.lua create mode 100644 localization/koKR.lua create mode 100644 localization/ptBR.lua create mode 100644 localization/ruRU.lua create mode 100644 localization/zhCN.lua create mode 100644 localization/zhTW.lua diff --git a/ActionBarSaver.lua b/ActionBarSaver.lua index 29a99d0..35a37e4 100644 --- a/ActionBarSaver.lua +++ b/ActionBarSaver.lua @@ -1,526 +1,528 @@ ---[[ - Action Bar Saver, Shadowed -]] -ActionBarSaver = select(2, ...) - -local ABS = ActionBarSaver -local L = ABS.locals - -local restoreErrors, spellCache, macroCache, macroNameCache, highestRanks = {}, {}, {}, {}, {} -local iconCache, playerClass - -local MAX_MACROS = 54 -local MAX_CHAR_MACROS = 18 -local MAX_GLOBAL_MACROS = 36 -local MAX_ACTION_BUTTONS = 144 -local POSSESSION_START = 121 -local POSSESSION_END = 132 - -function ABS:OnInitialize() - local defaults = { - macro = false, - checkCount = false, - restoreRank = true, - spellSubs = {}, - sets = {} - } - - ActionBarSaverDB = ActionBarSaverDB or {} - - -- Load defaults in - for key, value in pairs(defaults) do - if( ActionBarSaverDB[key] == nil ) then - ActionBarSaverDB[key] = value - end - end - - for classToken in pairs(RAID_CLASS_COLORS) do - ActionBarSaverDB.sets[classToken] = ActionBarSaverDB.sets[classToken] or {} - end - - self.db = ActionBarSaverDB - - playerClass = select(2, UnitClass("player")) -end - --- Text "compression" so it can be stored in our format fine -function ABS:CompressText(text) - text = string.gsub(text, "\n", "/n") - text = string.gsub(text, "/n$", "") - text = string.gsub(text, "||", "/124") - - return string.trim(text) -end - -function ABS:UncompressText(text) - text = string.gsub(text, "/n", "\n") - text = string.gsub(text, "/124", "|") - - return string.trim(text) -end - --- Restore a saved profile -function ABS:SaveProfile(name) - self.db.sets[playerClass][name] = self.db.sets[playerClass][name] or {} - local set = self.db.sets[playerClass][name] - - for actionID=1, MAX_ACTION_BUTTONS do - set[actionID] = nil - - local type, id, subType, extraID = GetActionInfo(actionID) - if( type and id and ( actionID < POSSESSION_START or actionID > POSSESSION_END ) ) then - -- DB Format: |||| - -- Save a companion - if( type == "companion" ) then - set[actionID] = string.format("%s|%s|%s|%s|%s|%s", type, id, "", "", subType, "") - -- Save an equipment set - elseif( type == "equipmentset" ) then - set[actionID] = string.format("%s|%s|%s", type, id, "") - -- Save an item - elseif( type == "item" ) then - set[actionID] = string.format("%s|%d|%s|%s", type, id, "", (GetItemInfo(id)) or "") - -- Save a spell - elseif( type == "spell" and id > 0 ) then - local spellName, spellStance = GetSpellInfo(id) - if( spellName and spellStance ) then - set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, id, "", spellName, spellStance or "", extraID or "") - end - -- Save a macro - elseif( type == "macro" ) then - local name, icon, macro = GetMacroInfo(id) - if( name and icon and macro ) then - set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, actionID, "", self:CompressText(name), icon, self:CompressText(macro)) - end - -- Flyout mnenu - elseif( type == "flyout" ) then - set[actionID] = string.format("%s|%d|%s|%s|%s", type, id, "", (GetFlyoutInfo(id)), "") - end - end - end - - self:Print(string.format(L["Saved profile %s!"], name)) -end - --- Finds the macroID in case it's changed -function ABS:FindMacro(id, name, data) - if( macroCache[id] == data ) then - return id - end - - -- No such luck, check text - for id, currentMacro in pairs(macroCache) do - if( currentMacro == data ) then - return id - end - end - - -- Still no luck, let us try name - if( macroNameCache[name] ) then - return macroNameCache[name] - end - - return nil -end - --- Restore any macros that don't exist -function ABS:RestoreMacros(set) - local perCharacter = true - for id, data in pairs(set) do - local type, id, binding, macroName, macroIcon, macroData = string.split("|", data) - if( type == "macro" ) then - -- Do we already have a macro? - local macroID = self:FindMacro(id, macroName, macroData) - if( not macroID ) then - local globalNum, charNum = GetNumMacros() - -- Make sure we aren't at the limit - if( globalNum == MAX_GLOBAL_MACROS and charNum == MAX_CHAR_MACROS ) then - table.insert(restoreErrors, L["Unable to restore macros, you already have 36 global and 18 per character ones created."]) - break - - -- We ran out of space for per character, so use global - elseif( charNum == MAX_CHAR_MACROS ) then - perCharacter = false - end - - -- When creating a macro, we have to pass the icon id not the icon path - if( not iconCache ) then - iconCache = {} - for i=1, GetNumMacroIcons() do - iconCache[(GetMacroIconInfo(i))] = i - end - end - - macroName = self:UncompressText(macroName) - - -- No macro name means a space has to be used or else it won't be created and saved - CreateMacro(macroName == "" and " " or macroName, iconCache[macroIcon] or 1, self:UncompressText(macroData), nil, perCharacter) - end - end - end - - -- Recache macros due to any additions - local blacklist = {} - for i=1, MAX_MACROS do - local name, icon, macro = GetMacroInfo(i) - - if( name ) then - -- If there are macros with the same name, then blacklist and don't look by name - if( macroNameCache[name] ) then - blacklist[name] = true - macroNameCache[name] = i - elseif( not blacklist[name] ) then - macroNameCache[name] = i - end - end - - macroCache[i] = macro and self:CompressText(macro) or nil - end -end - --- Restore a saved profile -function ABS:RestoreProfile(name, overrideClass) - local set = self.db.sets[overrideClass or playerClass][name] - if( not set ) then - self:Print(string.format(L["No profile with the name \"%s\" exists."], set)) - return - elseif( InCombatLockdown() ) then - self:Print(String.format(L["Unable to restore profile \"%s\", you are in combat."], set)) - return - end - - table.wipe(macroCache) - table.wipe(spellCache) - table.wipe(macroNameCache) - - -- Cache spells - for book=1, MAX_SKILLLINE_TABS do - local _, _, offset, numSpells = GetSpellTabInfo(book) - - for i=1, numSpells do - local index = offset + i - local spell, stance = GetSpellBookItemName(index, BOOKTYPE_SPELL) - - -- This way we restore the max rank of spells - spellCache[spell] = index - spellCache[string.lower(spell)] = index - - if( stance and stance ~= "" ) then - spellCache[spell .. stance] = index - end - end - end - - - -- Cache macros - local blacklist = {} - for i=1, MAX_MACROS do - local name, icon, macro = GetMacroInfo(i) - - if( name ) then - -- If there are macros with the same name, then blacklist and don't look by name - if( macroNameCache[name] ) then - blacklist[name] = true - macroNameCache[name] = i - elseif( not blacklist[name] ) then - macroNameCache[name] = i - end - end - - macroCache[i] = macro and self:CompressText(macro) or nil - end - - -- Check if we need to restore any missing macros - if( self.db.macro ) then - self:RestoreMacros(set) - end - - -- Start fresh with nothing on the cursor - ClearCursor() - - -- Save current sound setting - local soundToggle = GetCVar("Sound_EnableAllSound") - -- Turn sound off - SetCVar("Sound_EnableAllSound", 0) - - for i=1, MAX_ACTION_BUTTONS do - if( i < POSSESSION_START or i > POSSESSION_END ) then - local type, id = GetActionInfo(i) - - -- Clear the current spot - if( id or type ) then - PickupAction(i) - ClearCursor() - end - - -- Restore this spot - if( set[i] ) then - self:RestoreAction(i, string.split("|", set[i])) - end - end - end - - -- Restore old sound setting - SetCVar("Sound_EnableAllSound", soundToggle) - - -- Done! - if( #(restoreErrors) == 0 ) then - self:Print(string.format(L["Restored profile %s!"], name)) - else - self:Print(string.format(L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."], name, #(restoreErrors))) - end -end - -function ABS:RestoreAction(i, type, actionID, binding, ...) - -- Restore a spell, flyout or companion - if( type == "spell" or type == "flyout" or type == "companion" ) then - local spellName, spellRank = ... - if( ( self.db.restoreRank or spellRank == "" ) and spellCache[spellName] ) then - PickupSpellBookItem(spellCache[spellName], BOOKTYPE_SPELL) - elseif( spellRank ~= "" and spellCache[spellName .. spellRank] ) then - PickupSpellBookItem(spellCache[spellName .. spellRank], BOOKTYPE_SPELL) - else - PickupSpell(actionID) - end - - if( GetCursorInfo() ~= type ) then - -- Bad restore, check if we should link at all - local lowerSpell = string.lower(spellName) - for spell, linked in pairs(self.db.spellSubs) do - if( lowerSpell == spell and spellCache[linked] ) then - self:RestoreAction(i, type, actionID, binding, linked, nil, arg3) - return - elseif( lowerSpell == linked and spellCache[spell] ) then - self:RestoreAction(i, type, actionID, binding, spell, nil, arg3) - return - end - end - - table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], spellName, i)) - ClearCursor() - return - end - - PlaceAction(i) - -- Restore flyout - elseif( type == "flyout" ) then - PickupSpell(actionID) - if( GetCursorInfo() ~= "flyout" ) then - table.insert(restoreErrors, string.format(L["Unable to restore flyout spell \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) - ClearCursor() - return - end - PlaceAction(i) - - -- Restore an equipment set button - elseif( type == "equipmentset" ) then - local slotID = -1 - for i=1, GetNumEquipmentSets() do - if( GetEquipmentSetInfo(i) == actionID ) then - slotID = i - break - end - end - - PickupEquipmentSet(slotID) - if( GetCursorInfo() ~= "equipmentset" ) then - table.insert(restoreErrors, string.format(L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) - ClearCursor() - return - end - - PlaceAction(i) - - -- Restore an item - elseif( type == "item" ) then - PickupItem(actionID) - - if( GetCursorInfo() ~= type ) then - local itemName = select(i, ...) - table.insert(restoreErrors, string.format(L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."], itemName and itemName ~= "" and itemName or actionID, i)) - ClearCursor() - return - end - - PlaceAction(i) - -- Restore a macro - elseif( type == "macro" ) then - local name, _, content = ... - PickupMacro(self:FindMacro(actionID, name, content or -1)) - if( GetCursorInfo() ~= type ) then - table.insert(restoreErrors, string.format(L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."], actionID, i)) - ClearCursor() - return - end - - PlaceAction(i) - end -end - -function ABS:Print(msg) - DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99ABS|r: " .. msg) -end - -SLASH_ACTIONBARSAVER1 = nil -SlashCmdList["ACTIONBARSAVER"] = nil - -SLASH_ABS1 = "/abs" -SLASH_ABS2 = "/actionbarsaver" -SlashCmdList["ABS"] = function(msg) - msg = msg or "" - - local cmd, arg = string.split(" ", msg, 2) - cmd = string.lower(cmd or "") - arg = string.lower(arg or "") - - local self = ABS - - -- Profile saving - if( cmd == "save" and arg ~= "" ) then - self:SaveProfile(arg) - - -- Spell sub - elseif( cmd == "link" and arg ~= "" ) then - local first, second = string.match(arg, "\"(.+)\" \"(.+)\"") - first = string.trim(first or "") - second = string.trim(second or "") - - if( first == "" or second == "" ) then - self:Print(L["Invalid spells passed, remember you must put quotes around both of them."]) - return - end - - self.db.spellSubs[first] = second - - self:Print(string.format(L["Spells \"%s\" and \"%s\" are now linked."], first, second)) - - -- Profile restoring - elseif( cmd == "restore" and arg ~= "" ) then - for i=#(restoreErrors), 1, -1 do table.remove(restoreErrors, i) end - - if( not self.db.sets[playerClass][arg] ) then - self:Print(string.format(L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."], arg)) - return - end - - self:RestoreProfile(arg, playerClass) - - -- Profile renaming - elseif( cmd == "rename" and arg ~= "" ) then - local old, new = string.split(" ", arg, 2) - new = string.trim(new or "") - old = string.trim(old or "") - - if( new == old ) then - self:Print(string.format(L["You cannot rename \"%s\" to \"%s\" they are the same profile names."], old, new)) - return - elseif( new == "" ) then - self:Print(string.format(L["No name specified to rename \"%s\" to."], old)) - return - elseif( self.db.sets[playerClass][new] ) then - self:Print(string.format(L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."], old, new, (UnitClass("player")))) - return - elseif( not self.db.sets[playerClass][old] ) then - self:Print(string.format(L["No profile with the name \"%s\" exists."], old)) - return - end - - self.db.sets[playerClass][new] = CopyTable(self.db.sets[playerClass][old]) - self.db.sets[playerClass][old] = nil - - self:Print(string.format(L["Renamed \"%s\" to \"%s\""], old, new)) - - -- Restore errors - elseif( cmd == "errors" ) then - if( #(restoreErrors) == 0 ) then - self:Print(L["No errors found!"]) - return - end - - self:Print(string.format(L["Errors found: %d"], #(restoreErrors))) - for _, text in pairs(restoreErrors) do - DEFAULT_CHAT_FRAME:AddMessage(text) - end - - -- Delete profile - elseif( cmd == "delete" ) then - self.db.sets[playerClass][arg] = nil - self:Print(string.format(L["Deleted saved profile %s."], arg)) - - -- List profiles - elseif( cmd == "list" ) then - local classes = {} - local setList = {} - - for class, sets in pairs(self.db.sets) do - table.insert(classes, class) - end - - table.sort(classes, function(a, b) - return a < b - end) - - for _, class in pairs(classes) do - for i=#(setList), 1, -1 do table.remove(setList, i) end - for setName in pairs(self.db.sets[class]) do - table.insert(setList, setName) - end - - if( #(setList) > 0 ) then - DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff33ff99%s|r: %s", L[class] or "???", table.concat(setList, ", "))) - end - end - - -- Macro restoring - elseif( cmd == "macro" ) then - self.db.macro = not self.db.macro - - if( self.db.macro ) then - self:Print(L["Auto macro restoration is now enabled!"]) - else - self:Print(L["Auto macro restoration is now disabled!"]) - end - - -- Item counts - elseif( cmd == "count" ) then - self.db.checkCount = not self.db.checkCount - - if( self.db.checkCount ) then - self:Print(L["Checking item count is now enabled!"]) - else - self:Print(L["Checking item count is now disabled!"]) - end - - -- Rank restore - elseif( cmd == "rank" ) then - self.db.restoreRank = not self.db.restoreRank - - if( self.db.restoreRank ) then - self:Print(L["Auto restoring highest spell rank is now enabled!"]) - else - self:Print(L["Auto restoring highest spell rank is now disabled!"]) - end - - -- Halp - else - self:Print(L["Slash commands"]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs save - Saves your current action bar setup under the given profile."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs restore - Changes your action bars to the passed profile."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs delete - Deletes the saved profile."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs rename - Renames a saved profile from oldProfile to newProfile."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs macro - Attempts to restore macros that have been deleted for a profile."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."]) - DEFAULT_CHAT_FRAME:AddMessage(L["/abs list - Lists all saved profiles."]) - end -end - --- Check if we need to load -local frame = CreateFrame("Frame") -frame:RegisterEvent("ADDON_LOADED") -frame:SetScript("OnEvent", function(self, event, addon) - if( addon == "ActionBarSaver" ) then - ABS:OnInitialize() - self:UnregisterEvent("ADDON_LOADED") - end -end) \ No newline at end of file +--[[ + Action Bar Saver, Shadowed +]] +ActionBarSaver = select(2, ...) + +local ABS = ActionBarSaver +local L = ABS.L + +local restoreErrors, spellCache, macroCache, macroNameCache, highestRanks = {}, {}, {}, {}, {} +local playerClass + +local MAX_MACROS = 54 +local MAX_CHAR_MACROS = 18 +local MAX_GLOBAL_MACROS = 36 +local MAX_ACTION_BUTTONS = 144 +local POSSESSION_START = 121 +local POSSESSION_END = 132 + +local MAX_CHAR_MACROS = MAX_CHARACTER_MACROS +local MAX_GLOBAL_MACROS = MAX_ACCOUNT_MACROS +local MAX_MACROS = MAX_CHAR_MACROS + MAX_GLOBAL_MACROS + +function ABS:OnInitialize() + local defaults = { + macro = false, + checkCount = false, + restoreRank = false, + spellSubs = {}, + sets = {} + } + + ActionBarSaverDB = ActionBarSaverDB or {} + + -- Load defaults in + for key, value in pairs(defaults) do + if( ActionBarSaverDB[key] == nil ) then + ActionBarSaverDB[key] = value + end + end + + for classToken in pairs(RAID_CLASS_COLORS) do + ActionBarSaverDB.sets[classToken] = ActionBarSaverDB.sets[classToken] or {} + end + + self.db = ActionBarSaverDB + + playerClass = select(2, UnitClass("player")) +end + +-- Text "compression" so it can be stored in our format fine +function ABS:CompressText(text) + text = string.gsub(text, "\n", "/n") + text = string.gsub(text, "/n$", "") + text = string.gsub(text, "||", "/124") + + return string.trim(text) +end + +function ABS:UncompressText(text) + text = string.gsub(text, "/n", "\n") + text = string.gsub(text, "/124", "|") + + return string.trim(text) +end + +-- Restore a saved profile +function ABS:SaveProfile(name) + self.db.sets[playerClass][name] = self.db.sets[playerClass][name] or {} + local set = self.db.sets[playerClass][name] + + for actionID=1, MAX_ACTION_BUTTONS do + set[actionID] = nil + + local type, id, subType, extraID = GetActionInfo(actionID) + if( type and id and ( actionID < POSSESSION_START or actionID > POSSESSION_END ) ) then + -- DB Format: |||| + -- Save a companion + if( type == "companion" ) then + set[actionID] = string.format("%s|%s|%s|%s|%s|%s", type, id, "", "", subType, "") + -- Save an equipment set + elseif( type == "equipmentset" ) then + set[actionID] = string.format("%s|%s|%s", type, id, "") + -- Save an item + elseif( type == "item" ) then + set[actionID] = string.format("%s|%d|%s|%s", type, id, "", (GetItemInfo(id)) or "") + -- Save a spell + elseif( type == "spell" and id > 0 ) then + local spellName, spellStance = GetSpellInfo(id) + if( spellName or spellStance ) then + set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, id, "", spellName, spellStance or "", extraID or "") + end + -- Save a macro + elseif( type == "macro" ) then + local name, icon, macro = GetMacroInfo(id) + if( name and icon and macro ) then + set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, actionID, "", self:CompressText(name), icon, self:CompressText(macro)) + end + -- Flyout mnenu + elseif( type == "flyout" ) then + set[actionID] = string.format("%s|%d|%s|%s|%s", type, id, "", (GetFlyoutInfo(id)), "") + end + end + end + + self:Print(string.format(L["Saved profile %s!"], name)) +end + +-- Finds the macroID in case it's changed +function ABS:FindMacro(id, name, data) + if( macroCache[id] == data ) then + return id + end + + -- No such luck, check text + for id, currentMacro in pairs(macroCache) do + if( currentMacro == data ) then + return id + end + end + + -- Still no luck, let us try name + if( macroNameCache[name] ) then + return macroNameCache[name] + end + + return nil +end + +-- Restore any macros that don't exist +function ABS:RestoreMacros(set) + local perCharacter = true + for id, data in pairs(set) do + local type, id, binding, macroName, macroIcon, macroData = string.split("|", data) + if( type == "macro" ) then + -- Do we already have a macro? + local macroID = self:FindMacro(id, macroName, macroData) + if( not macroID ) then + local globalNum, charNum = GetNumMacros() + -- Make sure we aren't at the limit + if( globalNum == MAX_GLOBAL_MACROS and charNum == MAX_CHAR_MACROS ) then + table.insert(restoreErrors, L["Unable to restore macros, you already have 36 global and 18 per character ones created."]) + break + + -- We ran out of space for per character, so use global + elseif( charNum == MAX_CHAR_MACROS ) then + perCharacter = false + end + + macroName = self:UncompressText(macroName) + + -- GetMacroInfo still returns the full path while CreateMacro needs the relative + -- can also return INTERFACE\ICONS\ aswell, apparently. + macroIcon = macroIcon and string.gsub(macroIcon, "[iI][nN][tT][eE][rR][fF][aA][cC][eE]\\[iI][cC][oO][nN][sS]\\", "") + + -- No macro name means a space has to be used or else it won't be created and saved + CreateMacro(macroName == "" and " " or macroName, macroIcon or "INV_Misc_QuestionMark", self:UncompressText(macroData), perCharacter) + end + end + end + + -- Recache macros due to any additions + local blacklist = {} + for i=1, MAX_MACROS do + local name, icon, macro = GetMacroInfo(i) + + if( name ) then + -- If there are macros with the same name, then blacklist and don't look by name + if( macroNameCache[name] ) then + blacklist[name] = true + macroNameCache[name] = i + elseif( not blacklist[name] ) then + macroNameCache[name] = i + end + end + + macroCache[i] = macro and self:CompressText(macro) or nil + end +end + +-- Restore a saved profile +function ABS:RestoreProfile(name, overrideClass) + local set = self.db.sets[overrideClass or playerClass][name] + if( not set ) then + self:Print(string.format(L["No profile with the name \"%s\" exists."], set)) + return + elseif( InCombatLockdown() ) then + self:Print(String.format(L["Unable to restore profile \"%s\", you are in combat."], set)) + return + end + + table.wipe(macroCache) + table.wipe(spellCache) + table.wipe(macroNameCache) + + -- Cache spells + for book=1, MAX_SKILLLINE_TABS do + local _, _, offset, numSpells, _, offSpecID = GetSpellTabInfo(book) + + for i=1, numSpells do + if offSpecID == 0 then -- don't process grayed-out "offspec" tabs + for i=1, numSpells do + local index = offset + i + local spell, stance = GetSpellBookItemName(index, BOOKTYPE_SPELL) + + -- This way we restore the max rank of spells + spellCache[spell] = index + spellCache[string.lower(spell)] = index + + if( stance and stance ~= "" ) then + spellCache[spell .. stance] = index + end + end + end + end + end + + + -- Cache macros + local blacklist = {} + for i=1, MAX_MACROS do + local name, icon, macro = GetMacroInfo(i) + + if( name ) then + -- If there are macros with the same name, then blacklist and don't look by name + if( macroNameCache[name] ) then + blacklist[name] = true + macroNameCache[name] = i + elseif( not blacklist[name] ) then + macroNameCache[name] = i + end + end + + macroCache[i] = macro and self:CompressText(macro) or nil + end + + -- Check if we need to restore any missing macros + if( self.db.macro ) then + self:RestoreMacros(set) + end + + -- Start fresh with nothing on the cursor + ClearCursor() + + -- Save current sound setting + local soundToggle = GetCVar("Sound_EnableAllSound") + -- Turn sound off + SetCVar("Sound_EnableAllSound", 0) + + for i=1, MAX_ACTION_BUTTONS do + if( i < POSSESSION_START or i > POSSESSION_END ) then + local type, id = GetActionInfo(i) + + -- Clear the current spot + if( id or type ) then + PickupAction(i) + ClearCursor() + end + + -- Restore this spot + if( set[i] ) then + self:RestoreAction(i, string.split("|", set[i])) + end + end + end + + -- Restore old sound setting + SetCVar("Sound_EnableAllSound", soundToggle) + + -- Done! + if( #(restoreErrors) == 0 ) then + self:Print(string.format(L["Restored profile %s!"], name)) + else + self:Print(string.format(L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."], name, #(restoreErrors))) + end +end + +function ABS:RestoreAction(i, type, actionID, binding, ...) + -- Restore a spell, flyout or companion + if( type == "spell" or type == "flyout" or type == "companion" ) then + local spellName, spellRank = ... + if( spellCache[spellName] ) then + PickupSpellBookItem(spellCache[spellName], BOOKTYPE_SPELL); + else + PickupSpell(actionID) + end + + if( GetCursorInfo() ~= type ) then + -- Bad restore, check if we should link at all + local lowerSpell = string.lower(spellName) + for spell, linked in pairs(self.db.spellSubs) do + if( lowerSpell == spell and spellCache[linked] ) then + self:RestoreAction(i, type, actionID, binding, linked, nil, arg3) + return + elseif( lowerSpell == linked and spellCache[spell] ) then + self:RestoreAction(i, type, actionID, binding, spell, nil, arg3) + return + end + end + + table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], spellName, i)) + ClearCursor() + return + end + + PlaceAction(i) + -- Restore flyout + elseif( type == "flyout" ) then + PickupSpell(actionID) + if( GetCursorInfo() ~= "flyout" ) then + table.insert(restoreErrors, string.format(L["Unable to restore flyout spell \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) + ClearCursor() + return + end + PlaceAction(i) + + -- Restore an equipment set button + elseif( type == "equipmentset" ) then + local slotID = -1 + for i=1, GetNumEquipmentSets() do + if( GetEquipmentSetInfo(i) == actionID ) then + slotID = i + break + end + end + + PickupEquipmentSet(slotID) + if( GetCursorInfo() ~= "equipmentset" ) then + table.insert(restoreErrors, string.format(L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) + ClearCursor() + return + end + + PlaceAction(i) + + -- Restore an item + elseif( type == "item" ) then + PickupItem(actionID) + + if( GetCursorInfo() ~= type ) then + local itemName = select(i, ...) + table.insert(restoreErrors, string.format(L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."], itemName and itemName ~= "" and itemName or actionID, i)) + ClearCursor() + return + end + + PlaceAction(i) + -- Restore a macro + elseif( type == "macro" ) then + local name, _, content = ... + PickupMacro(self:FindMacro(actionID, name, content or -1)) + if( GetCursorInfo() ~= type ) then + table.insert(restoreErrors, string.format(L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."], actionID, i)) + ClearCursor() + return + end + + PlaceAction(i) + end +end + +function ABS:Print(msg) + DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99ABS|r: " .. msg) +end + +SLASH_ACTIONBARSAVER1 = nil +SlashCmdList["ACTIONBARSAVER"] = nil + +SLASH_ABS1 = "/abs" +SLASH_ABS2 = "/actionbarsaver" +SlashCmdList["ABS"] = function(msg) + msg = msg or "" + + local cmd, arg = string.split(" ", msg, 2) + cmd = string.lower(cmd or "") + arg = string.lower(arg or "") + + local self = ABS + + -- Profile saving + if( cmd == "save" and arg ~= "" ) then + self:SaveProfile(arg) + + -- Spell sub + elseif( cmd == "link" and arg ~= "" ) then + local first, second = string.match(arg, "\"(.+)\" \"(.+)\"") + first = string.trim(first or "") + second = string.trim(second or "") + + if( first == "" or second == "" ) then + self:Print(L["Invalid spells passed, remember you must put quotes around both of them."]) + return + end + + self.db.spellSubs[first] = second + + self:Print(string.format(L["Spells \"%s\" and \"%s\" are now linked."], first, second)) + + -- Profile restoring + elseif( cmd == "restore" and arg ~= "" ) then + for i=#(restoreErrors), 1, -1 do table.remove(restoreErrors, i) end + + if( not self.db.sets[playerClass][arg] ) then + self:Print(string.format(L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."], arg)) + return + end + + self:RestoreProfile(arg, playerClass) + + -- Profile renaming + elseif( cmd == "rename" and arg ~= "" ) then + local old, new = string.split(" ", arg, 2) + new = string.trim(new or "") + old = string.trim(old or "") + + if( new == old ) then + self:Print(string.format(L["You cannot rename \"%s\" to \"%s\" they are the same profile names."], old, new)) + return + elseif( new == "" ) then + self:Print(string.format(L["No name specified to rename \"%s\" to."], old)) + return + elseif( self.db.sets[playerClass][new] ) then + self:Print(string.format(L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."], old, new, (UnitClass("player")))) + return + elseif( not self.db.sets[playerClass][old] ) then + self:Print(string.format(L["No profile with the name \"%s\" exists."], old)) + return + end + + self.db.sets[playerClass][new] = CopyTable(self.db.sets[playerClass][old]) + self.db.sets[playerClass][old] = nil + + self:Print(string.format(L["Renamed \"%s\" to \"%s\""], old, new)) + + -- Restore errors + elseif( cmd == "errors" ) then + if( #(restoreErrors) == 0 ) then + self:Print(L["No errors found!"]) + return + end + + self:Print(string.format(L["Errors found: %d"], #(restoreErrors))) + for _, text in pairs(restoreErrors) do + DEFAULT_CHAT_FRAME:AddMessage(text) + end + + -- Delete profile + elseif( cmd == "delete" ) then + self.db.sets[playerClass][arg] = nil + self:Print(string.format(L["Deleted saved profile %s."], arg)) + + -- List profiles + elseif( cmd == "list" ) then + local classes = {} + local setList = {} + + for class, sets in pairs(self.db.sets) do + table.insert(classes, class) + end + + table.sort(classes, function(a, b) + return a < b + end) + + for _, class in pairs(classes) do + for i=#(setList), 1, -1 do table.remove(setList, i) end + for setName in pairs(self.db.sets[class]) do + table.insert(setList, setName) + end + + if( #(setList) > 0 ) then + DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff33ff99%s|r: %s", L[class] or "???", table.concat(setList, ", "))) + end + end + + -- Macro restoring + elseif( cmd == "macro" ) then + self.db.macro = not self.db.macro + + if( self.db.macro ) then + self:Print(L["Auto macro restoration is now enabled!"]) + else + self:Print(L["Auto macro restoration is now disabled!"]) + end + + -- Item counts + elseif( cmd == "count" ) then + self.db.checkCount = not self.db.checkCount + + if( self.db.checkCount ) then + self:Print(L["Checking item count is now enabled!"]) + else + self:Print(L["Checking item count is now disabled!"]) + end + + -- Rank restore + elseif( cmd == "rank" ) then + self.db.restoreRank = not self.db.restoreRank + + if( self.db.restoreRank ) then + self:Print(L["Auto restoring highest spell rank is now enabled!"]) + else + self:Print(L["Auto restoring highest spell rank is now disabled!"]) + end + + -- Halp + else + self:Print(L["Slash commands"]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs save - Saves your current action bar setup under the given profile."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs restore - Changes your action bars to the passed profile."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs delete - Deletes the saved profile."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs rename - Renames a saved profile from oldProfile to newProfile."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs macro - Attempts to restore macros that have been deleted for a profile."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."]) + DEFAULT_CHAT_FRAME:AddMessage(L["/abs list - Lists all saved profiles."]) + end +end + +-- Check if we need to load +local frame = CreateFrame("Frame") +frame:RegisterEvent("ADDON_LOADED") +frame:SetScript("OnEvent", function(self, event, addon) + if( addon == "ActionBarSaver" ) then + ABS:OnInitialize() + self:UnregisterEvent("ADDON_LOADED") + end +end) diff --git a/ActionBarSaver.toc b/ActionBarSaver.toc index 6c34a98..6ee17bf 100644 --- a/ActionBarSaver.toc +++ b/ActionBarSaver.toc @@ -1,11 +1,19 @@ -## Interface: 40200 -## Title: Action Bar Saver 2 -## Notes: Saves and restores your action bars -## Author: Shadowed -## SavedVariables: ActionBarSaverDB -## LoadManagers: AddonLoader -## X-LoadOn-Slash: /actionbarsaver, /abs - -localization.enUS.lua - -ActionBarSaver.lua \ No newline at end of file +## Interface: 11302 +## Title: Action Bar Saver +## Notes: Saves and restores your action bars. +## Author: Shadowed +## SavedVariables: ActionBarSaverDB +## LoadManagers: AddonLoader +## X-LoadOn-Slash: /actionbarsaver, /abs + +localization\enUS.lua +localization\deDE.lua +localization\esES.lua +localization\esMX.lua +localization\frFR.lua +localization\koKR.lua +localization\ruRU.lua +localization\zhCN.lua +localization\zhTW.lua + +ActionBarSaver.lua diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000..a2cba3b --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,18 @@ +tag 555710881e32af0cd96dae6601aa4d69a7561832 v2.3.4 +Author: Shadowed +Date: Sun Dec 1 10:41:24 2019 -0800 + +Tagging as release v2.3.4 + +commit e2be662b094e6ebdc26c1fab51d871c03d9ef122 +Author: Shadowed +Date: Sun Dec 1 09:57:25 2019 -0800 + + Updated for WoW Classic + +commit b9901cb49ec9f46d69f39575fc85c50c8b0f37a9 +Author: Shadowed +Date: Tue Nov 25 23:28:02 2014 -0800 + + code is hard + diff --git a/localization/deDE.lua b/localization/deDE.lua new file mode 100644 index 0000000..1300c9a --- /dev/null +++ b/localization/deDE.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "deDE" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/enUS.lua b/localization/enUS.lua new file mode 100644 index 0000000..b6d5cef --- /dev/null +++ b/localization/enUS.lua @@ -0,0 +1,76 @@ +local ABS = select(2, ...) +local L = {} +L["%s Profiles"] = "%s Profiles" +L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring." +L["/abs delete - Deletes the saved profile."] = "/abs delete - Deletes the saved profile." +L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Lists the errors that happened on the last restore (if any)." +L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa." +L["/abs list - Lists all saved profiles."] = "/abs list - Lists all saved profiles." +L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Toggles auto saving of the current profile whenever you leave the world." +L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Attempts to restore macros that have been deleted for a profile." +L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally." +L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Renames a saved profile from oldProfile to newProfile." +L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Changes your action bars to the passed profile." +L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Saves your current action bar setup under the given profile." +L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Tests restoring a profile, results will be outputted to chat." +L["Also moved from the unknown category to %s."] = "Also moved from the unknown category to %s." +L["Auto macro restoration is now disabled!"] = "Auto macro restoration is now disabled!" +L["Auto macro restoration is now enabled!"] = "Auto macro restoration is now enabled!" +L["Auto profile save on logout is disabled!"] = "Auto profile save on logout is disabled!" +L["Auto profile save on logout is enabled!"] = "Auto profile save on logout is enabled!" +L["Auto restoring highest spell rank is now disabled!"] = "Auto restoring highest spell rank is now disabeld!" +L["Auto restoring highest spell rank is now enabled!"] = "Auto restoring highest spell rank is now enabled!" +L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "Cannot rename \"%s\" to \"%s\" a profile already exists for %s." +L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "Cannot restore profile \"%s\", you can only restore profiles saved to your class." +L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "Cannot test restore profile \"%s\", you can only test restore profiles saved to your class." +L["Checking item count is now disabled!"] = "Checking item count is now disabled!" +L["Checking item count is now enabled!"] = "Checking item count is now enabled!" +L["DEATHKNIGHT"] = "Death Knight" +L["Deleted saved profile %s."] = "Deleted saved profile %s." +L["DRUID"] = "Druid" +L["Errors found: %d"] = "Errors found: %d" +L["HUNTER"] = "Hunter" +L["Instant"] = "Instant" +L["Invalid spells passed, remember you must put quotes around both of them."] = "Invalid spells passed, remember you must put quotes around both of them." +L["MAGE"] = "Mage" +L["Miscellaneous"] = "Miscellaneous" +L["MONK"] = "Monk" +L["No errors found!"] = "No errors found!" +L["No name specified to rename \"%s\" to."] = "No name specified to rename \"%s\" to." +L["No profile with the name \"%s\" exists."] = "No profile with the name \"%s\" exists." +L["PALADIN"] = "Paladin" +L["PRIEST"] = "Priest" +L["Profile List"] = "Profile List" +L["Renamed \"%s\" to \"%s\""] = "Renamed \"%s\" to \"%s\"" +L["Restored profile %s!"] = "Restored profile %s!" +L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restored profile %s, failed to restore %d buttons type /abs errors for more information." +L["ROGUE"] = "Rogue" +L["Saved profile %s!"] = "Saved profile %s!" +L["SHAMAN"] = "Shaman" +L["Slash commands"] = "Slash commands" +L["Spells \"%s\" and \"%s\" are now linked."] = "Spells \"%s\" and \"%s\" are now linked." +L["The profile %s has been moved from the unknown category to %s."] = "The profile %s has been moved from the unknown category to %s." +L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet." +L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore." +L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "Unable to restore item \"%s\" to slot #%d, cannot be found in inventory." +L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect." +L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "Unable to restore macro id #%d to slot #%d, it appears to have been deleted." +L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "Unable to restore macros, you already have 36 global and 18 per character ones created." +L["Unable to restore profile \"%s\", you are in combat."] = "Unable to restore profile \"%s\", you are in combat." +L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet." +L["UNKNOWN"] = "Unknown" +L["WARLOCK"] = "Warlock" +L["WARRIOR"] = "Warrior" +L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "You cannot rename \"%s\" to \"%s\" they are the same profile names." +L["Your DB has been upgraded to the new storage format."] = "Your DB has been upgraded to the new storage format." + + +ABS.L = L +--[===[@debug@ +ABS.L = setmetatable(ABS.L, { + __index = function(tbl, value) + rawset(tbl, value, value) + return value + end, +}) +--@end-debug@]===] diff --git a/localization/esES.lua b/localization/esES.lua new file mode 100644 index 0000000..9a1a94e --- /dev/null +++ b/localization/esES.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "esES" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/esMX.lua b/localization/esMX.lua new file mode 100644 index 0000000..d08fea7 --- /dev/null +++ b/localization/esMX.lua @@ -0,0 +1,68 @@ +if( GetLocale() ~= "esMX" ) then return end +local L = {} +L["%s Profiles"] = "Perfiles %s" +L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Comprobar de que tiene el objeto en su inventario antes de restaurarlo. Activa esta opción si se desconecta al restaurar." +L["/abs delete - Deletes the saved profile."] = "/abs delete - Eliminar el perfil guardado." +L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Listar los errores (si los hay) que ocurrieron en la previa restauración." +L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Enlazar un hechizo con otro. INCLUYA LAS COMILLAS. Por ejemplo, si se introduce \"Fusión de las sombras\" \"Pisotón de guerra\", se utilizará \"Pisotón de guerra\" cuando no se encuentra \"Fusión de las sombras\", y viceversa." +L["/abs list - Lists all saved profiles."] = "/abs list - Listar los perfiles guardados." +L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Guardar automáticamente la perfil acutal al desconectar." +L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Tratar a restaurar los macros que se han eliminado para el perfil." +L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Restaurar el rango más alto del hechizo, o el rango guardado originalmente." +L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Cambiar el nombre de un perfil guardado de perfilAntiguo a perfilNuevo." +L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Cambiar las barras de acción al perfil especificado." +L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Guardar la configuración actual de las barras de acción al perfil especificado." +L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Ensayar a restaurar un perfil, y informar los resultados a chat." +L["Also moved from the unknown category to %s."] = "También movió desde la categoría desconocida a %s." +L["Auto macro restoration is now disabled!"] = "Restauración automática está ahora desactivado!" +L["Auto macro restoration is now enabled!"] = "Restauración automática está ahora activado!" +L["Auto profile save on logout is disabled!"] = "Guardado automático al desconectar está ahora desactivado!" +L["Auto profile save on logout is enabled!"] = "Guardado automático al desconectar está ahora activado!" +L["Auto restoring highest spell rank is now disabled!"] = "Restauración automática del rango más alto está ahora desactivado!" +L["Auto restoring highest spell rank is now enabled!"] = "Restauración automática del rango más alto está ahora activado!" +L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "No puede cambiar el nombre \"%s\" a \"%s\" -- un perfil ya existe en %s." +L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "No puede restaurar \"%s\" -- sólo puede restaurar los perfiles guardados en su clase." +L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "No puede ensayar \"%s\" -- sólo puede ensayar los perfiles guardados en su clase." +L["Checking item count is now disabled!"] = "Comprobación de objetos está ahora desactivado!" +L["Checking item count is now enabled!"] = "Comprobación de objetos está ahora activado!" +L["DEATHKNIGHT"] = "Caballero de la Muerte" +L["Deleted saved profile %s."] = "Eliminó el perfil %s." +L["DRUID"] = "Druida" +L["Errors found: %d"] = "Errores encontrados: %d" +L["HUNTER"] = "Cazador" +L["Instant"] = "Instante" +L["Invalid spells passed, remember you must put quotes around both of them."] = "Hechizos inválidos especificados. Recuerde, debe escribir comillas alrededor de ambos nombres." +L["MAGE"] = "Mago" +L["Miscellaneous"] = "Misceláneo" +L["MONK"] = "Monje" +L["No errors found!"] = "No se encontraron errores!" +L["No name specified to rename \"%s\" to."] = "Ningún nombre especificado para cambiar de \"%s\"." +L["No profile with the name \"%s\" exists."] = "No existe un perfil del nombre \"%s\"." +L["PALADIN"] = "Paladin" +L["PRIEST"] = "Sacerdote" +L["Profile List"] = "Lista de perfiles" +L["Renamed \"%s\" to \"%s\""] = "Cambió el nombre de \"%s\" a \"%s\"." +L["Restored profile %s!"] = "Restauró el perfil %s!" +L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restauró el perfil %s, pero no pudo restaurar %d botones. Escribe \"/abs errors\" para más detalles." +L["ROGUE"] = "Picaro" +L["Saved profile %s!"] = "Guardó el perfil %s!" +L["SHAMAN"] = "Chamán" +L["Slash commands"] = "Comandos" +L["Spells \"%s\" and \"%s\" are now linked."] = "Los hechizos \"%s\" y \"%s\" ahora están enlazados." +L["The profile %s has been moved from the unknown category to %s."] = "El perfil %s se ha movido de la categoría desconocido a %s." +L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "No puede restuarar \"%s\" a la posición #%d, porque no parece existir todavía." +L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "No puede restaurar el conjunto de equipamiento \"%s\" a la posición #%d, porque no parece existir más." +L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque no se encontró en su inventario." +L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque está en los reinos de torneos de arena, y se desconectará si trata restraurarlo." +L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "No puede restaurar el macro #%d a la posición #%d, porque parece que ha sido eliminado." +L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "No puede restaurar los macros, porque ya tiene 36 macros globales y 18 específicos a su personaje." +L["Unable to restore profile \"%s\", you are in combat."] = "No puede restaurar el eprfil \"%s\", porque está en combate." +L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "No puede restaurar \"%s\" a la posición #%d, no parece que has aprendido aún." +L["UNKNOWN"] = "Desconocido" +L["WARLOCK"] = "Brujo" +L["WARRIOR"] = "Guerrero" +L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "No puede cambiar el nombre de \"%s\" a \"%s\" porque ambos nombres son idénticos." +L["Your DB has been upgraded to the new storage format."] = "la configuración guardada se ha actualizado al nuevo formato de almacenamiento." + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/frFR.lua b/localization/frFR.lua new file mode 100644 index 0000000..f9dee51 --- /dev/null +++ b/localization/frFR.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "frFR" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/koKR.lua b/localization/koKR.lua new file mode 100644 index 0000000..0cb163c --- /dev/null +++ b/localization/koKR.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "koKR" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/ptBR.lua b/localization/ptBR.lua new file mode 100644 index 0000000..6e0ada1 --- /dev/null +++ b/localization/ptBR.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "ptBR" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/ruRU.lua b/localization/ruRU.lua new file mode 100644 index 0000000..7c01b12 --- /dev/null +++ b/localization/ruRU.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "ruRU" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/zhCN.lua b/localization/zhCN.lua new file mode 100644 index 0000000..a704410 --- /dev/null +++ b/localization/zhCN.lua @@ -0,0 +1,5 @@ +if( GetLocale() ~= "zhCN" ) then return end +local L = {} + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/zhTW.lua b/localization/zhTW.lua new file mode 100644 index 0000000..50bcabd --- /dev/null +++ b/localization/zhTW.lua @@ -0,0 +1,68 @@ +if( GetLocale() ~= "zhTW" ) then return end +local L = {} +L["%s Profiles"] = "%s 設定檔" +L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - 切換在回復設定檔前,是否檢查物品已在庫存中。如遇到回復中斷,請使用此指令。" +L["/abs delete - Deletes the saved profile."] = "/abs delete - 刪除已儲存之設定檔。" +L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - 列出上次載入設定檔時的錯誤(如有)。" +L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - 連結法術,格式包含括號\"\" ,例如可用 \"影遁\" \"戰爭踐踏\" ,若未能找到 戰爭踐踏 就使用 影遁,反之亦然。" +L["/abs list - Lists all saved profiles."] = "/abs list - 列出所有已儲存之設定檔。" +L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - 切換當你登出時是否自動儲存現有設定檔。" +L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - 嘗試回復設定檔內被刪除的巨集。" +L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - 切換 ABS 是否回復到法術之最高等級或回復到已儲存之法術等級。" +L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - 重新命名已儲存之設定檔名稱,由 (舊檔名) 改為 (新檔名)。" +L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - 更改動作條為已儲存之設定檔。" +L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - 儲存現有動作條為設定檔,為自定的設定檔名稱。" +L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - 測試回復設定檔,結果會在對話框顯示。" +L["Also moved from the unknown category to %s."] = "並由未知類別移動到 %s。" +L["Auto macro restoration is now disabled!"] = "巨集自動回復已停用!" +L["Auto macro restoration is now enabled!"] = "巨集自動回復已啟用!" +L["Auto profile save on logout is disabled!"] = "登出時自動儲存設定檔已停用!" +L["Auto profile save on logout is enabled!"] = "登出時自動儲存設定檔已啟用!" +L["Auto restoring highest spell rank is now disabled!"] = "自動回復至法術的最高等級已最停用!" +L["Auto restoring highest spell rank is now enabled!"] = "自動回復至法術的最高等級已最啟用!" +L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "不能重新命名 \"%s\" 至 \"%s\" %s 該名稱已存在。" +L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "不能回復設定檔 \"%s\",只能回復相同職業所儲存之設定檔。" +L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "不能測試回復設定檔 \"%s\",只能測試回復相同職業所儲存之設定檔。" +L["Checking item count is now disabled!"] = "物檢查品已停用!" +L["Checking item count is now enabled!"] = "物檢查品已啟用!" +L["DEATHKNIGHT"] = "死亡騎士" +L["Deleted saved profile %s."] = "刪除已儲存的設定檔 %s。" +L["DRUID"] = "德魯伊" +L["Errors found: %d"] = "發生錯誤:%d" +L["HUNTER"] = "獵人" +L["Instant"] = "立刻" +L["Invalid spells passed, remember you must put quotes around both of them."] = "無效的法術名稱,法術名稱必需有括號。" +L["MAGE"] = "法師" +L["Miscellaneous"] = "雜項" +L["MONK"] = "武僧" +L["No errors found!"] = "無錯誤發生!" +L["No name specified to rename \"%s\" to."] = "重新命名 \"%s\" 時,未有設定名稱。" +L["No profile with the name \"%s\" exists."] = "沒有名為 \"%s\" 的設定檔。" +L["PALADIN"] = "聖騎士" +L["PRIEST"] = "牧師" +L["Profile List"] = "設定檔列表" +L["Renamed \"%s\" to \"%s\""] = "重新命名 \"%s\" 為 \"%s\"" +L["Restored profile %s!"] = "已回復到設定檔 %s!" +L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "已回復到設定檔 %s, 未能回復 %d 按鍵,輸入 /abs errors 以取得更多資料。" +L["ROGUE"] = "盜賊" +L["Saved profile %s!"] = "已儲存設定檔 %s!" +L["SHAMAN"] = "薩滿" +L["Slash commands"] = "斜線指令" +L["Spells \"%s\" and \"%s\" are now linked."] = "法術 \"%s\" 和 \"%s\" 已連結。" +L["The profile %s has been moved from the unknown category to %s."] = "設定檔 %s 已由未知類別移動到 %s。" +L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "未能回復 小寵物 \"%s\" 至 位置 #%d,小寵物 \"%s\" 未存在。" +L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "未能回復套裝 \"%s\" 至 位置 #%d,套裝未存在。" +L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "未能回復物品 \"%s\" 至 位置 #%d,物品不在庫存中。" +L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "未能回復物品 \"%s\" 至 位置 #%d, 你現處身於競技場區,嘗試回復會導致中斷。" +L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "未能回復巨集 #%d 至 位置 #%d,巨集已被刪除。" +L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "未能回復巨集,你已創建了 36 個共享巨集及 18 個每個角色獨有的巨集。" +L["Unable to restore profile \"%s\", you are in combat."] = "未能回復設定檔 \"%s\",你處於戰鬥中。" +L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "未能回復法術 \"%s\" 至 位置 #%d,你並未學習到此法術。" +L["UNKNOWN"] = "未知" +L["WARLOCK"] = "術士" +L["WARRIOR"] = "戰士" +L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "不能重新命名 \"%s\" 為 \"%s\",名稱相同。" +L["Your DB has been upgraded to the new storage format."] = "你的 DB 已升級為新儲存格式。" + +local ABS = select(2, ...) +ABS.L = setmetatable(L, {__index = ABS.L}) From 497fa1dd83ea1e83951cc37b8a1079bb3979a1f2 Mon Sep 17 00:00:00 2001 From: Goranaws <569473+Goranaws@users.noreply.github.com> Date: Thu, 25 Feb 2021 09:27:39 -0600 Subject: [PATCH 2/2] Update for shadowlands --- ActionBarSaver.lua | 363 +++++++++++++++++-------- ActionBarSaver.toc | 7 +- Changelog-ActionBarSaver-v2.3.3.txt | 13 + Options.lua | 395 ++++++++++++++++++++++++++++ localization/enUS.lua | 126 ++++----- localization/esMX.lua | 126 ++++----- localization/zhTW.lua | 63 ----- 7 files changed, 794 insertions(+), 299 deletions(-) create mode 100644 Changelog-ActionBarSaver-v2.3.3.txt create mode 100644 Options.lua diff --git a/ActionBarSaver.lua b/ActionBarSaver.lua index 35a37e4..daad40a 100644 --- a/ActionBarSaver.lua +++ b/ActionBarSaver.lua @@ -63,41 +63,75 @@ function ABS:UncompressText(text) return string.trim(text) end + +function macroContainsClassSpell(macroBody) + for spellName, id in pairs(spellCache) do + if string.find(macroBody, spellName) then + return true + end + end +end + + -- Restore a saved profile function ABS:SaveProfile(name) + self:CreateSpellCache() self.db.sets[playerClass][name] = self.db.sets[playerClass][name] or {} local set = self.db.sets[playerClass][name] - - for actionID=1, MAX_ACTION_BUTTONS do + for actionID = 1, MAX_ACTION_BUTTONS do set[actionID] = nil - local type, id, subType, extraID = GetActionInfo(actionID) if( type and id and ( actionID < POSSESSION_START or actionID > POSSESSION_END ) ) then -- DB Format: |||| + --save a mount + -- print(type, subType) + if( type == "summonmount" ) or (subType == "MOUNT") then + --Blizzard uses two different methods for mounts, so catch it either way. + set[actionID] = string.join("|", "MOUNT", id) --mount must be all caps! GetCursorInfo returns it as all caps when restoring + --save a battle pet(non-combat pets) + elseif( type == "summonpet" ) then + set[actionID] = string.join("|", "battlepet", id) -- Save a companion - if( type == "companion" ) then - set[actionID] = string.format("%s|%s|%s|%s|%s|%s", type, id, "", "", subType, "") + elseif( type == "companion" ) then + set[actionID] = string.join("|", type, id, "", "", subType) -- Save an equipment set elseif( type == "equipmentset" ) then - set[actionID] = string.format("%s|%s|%s", type, id, "") + set[actionID] = string.join("|", type, id, "") -- Save an item elseif( type == "item" ) then - set[actionID] = string.format("%s|%d|%s|%s", type, id, "", (GetItemInfo(id)) or "") + set[actionID] = string.join("|", type, id, "", (GetItemInfo(id)) or "") + -- Save a pet spell + elseif( subType == "pet" and id > 0 ) then + local spellName, spellStance = GetSpellInfo(id) + if( spellName) then + set[actionID] = string.join("|", "petaction", id, "", spellName, spellStance or "", extraID or "") + end -- Save a spell elseif( type == "spell" and id > 0 ) then - local spellName, spellStance = GetSpellInfo(id) - if( spellName or spellStance ) then - set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, id, "", spellName, spellStance or "", extraID or "") + local spellName, spellStance = GetSpellInfo(id) + if( spellName) then + local class + if spellCache[spellName] then + --spell is class specific + class = select(2, UnitClass("player")) + end + set[actionID] = string.join("|", type, id, "", spellName, spellStance or "", extraID or "", class or "") end -- Save a macro elseif( type == "macro" ) then local name, icon, macro = GetMacroInfo(id) if( name and icon and macro ) then - set[actionID] = string.format("%s|%d|%s|%s|%s|%s", type, actionID, "", self:CompressText(name), icon, self:CompressText(macro)) + local spellName = GetMacroSpell(GetMacroIndexByName(name)) + local class + if macroContainsClassSpell(macro) then + --macro casts a spell, and that spell is class specific + class = select(2, UnitClass("player")) + end + set[actionID] = string.join("|", type, actionID, "", self:CompressText(name), icon, self:CompressText(macro), class or "") end - -- Flyout mnenu - elseif( type == "flyout" ) then - set[actionID] = string.format("%s|%d|%s|%s|%s", type, id, "", (GetFlyoutInfo(id)), "") + -- Flyout menu + elseif( type == "flyout" ) then + set[actionID] = string.join("|", type, id, "", (GetFlyoutInfo(id))) end end end @@ -149,7 +183,7 @@ function ABS:RestoreMacros(set) macroName = self:UncompressText(macroName) -- GetMacroInfo still returns the full path while CreateMacro needs the relative - -- can also return INTERFACE\ICONS\ aswell, apparently. + -- can also return INTERFACE\ICONS\ as well, apparently. macroIcon = macroIcon and string.gsub(macroIcon, "[iI][nN][tT][eE][rR][fF][aA][cC][eE]\\[iI][cC][oO][nN][sS]\\", "") -- No macro name means a space has to be used or else it won't be created and saved @@ -177,21 +211,27 @@ function ABS:RestoreMacros(set) end end --- Restore a saved profile -function ABS:RestoreProfile(name, overrideClass) - local set = self.db.sets[overrideClass or playerClass][name] - if( not set ) then - self:Print(string.format(L["No profile with the name \"%s\" exists."], set)) - return - elseif( InCombatLockdown() ) then - self:Print(String.format(L["Unable to restore profile \"%s\", you are in combat."], set)) - return - end +function isSpellCurrentClass(type, id) + local isCurrent - table.wipe(macroCache) + if type == "macro" then + local name, icon, body, isLocal = GetMacroInfo(id) + id = GetMacroSpell(name) + end + + local spellName = spellCache[GetSpellInfo(id)] + if spellName then + local spec, class = IsSpellClassOrSpec(spellName, "spell") + + if id and ((type == "spell") or (type == "macro")) and (spec or class) then + isCurrent = true + end + end + return isCurrent +end + +function ABS:CreateSpellCache() table.wipe(spellCache) - table.wipe(macroNameCache) - -- Cache spells for book=1, MAX_SKILLLINE_TABS do local _, _, offset, numSpells, _, offSpecID = GetSpellTabInfo(book) @@ -213,7 +253,32 @@ function ABS:RestoreProfile(name, overrideClass) end end end - +end + +function ABS:ClearActionBars() + for i=1, MAX_ACTION_BUTTONS do + if( i < POSSESSION_START or i > POSSESSION_END ) then + PickupAction(i) + ClearCursor() + end + end +end + +-- Restore a saved profile +function ABS:RestoreProfile(name, overrideClass) + local set = self.db.sets[overrideClass or playerClass][name] + if( not set ) then + self:Print(string.format(L["No profile with the name \"%s\" exists."], set)) + return + elseif( InCombatLockdown() ) then + self:Print(String.format(L["Unable to restore profile \"%s\", you are in combat."], set)) + return + end + + table.wipe(macroCache) + table.wipe(macroNameCache) + + self:CreateSpellCache() -- Cache macros local blacklist = {} @@ -237,7 +302,7 @@ function ABS:RestoreProfile(name, overrideClass) if( self.db.macro ) then self:RestoreMacros(set) end - + -- Start fresh with nothing on the cursor ClearCursor() @@ -248,16 +313,24 @@ function ABS:RestoreProfile(name, overrideClass) for i=1, MAX_ACTION_BUTTONS do if( i < POSSESSION_START or i > POSSESSION_END ) then - local type, id = GetActionInfo(i) + local type, id, subType = GetActionInfo(i) + local proceed = true -- Clear the current spot - if( id or type ) then - PickupAction(i) - ClearCursor() + if( id or type ) and (self.db.leave ~= true) then + + if (self.db.leaveClass == true) then + proceed = isSpellCurrentClass(type, id) == nil + end + + if proceed == true then + PickupAction(i) + ClearCursor() + end end -- Restore this spot - if( set[i] ) then + if( set[i] ) and (proceed == true) then self:RestoreAction(i, string.split("|", set[i])) end end @@ -273,89 +346,157 @@ function ABS:RestoreProfile(name, overrideClass) self:Print(string.format(L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."], name, #(restoreErrors))) end end - -function ABS:RestoreAction(i, type, actionID, binding, ...) - -- Restore a spell, flyout or companion - if( type == "spell" or type == "flyout" or type == "companion" ) then - local spellName, spellRank = ... - if( spellCache[spellName] ) then - PickupSpellBookItem(spellCache[spellName], BOOKTYPE_SPELL); - else - PickupSpell(actionID) - end - - if( GetCursorInfo() ~= type ) then - -- Bad restore, check if we should link at all - local lowerSpell = string.lower(spellName) - for spell, linked in pairs(self.db.spellSubs) do - if( lowerSpell == spell and spellCache[linked] ) then - self:RestoreAction(i, type, actionID, binding, linked, nil, arg3) - return - elseif( lowerSpell == linked and spellCache[spell] ) then - self:RestoreAction(i, type, actionID, binding, spell, nil, arg3) - return - end +local types +types = { + item = { + pickup = function(i, type, actionID, binding, ...) + return PickupItem(actionID) + end, + errorMessage = function(i, type, actionID, binding, ...) + if( GetCursorInfo() ~= type ) then + local itemName = select(i, ...) + table.insert(restoreErrors, string.format(L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."], itemName and itemName ~= "" and itemName or actionID, i)) + return true end + end, + }, + macro = { + pickup = function(i, type, actionID, binding, ...) + local name, _, content, class = ... - table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], spellName, i)) - ClearCursor() - return - end + if class and (class ~= "") and ABS.db.ignoreClass and (class ~= select(2, UnitClass("player"))) then + + else + return PickupMacro(ABS:FindMacro(actionID, name, content or -1)) + end + end, + errorMessage = function(i, type, actionID, binding, ...) + if( GetCursorInfo() ~= type ) then + table.insert(restoreErrors, string.format(L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."], actionID, i)) + return true + end + end, + }, + petaction = { + pickup = function(i, type, actionID, binding, ...) + PickupPetSpell(actionID) + end, + errorMessage = function(...) return types.spell.errorMessage(...) end, + }, + spell = { + pickup = function(i, type, actionID, binding, ...) + local spellName, _, _, class = ... + if class and (class ~= "") and ABS.db.ignoreClass and (class ~= select(2, UnitClass("player"))) then - PlaceAction(i) - -- Restore flyout - elseif( type == "flyout" ) then - PickupSpell(actionID) - if( GetCursorInfo() ~= "flyout" ) then - table.insert(restoreErrors, string.format(L["Unable to restore flyout spell \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) - ClearCursor() - return - end - PlaceAction(i) - - -- Restore an equipment set button - elseif( type == "equipmentset" ) then - local slotID = -1 - for i=1, GetNumEquipmentSets() do - if( GetEquipmentSetInfo(i) == actionID ) then - slotID = i - break + + else + if( spellCache[spellName] and ABS.db.restoreRank ) then + return PickupSpellBookItem(spellCache[spellName], BOOKTYPE_SPELL); + else + return PickupSpell(actionID) + end + + if( GetCursorInfo() ~= type ) then + --last ditch effort if spellCache goes wrong(it does fail for a few warlock spells) + return PickupSpell(actionID) + end + end + end, + errorMessage = function(i, type, actionID, binding, ...) + local spellName = ... + if( GetCursorInfo() ~= type ) then + -- Bad restore, check if we should link at all + local lowerSpell = string.lower(spellName) + for spell, linked in pairs(ABS.db.spellSubs) do + if( lowerSpell == spell and spellCache[linked] ) then + ABS:RestoreAction(i, type, actionID, binding, linked, nil, arg3) + return + elseif( lowerSpell == linked and spellCache[spell] ) then + ABS:RestoreAction(i, type, actionID, binding, spell, nil, arg3) + return + end + end + table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], spellName, i)) + return true + end + end, + }, + mount = { + pickup = function(i, type, actionID, binding, ...) + local _, spellID = types.mount.info(actionID) + PickupSpell(spellID or actionID) + end, + info = function(actionID) + return C_MountJournal.GetMountInfoByID(actionID) + end, + errorMessage = function(i, type, actionID, binding, ...) + print(type) + local cType, cID, cSubType = GetCursorInfo() + local creatureName = types.mount.info(actionID) + if( cSubType ~= type ) and creatureName then + table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], creatureName, i)) + return true + end + end, + }, + equipmentset = { + pickup = function(i, type, actionID, binding, ...) + local slotID = -1 + for i=1, GetNumEquipmentSets() do + if( GetEquipmentSetInfo(i) == actionID ) then + slotID = i + break + end end - end - - PickupEquipmentSet(slotID) - if( GetCursorInfo() ~= "equipmentset" ) then - table.insert(restoreErrors, string.format(L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) - ClearCursor() - return - end - - PlaceAction(i) - -- Restore an item - elseif( type == "item" ) then - PickupItem(actionID) + return PickupEquipmentSet(slotID) + end, + errorMessage = function(i, type, actionID, binding, ...) + if( GetCursorInfo() ~= "equipmentset" ) then + table.insert(restoreErrors, string.format(L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."], actionID, i)) + return true + end + end, + }, + flyout = { + pickup = function(i, type, actionID, binding, ...) + local name = ... + PickupSpellBookItem(spellCache[string.lower(name)] or actionId, "spell") + end, + errorMessage = function(i, type, actionID, binding, ...) + if( GetCursorInfo() ~= "flyout" ) then + table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], name, actionID)) + return true + end + end, + }, + battlepet ={ + pickup = function(i, type, actionID, binding, ...) + local _, customName, _, _, _, _, _, name = types.battlepet.info(actionID) + C_PetJournal.PickupPet(actionID) + end, + info = function(actionID) + return C_PetJournal.GetPetInfoByPetID(actionID) + end, + errorMessage = function(i, type, actionID, binding, ...) + if( type ~= GetCursorInfo() ) then + table.insert(restoreErrors, string.format(L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."], customName or name, i)) + return true + end + end, + }, + +} - if( GetCursorInfo() ~= type ) then - local itemName = select(i, ...) - table.insert(restoreErrors, string.format(L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."], itemName and itemName ~= "" and itemName or actionID, i)) - ClearCursor() - return - end - - PlaceAction(i) - -- Restore a macro - elseif( type == "macro" ) then - local name, _, content = ... - PickupMacro(self:FindMacro(actionID, name, content or -1)) - if( GetCursorInfo() ~= type ) then - table.insert(restoreErrors, string.format(L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."], actionID, i)) +function ABS:RestoreAction(i, type, actionID, binding, ...) + local info = types[string.lower(type)] + if info then + info.pickup(i, type, actionID, binding, ...) + if info.errorMessage(i, type, actionID, binding, ...) then ClearCursor() - return end - - PlaceAction(i) end + PlaceAction(i) end function ABS:Print(msg) @@ -502,6 +643,10 @@ SlashCmdList["ABS"] = function(msg) self:Print(L["Auto restoring highest spell rank is now disabled!"]) end + -- open new profiles menu + elseif( string.find("options", cmd, 1)) then + InterfaceOptionsFrame:Show() + InterfaceOptionsFrame_OpenToCategory(ActionBarSaver.Options.name) -- Halp else self:Print(L["Slash commands"]) diff --git a/ActionBarSaver.toc b/ActionBarSaver.toc index 6ee17bf..f95d1c6 100644 --- a/ActionBarSaver.toc +++ b/ActionBarSaver.toc @@ -1,10 +1,14 @@ -## Interface: 11302 +## Interface: 60000 ## Title: Action Bar Saver ## Notes: Saves and restores your action bars. ## Author: Shadowed ## SavedVariables: ActionBarSaverDB ## LoadManagers: AddonLoader ## X-LoadOn-Slash: /actionbarsaver, /abs +## X-Curse-Packaged-Version: v2.3.3 +## X-Curse-Project-Name: Action Bar Saver +## X-Curse-Project-ID: action-bar-saver +## X-Curse-Repository-ID: wow/action-bar-saver/mainline localization\enUS.lua localization\deDE.lua @@ -17,3 +21,4 @@ localization\zhCN.lua localization\zhTW.lua ActionBarSaver.lua +Options.lua diff --git a/Changelog-ActionBarSaver-v2.3.3.txt b/Changelog-ActionBarSaver-v2.3.3.txt new file mode 100644 index 0000000..66b0e0d --- /dev/null +++ b/Changelog-ActionBarSaver-v2.3.3.txt @@ -0,0 +1,13 @@ +tag v2.3.3 +ad89ad5bf9ece06e5b6ff53859c333241612ffa6 +Shadowed +2014-11-25 23:26:55 -0800 + +Tagging as release v2.3.3 + + +-------------------- + +Shadowed: + - cleaned up files + - Updated for WoD diff --git a/Options.lua b/Options.lua new file mode 100644 index 0000000..d61c184 --- /dev/null +++ b/Options.lua @@ -0,0 +1,395 @@ +--[[ + Action Bar Saver Options, Goranaws +]] +local ActionBarSaver = select(2, ...) +ActionBarSaver.Options = CreateFrame("Frame", nil, InterfaceOptionsFramePanelContainer) +ActionBarSaver.Options.name = "Action Button Saver" +InterfaceOptions_AddCategory(ActionBarSaver.Options) + +local Options = ActionBarSaver.Options + +Options:Hide() +Options.profileButtons = {used = {},unUsed = {}} + +local overrideClass, overrideName +local forceOverride + +local L = ActionBarSaver.L +local playerClass + +function Options:GetDB() + return ActionBarSaverDB +end + +local stored = {} +function Options:GetAllProfiles() + local profiles = self:GetDB().sets + table.wipe(stored) + for class, profs in pairs(profiles) do + for profileName, settings in pairs(profs) do + local storing = {name = profileName, class = class, settings = settings} + tinsert(stored, storing) + end + end + return stored +end + + --update options display +function Options:Reload() + ActionBarSaver:OnInitialize() + self.pName:SetText(overrideName or string.lower(UnitName("Player"))) + self.cName:SetText(overrideClass or playerClass) + self:SetProfileButtons() +end + +local function newButton(parent, text) + local b = CreateFrame("Button",nil, parent, "UIMenuButtonStretchTemplate") + b.Text:SetText(text) + b:SetWidth(b.Text:GetWidth()+20) + b:SetScript("OnClick", function() + if b.click then + b.click() + end + end) + return b +end + +local index = 1 +local prevCheck +local function newCheck(parent, text) + local b = CreateFrame("CheckButton","ActionBarSaverCheckButton"..index, parent, "OptionsCheckButtonTemplate") + index = index + 1 + _G[b:GetName().."Text"]:SetText(text) + b.offset = _G[b:GetName().."Text"]:GetWidth() + b:SetScript("OnClick", function() + if b.click then + b:SetChecked(b.click()) + end + end) + b:SetScript("OnShow", function() + if b.onShow then + b:SetChecked(b.onShow()) + end + end) + b:SetScript("OnEnter", function() + if b.onEnter then + GameTooltip:SetOwner(b, "ANCHOR_BOTTOMRIGHT") + GameTooltip:SetText(string.trim(b.onEnter), 1, 1, 1, nil, true); + GameTooltip:Show(); + end + end) + b:SetScript("OnLeave", function() + GameTooltip:Hide(); + end) + b:Hide() + + if prevCheck then + b:SetPoint("TopLeft", prevCheck, "BottomLeft", 0, -3) + else + b:SetPoint("TopLeft", parent, 10, -70) + end + + prevCheck = b + + return b +end + +Options:SetScript("OnShow", function(self) + --Create the options menu + playerClass = select(2, UnitClass("player")) + + local title = self:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") + title:SetText(self.name) + title:SetPoint("TopLeft", 10,-10) + + + local pName = CreateFrame("EditBox", nil, self, "InputBoxTemplate") + pName:SetSize(150, 25) + pName:SetAutoFocus(false) + pName:SetPoint("TopLeft", 10, -40) + local t = self:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") + t:SetText("Profile") + t:SetPoint("BottomLeft", pName, "TopLeft") + self.pName = pName + + local cName = CreateFrame("EditBox", nil, self, "InputBoxTemplate") + cName:SetSize(150, 25) + cName:SetAutoFocus(false) + cName:SetPoint("Left", pName, "Right", 5, 0) + local t = self:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall") + t:SetText("Class") + t:SetPoint("BottomLeft", cName, "TopLeft") + self.cName = cName + + local Save = newButton(self, "Save") + Save:SetPoint("Left", cName, "Right", 5, 0) + Save.click = function() + overrideName = string.lower(string.gsub(pName:GetText(), " ", "")) + overrideClass = playerClass + SlashCmdList.ABS("save "..overrideName) + Options:Reload() + end + + local Delete = newButton(self, "Delete") + Delete:SetPoint("Left", Save, "Right", 5, 0) + Delete.click = function() + local arg = pName:GetText() + self:GetDB().sets[overrideClass or playerClass][arg] = nil + ActionBarSaver:Print(string.format(L["Deleted saved profile %s."], arg)) + Options:Reload() + end + + local Rename = newButton(self, "Rename") + Rename:SetPoint("Left", Delete, "Right", 5, 0) + Rename.click = function() + local self = ActionBarSaver + local arg = pName:GetText() + local old, new = string.split(" ", arg, 2) + new = string.trim(new or "") + old = string.trim(old or "") + + if( new == old ) then + self:Print(string.format(L["You cannot rename \"%s\" to \"%s\" they are the same profile names."], old, new)) + return + elseif( new == "" ) then + self:Print(string.format(L["No name specified to rename \"%s\" to."], old)) + return + elseif( self.db.sets[overrideClass or playerClass][new] ) then + self:Print(string.format(L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."], old, new, (overrideClass or playerClass))) + return + elseif( not self.db.sets[overrideClass or playerClass][old] ) then + self:Print(string.format(L["No profile with the name \"%s\" exists."], old)) + return + end + + self.db.sets[overrideClass or playerClass][new] = CopyTable(self.db.sets[overrideClass or playerClass][old]) + self.db.sets[overrideClass or playerClass][old] = nil + + self:Print(string.format(L["Renamed \"%s\" to \"%s\""], old, new)) + overrideName = new + Options:Reload() + end + + local Restore = newButton(self, "Restore") + Restore:SetPoint("Left", Rename, "Right", 5, 0) + Restore.click = function() + if forceOverride == true then + --override class restrictions! + local old, new = string.split(" ", pName:GetText(), 2) + ActionBarSaver:RestoreProfile(old, overrideClass or playerClass) + else + SlashCmdList.ABS("restore "..pName:GetText()) + --workaround since some of the error reporting is stored as locals in ActionButtonSaver.lua + end + forceOverride = nil + end + Restore.tooltipText = "" + + + local Clear = newButton(self, "Clear") + Clear:SetPoint("Left", Restore, "Right", 5, 0) + Clear.click = function() + ActionBarSaver:ClearActionBars() + end + + pName:SetScript("OnTextChanged", function() + local t = pName:GetText() + if string.gsub(t, " ", "") == "" then + Save:Disable() + Delete:Disable() + Rename:Disable() + Restore:Disable() + else + if string.find(t," ") then + Save:Disable() + Rename:Enable() + else + Save:Enable() + Rename:Disable() + end + Delete:Enable() + if (overrideClass and overrideClass ~= playerClass) and (forceOverride == nil) then + Restore:Disable() + else + Restore:Enable() + end + end + end) + + local macros = newCheck(self, "Restore Macros") + function macros.click() + self:GetDB().macro = not self:GetDB().macro + return self:GetDB().macro + end + function macros.onShow() + return self:GetDB().macro + end + local _, text = string.split("-", L["/abs macro - Attempts to restore macros that have been deleted for a profile."]) + macros.onEnter = text + + macros:Show() + + local rank = newCheck(self, "Restore Highest Rank") + function rank.click() + self:GetDB().restoreRank = not self:GetDB().restoreRank + return self:GetDB().restoreRank + end + function rank.onShow() + return self:GetDB().restoreRank + end + local _, text = string.split("-", L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."]) + rank.onEnter = text + rank:Show() + + local count = newCheck(self, "Item Count") + function count.click() + self:GetDB().checkCount = not self:GetDB().checkCount + return self:GetDB().checkCount + end + function count.onShow() + return self:GetDB().checkCount + end + local _, text = string.split("-", L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."]) + count.onEnter = text + count:Show() + + local class = newCheck(self, "Leave Class") + + function class.onShow() + return self:GetDB().leaveClass + end + local text = "Do not remove class specific spells or macros." + class.onEnter = text + class:Show() + + local noClear = newCheck(self, "Leave Current") + + function class.click() + self:GetDB().leaveClass = not self:GetDB().leaveClass + if self:GetDB().leaveClass == true then + self:GetDB().leaveAll = nil + end + noClear:SetChecked(self:GetDB().leaveAll) + return self:GetDB().leaveClass + end + + function noClear.click() + self:GetDB().leaveAll = not self:GetDB().leaveAll + if self:GetDB().leaveAll == true then + self:GetDB().leaveClass = nil + end + class:SetChecked(self:GetDB().leaveClass) + return self:GetDB().leaveAll + end + function noClear.onShow() + return self:GetDB().leaveAll + end + local text = "Do not remove anything from your action bars, just add new ones from the selected profile." + noClear.onEnter = text + noClear:Show() + + + + local ignorePlacement = newCheck(self, "Ignore Class") + function ignorePlacement.click() + self:GetDB().ignoreClass = not self:GetDB().ignoreClass + return self:GetDB().ignoreClass + end + function ignorePlacement.onShow() + return self:GetDB().ignoreClass + end + local text = "Ignore any spells or macros not specific to your current class." + ignorePlacement.onEnter = text + ignorePlacement:Show() + + + + local buttonContainer = CreateFrame("Frame",nil, self) + + buttonContainer:SetPoint("TopLeft", prevCheck, "BottomLeft", 0, -25) + buttonContainer:SetPoint("BottomRight", 25, 10) + + self.bc = buttonContainer + + + local title = self:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") + title:SetText("Saved Profiles") + title:SetPoint("BottomLeft", self.bc, "TopLeft", 10,5) + + self:SetScript("OnEvent", self.Reload) + self:RegisterEvent("ADDON_LOADED") + self:SetScript("OnShow", self.Reload) + self:SetScript("OnSizeChanged", self.SetProfileButtons) + Options:Reload() +end) + +local used = {} +local unused = {} + +function Options:getButton(index) + if used[index] then + return used[index] + else + if #unused ~= 0 then + local b = unused[1] + tremove(unused, 1) + tinsert(used, b) + return b + else + local b = newButton(self.bc, "") + b:SetWidth(125) + tinsert(used, b) + return b + end + end +end + +local W, H = 125, 26 +local maxCols, maxRows = 4, 12 + + +function Options:SetProfileButtons() + local profiles = self:GetAllProfiles() + while #used > #profiles do + used[1]:Hide() + tinsert(unused, used[1]) + + tremove(used, 1) + end + + local height = H + ((self.bc:GetHeight() - (maxRows * H)) / maxRows) + local width = W + ((self.bc:GetWidth() - (maxCols * W)) / maxCols) + + for index, profile in pairs(profiles) do + local b = self:getButton(index) + b.Text:SetText(profile.name) + --this extra line below makes the tooltip display the profile name on one line, and class on the second. + b.tooltipText = profile.name..[[ + +]]..profile.class + + b.click = function() + overrideClass = profile.class + overrideName = profile.name + if IsShiftKeyDown() then + forceOverride = true + else + forceOverride = nil + end + self:Reload() + end + + local row = (index - 1) % maxRows + local col = floor((index - 1) / maxRows) + + local x = width * col + local y = height * row + + if x and y then + b:ClearAllPoints() + b:SetPoint("TopLeft", x, -y) + end + + b:Show() + end +end \ No newline at end of file diff --git a/localization/enUS.lua b/localization/enUS.lua index b6d5cef..c1fb76f 100644 --- a/localization/enUS.lua +++ b/localization/enUS.lua @@ -1,68 +1,68 @@ local ABS = select(2, ...) local L = {} -L["%s Profiles"] = "%s Profiles" -L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring." -L["/abs delete - Deletes the saved profile."] = "/abs delete - Deletes the saved profile." -L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Lists the errors that happened on the last restore (if any)." -L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa." -L["/abs list - Lists all saved profiles."] = "/abs list - Lists all saved profiles." -L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Toggles auto saving of the current profile whenever you leave the world." -L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Attempts to restore macros that have been deleted for a profile." -L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally." -L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Renames a saved profile from oldProfile to newProfile." -L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Changes your action bars to the passed profile." -L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Saves your current action bar setup under the given profile." -L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Tests restoring a profile, results will be outputted to chat." -L["Also moved from the unknown category to %s."] = "Also moved from the unknown category to %s." -L["Auto macro restoration is now disabled!"] = "Auto macro restoration is now disabled!" -L["Auto macro restoration is now enabled!"] = "Auto macro restoration is now enabled!" -L["Auto profile save on logout is disabled!"] = "Auto profile save on logout is disabled!" -L["Auto profile save on logout is enabled!"] = "Auto profile save on logout is enabled!" -L["Auto restoring highest spell rank is now disabled!"] = "Auto restoring highest spell rank is now disabeld!" -L["Auto restoring highest spell rank is now enabled!"] = "Auto restoring highest spell rank is now enabled!" -L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "Cannot rename \"%s\" to \"%s\" a profile already exists for %s." -L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "Cannot restore profile \"%s\", you can only restore profiles saved to your class." -L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "Cannot test restore profile \"%s\", you can only test restore profiles saved to your class." -L["Checking item count is now disabled!"] = "Checking item count is now disabled!" -L["Checking item count is now enabled!"] = "Checking item count is now enabled!" -L["DEATHKNIGHT"] = "Death Knight" -L["Deleted saved profile %s."] = "Deleted saved profile %s." -L["DRUID"] = "Druid" -L["Errors found: %d"] = "Errors found: %d" -L["HUNTER"] = "Hunter" -L["Instant"] = "Instant" -L["Invalid spells passed, remember you must put quotes around both of them."] = "Invalid spells passed, remember you must put quotes around both of them." -L["MAGE"] = "Mage" -L["Miscellaneous"] = "Miscellaneous" -L["MONK"] = "Monk" -L["No errors found!"] = "No errors found!" -L["No name specified to rename \"%s\" to."] = "No name specified to rename \"%s\" to." -L["No profile with the name \"%s\" exists."] = "No profile with the name \"%s\" exists." -L["PALADIN"] = "Paladin" -L["PRIEST"] = "Priest" -L["Profile List"] = "Profile List" -L["Renamed \"%s\" to \"%s\""] = "Renamed \"%s\" to \"%s\"" -L["Restored profile %s!"] = "Restored profile %s!" -L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restored profile %s, failed to restore %d buttons type /abs errors for more information." -L["ROGUE"] = "Rogue" -L["Saved profile %s!"] = "Saved profile %s!" -L["SHAMAN"] = "Shaman" -L["Slash commands"] = "Slash commands" -L["Spells \"%s\" and \"%s\" are now linked."] = "Spells \"%s\" and \"%s\" are now linked." -L["The profile %s has been moved from the unknown category to %s."] = "The profile %s has been moved from the unknown category to %s." -L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet." -L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore." -L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "Unable to restore item \"%s\" to slot #%d, cannot be found in inventory." -L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect." -L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "Unable to restore macro id #%d to slot #%d, it appears to have been deleted." -L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "Unable to restore macros, you already have 36 global and 18 per character ones created." -L["Unable to restore profile \"%s\", you are in combat."] = "Unable to restore profile \"%s\", you are in combat." -L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet." -L["UNKNOWN"] = "Unknown" -L["WARLOCK"] = "Warlock" -L["WARRIOR"] = "Warrior" -L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "You cannot rename \"%s\" to \"%s\" they are the same profile names." -L["Your DB has been upgraded to the new storage format."] = "Your DB has been upgraded to the new storage format." +L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring." +L["/abs delete - Deletes the saved profile."] = "/abs delete - Deletes the saved profile." +L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Lists the errors that happened on the last restore (if any)." +L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa." +L["/abs list - Lists all saved profiles."] = "/abs list - Lists all saved profiles." +L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Toggles auto saving of the current profile whenever you leave the world." +L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Attempts to restore macros that have been deleted for a profile." +L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally." +L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Renames a saved profile from oldProfile to newProfile." +L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Changes your action bars to the passed profile." +L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Saves your current action bar setup under the given profile." +L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Tests restoring a profile, results will be outputted to chat." +L["Also moved from the unknown category to %s."] = "Also moved from the unknown category to %s." +L["Auto macro restoration is now disabled!"] = "Auto macro restoration is now disabled!" +L["Auto macro restoration is now enabled!"] = "Auto macro restoration is now enabled!" +L["Auto profile save on logout is disabled!"] = "Auto profile save on logout is disabled!" +L["Auto profile save on logout is enabled!"] = "Auto profile save on logout is enabled!" +L["Auto restoring highest spell rank is now disabled!"] = "Auto restoring highest spell rank is now disabeld!" +L["Auto restoring highest spell rank is now enabled!"] = "Auto restoring highest spell rank is now enabled!" +L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "Cannot rename \"%s\" to \"%s\" a profile already exists for %s." +L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "Cannot restore profile \"%s\", you can only restore profiles saved to your class." +L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "Cannot test restore profile \"%s\", you can only test restore profiles saved to your class." +L["Checking item count is now disabled!"] = "Checking item count is now disabled!" +L["Checking item count is now enabled!"] = "Checking item count is now enabled!" +L["DEATHKNIGHT"] = "Death Knight" +L["Deleted saved profile %s."] = "Deleted saved profile %s." +L["DRUID"] = "Druid" +L["Errors found: %d"] = "Errors found: %d" +L["HUNTER"] = "Hunter" +L["Instant"] = "Instant" +L["Invalid spells passed, remember you must put quotes around both of them."] = "Invalid spells passed, remember you must put quotes around both of them." +L["MAGE"] = "Mage" +L["Miscellaneous"] = "Miscellaneous" +L["MONK"] = "Monk" +L["No errors found!"] = "No errors found!" +L["No name specified to rename \"%s\" to."] = "No name specified to rename \"%s\" to." +L["No profile with the name \"%s\" exists."] = "No profile with the name \"%s\" exists." +L["PALADIN"] = "Paladin" +L["PRIEST"] = "Priest" +L["Profile List"] = "Profile List" +L["Renamed \"%s\" to \"%s\""] = "Renamed \"%s\" to \"%s\"" +L["Restored profile %s!"] = "Restored profile %s!" +L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restored profile %s, failed to restore %d buttons type /abs errors for more information." +L["ROGUE"] = "Rogue" +L["Saved profile %s!"] = "Saved profile %s!" +L["SHAMAN"] = "Shaman" +L["Slash commands"] = "Slash commands" +L["Spells \"%s\" and \"%s\" are now linked."] = "Spells \"%s\" and \"%s\" are now linked." +L["%s Profiles"] = "%s Profiles" +L["The profile %s has been moved from the unknown category to %s."] = "The profile %s has been moved from the unknown category to %s." +L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet." +L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore." +L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "Unable to restore item \"%s\" to slot #%d, cannot be found in inventory." +L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect." +L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "Unable to restore macro id #%d to slot #%d, it appears to have been deleted." +L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "Unable to restore macros, you already have 36 global and 18 per character ones created." +L["Unable to restore profile \"%s\", you are in combat."] = "Unable to restore profile \"%s\", you are in combat." +L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet." +L["UNKNOWN"] = "Unknown" +L["WARLOCK"] = "Warlock" +L["WARRIOR"] = "Warrior" +L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "You cannot rename \"%s\" to \"%s\" they are the same profile names." +L["Your DB has been upgraded to the new storage format."] = "Your DB has been upgraded to the new storage format." ABS.L = L diff --git a/localization/esMX.lua b/localization/esMX.lua index d08fea7..ac9df9f 100644 --- a/localization/esMX.lua +++ b/localization/esMX.lua @@ -1,68 +1,68 @@ if( GetLocale() ~= "esMX" ) then return end local L = {} -L["%s Profiles"] = "Perfiles %s" -L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Comprobar de que tiene el objeto en su inventario antes de restaurarlo. Activa esta opción si se desconecta al restaurar." -L["/abs delete - Deletes the saved profile."] = "/abs delete - Eliminar el perfil guardado." -L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Listar los errores (si los hay) que ocurrieron en la previa restauración." -L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Enlazar un hechizo con otro. INCLUYA LAS COMILLAS. Por ejemplo, si se introduce \"Fusión de las sombras\" \"Pisotón de guerra\", se utilizará \"Pisotón de guerra\" cuando no se encuentra \"Fusión de las sombras\", y viceversa." -L["/abs list - Lists all saved profiles."] = "/abs list - Listar los perfiles guardados." -L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Guardar automáticamente la perfil acutal al desconectar." -L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Tratar a restaurar los macros que se han eliminado para el perfil." -L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Restaurar el rango más alto del hechizo, o el rango guardado originalmente." -L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Cambiar el nombre de un perfil guardado de perfilAntiguo a perfilNuevo." -L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Cambiar las barras de acción al perfil especificado." -L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Guardar la configuración actual de las barras de acción al perfil especificado." -L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Ensayar a restaurar un perfil, y informar los resultados a chat." -L["Also moved from the unknown category to %s."] = "También movió desde la categoría desconocida a %s." -L["Auto macro restoration is now disabled!"] = "Restauración automática está ahora desactivado!" -L["Auto macro restoration is now enabled!"] = "Restauración automática está ahora activado!" -L["Auto profile save on logout is disabled!"] = "Guardado automático al desconectar está ahora desactivado!" -L["Auto profile save on logout is enabled!"] = "Guardado automático al desconectar está ahora activado!" -L["Auto restoring highest spell rank is now disabled!"] = "Restauración automática del rango más alto está ahora desactivado!" -L["Auto restoring highest spell rank is now enabled!"] = "Restauración automática del rango más alto está ahora activado!" -L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "No puede cambiar el nombre \"%s\" a \"%s\" -- un perfil ya existe en %s." -L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "No puede restaurar \"%s\" -- sólo puede restaurar los perfiles guardados en su clase." -L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "No puede ensayar \"%s\" -- sólo puede ensayar los perfiles guardados en su clase." -L["Checking item count is now disabled!"] = "Comprobación de objetos está ahora desactivado!" -L["Checking item count is now enabled!"] = "Comprobación de objetos está ahora activado!" -L["DEATHKNIGHT"] = "Caballero de la Muerte" -L["Deleted saved profile %s."] = "Eliminó el perfil %s." -L["DRUID"] = "Druida" -L["Errors found: %d"] = "Errores encontrados: %d" -L["HUNTER"] = "Cazador" -L["Instant"] = "Instante" -L["Invalid spells passed, remember you must put quotes around both of them."] = "Hechizos inválidos especificados. Recuerde, debe escribir comillas alrededor de ambos nombres." -L["MAGE"] = "Mago" -L["Miscellaneous"] = "Misceláneo" -L["MONK"] = "Monje" -L["No errors found!"] = "No se encontraron errores!" -L["No name specified to rename \"%s\" to."] = "Ningún nombre especificado para cambiar de \"%s\"." -L["No profile with the name \"%s\" exists."] = "No existe un perfil del nombre \"%s\"." -L["PALADIN"] = "Paladin" -L["PRIEST"] = "Sacerdote" -L["Profile List"] = "Lista de perfiles" -L["Renamed \"%s\" to \"%s\""] = "Cambió el nombre de \"%s\" a \"%s\"." -L["Restored profile %s!"] = "Restauró el perfil %s!" -L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restauró el perfil %s, pero no pudo restaurar %d botones. Escribe \"/abs errors\" para más detalles." -L["ROGUE"] = "Picaro" -L["Saved profile %s!"] = "Guardó el perfil %s!" -L["SHAMAN"] = "Chamán" -L["Slash commands"] = "Comandos" -L["Spells \"%s\" and \"%s\" are now linked."] = "Los hechizos \"%s\" y \"%s\" ahora están enlazados." -L["The profile %s has been moved from the unknown category to %s."] = "El perfil %s se ha movido de la categoría desconocido a %s." -L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "No puede restuarar \"%s\" a la posición #%d, porque no parece existir todavía." -L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "No puede restaurar el conjunto de equipamiento \"%s\" a la posición #%d, porque no parece existir más." -L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque no se encontró en su inventario." -L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque está en los reinos de torneos de arena, y se desconectará si trata restraurarlo." -L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "No puede restaurar el macro #%d a la posición #%d, porque parece que ha sido eliminado." -L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "No puede restaurar los macros, porque ya tiene 36 macros globales y 18 específicos a su personaje." -L["Unable to restore profile \"%s\", you are in combat."] = "No puede restaurar el eprfil \"%s\", porque está en combate." -L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "No puede restaurar \"%s\" a la posición #%d, no parece que has aprendido aún." -L["UNKNOWN"] = "Desconocido" -L["WARLOCK"] = "Brujo" -L["WARRIOR"] = "Guerrero" -L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "No puede cambiar el nombre de \"%s\" a \"%s\" porque ambos nombres son idénticos." -L["Your DB has been upgraded to the new storage format."] = "la configuración guardada se ha actualizado al nuevo formato de almacenamiento." +L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - Comprobar de que tiene el objeto en su inventario antes de restaurarlo. Activa esta opción si se desconecta al restaurar." +L["/abs delete - Deletes the saved profile."] = "/abs delete - Eliminar el perfil guardado." +L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - Listar los errores (si los hay) que ocurrieron en la previa restauración." +L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - Enlazar un hechizo con otro. INCLUYA LAS COMILLAS. Por ejemplo, si se introduce \"Fusión de las sombras\" \"Pisotón de guerra\", se utilizará \"Pisotón de guerra\" cuando no se encuentra \"Fusión de las sombras\", y viceversa." +L["/abs list - Lists all saved profiles."] = "/abs list - Listar los perfiles guardados." +L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - Guardar automáticamente la perfil acutal al desconectar." +L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - Tratar a restaurar los macros que se han eliminado para el perfil." +L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - Restaurar el rango más alto del hechizo, o el rango guardado originalmente." +L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - Cambiar el nombre de un perfil guardado de perfilAntiguo a perfilNuevo." +L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - Cambiar las barras de acción al perfil especificado." +L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - Guardar la configuración actual de las barras de acción al perfil especificado." +L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - Ensayar a restaurar un perfil, y informar los resultados a chat." +L["Also moved from the unknown category to %s."] = "También movió desde la categoría desconocida a %s." +L["Auto macro restoration is now disabled!"] = "Restauración automática está ahora desactivado!" +L["Auto macro restoration is now enabled!"] = "Restauración automática está ahora activado!" +L["Auto profile save on logout is disabled!"] = "Guardado automático al desconectar está ahora desactivado!" +L["Auto profile save on logout is enabled!"] = "Guardado automático al desconectar está ahora activado!" +L["Auto restoring highest spell rank is now disabled!"] = "Restauración automática del rango más alto está ahora desactivado!" +L["Auto restoring highest spell rank is now enabled!"] = "Restauración automática del rango más alto está ahora activado!" +L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "No puede cambiar el nombre \"%s\" a \"%s\" -- un perfil ya existe en %s." +L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "No puede restaurar \"%s\" -- sólo puede restaurar los perfiles guardados en su clase." +L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "No puede ensayar \"%s\" -- sólo puede ensayar los perfiles guardados en su clase." +L["Checking item count is now disabled!"] = "Comprobación de objetos está ahora desactivado!" +L["Checking item count is now enabled!"] = "Comprobación de objetos está ahora activado!" +L["DEATHKNIGHT"] = "Caballero de la Muerte" +L["Deleted saved profile %s."] = "Eliminó el perfil %s." +L["DRUID"] = "Druida" +L["Errors found: %d"] = "Errores encontrados: %d" +L["HUNTER"] = "Cazador" +L["Instant"] = "Instante" +L["Invalid spells passed, remember you must put quotes around both of them."] = "Hechizos inválidos especificados. Recuerde, debe escribir comillas alrededor de ambos nombres." +L["MAGE"] = "Mago" +L["Miscellaneous"] = "Misceláneo" +L["MONK"] = "Monje" +L["No errors found!"] = "No se encontraron errores!" +L["No name specified to rename \"%s\" to."] = "Ningún nombre especificado para cambiar de \"%s\"." +L["No profile with the name \"%s\" exists."] = "No existe un perfil del nombre \"%s\"." +L["PALADIN"] = "Paladin" +L["PRIEST"] = "Sacerdote" +L["Profile List"] = "Lista de perfiles" +L["Renamed \"%s\" to \"%s\""] = "Cambió el nombre de \"%s\" a \"%s\"." +L["Restored profile %s!"] = "Restauró el perfil %s!" +L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "Restauró el perfil %s, pero no pudo restaurar %d botones. Escribe \"/abs errors\" para más detalles." +L["ROGUE"] = "Picaro" +L["Saved profile %s!"] = "Guardó el perfil %s!" +L["SHAMAN"] = "Chamán" +L["Slash commands"] = "Comandos" +L["Spells \"%s\" and \"%s\" are now linked."] = "Los hechizos \"%s\" y \"%s\" ahora están enlazados." +L["%s Profiles"] = "Perfiles %s" +L["The profile %s has been moved from the unknown category to %s."] = "El perfil %s se ha movido de la categoría desconocido a %s." +L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "No puede restuarar \"%s\" a la posición #%d, porque no parece existir todavía." +L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "No puede restaurar el conjunto de equipamiento \"%s\" a la posición #%d, porque no parece existir más." +L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque no se encontró en su inventario." +L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "No puede restuarar el objecto \"%s\" a la posición #%d, porque está en los reinos de torneos de arena, y se desconectará si trata restraurarlo." +L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "No puede restaurar el macro #%d a la posición #%d, porque parece que ha sido eliminado." +L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "No puede restaurar los macros, porque ya tiene 36 macros globales y 18 específicos a su personaje." +L["Unable to restore profile \"%s\", you are in combat."] = "No puede restaurar el eprfil \"%s\", porque está en combate." +L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "No puede restaurar \"%s\" a la posición #%d, no parece que has aprendido aún." +L["UNKNOWN"] = "Desconocido" +L["WARLOCK"] = "Brujo" +L["WARRIOR"] = "Guerrero" +L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "No puede cambiar el nombre de \"%s\" a \"%s\" porque ambos nombres son idénticos." +L["Your DB has been upgraded to the new storage format."] = "la configuración guardada se ha actualizado al nuevo formato de almacenamiento." local ABS = select(2, ...) ABS.L = setmetatable(L, {__index = ABS.L}) diff --git a/localization/zhTW.lua b/localization/zhTW.lua index 50bcabd..ffe2c31 100644 --- a/localization/zhTW.lua +++ b/localization/zhTW.lua @@ -1,68 +1,5 @@ if( GetLocale() ~= "zhTW" ) then return end local L = {} -L["%s Profiles"] = "%s 設定檔" -L["/abs count - Toggles checking if you have the item in your inventory before restoring it, use if you have disconnect issues when restoring."] = "/abs count - 切換在回復設定檔前,是否檢查物品已在庫存中。如遇到回復中斷,請使用此指令。" -L["/abs delete - Deletes the saved profile."] = "/abs delete - 刪除已儲存之設定檔。" -L["/abs errors - Lists the errors that happened on the last restore (if any)."] = "/abs errors - 列出上次載入設定檔時的錯誤(如有)。" -L["/abs link \"\" \"\" - Links a spell with another, INCLUDE QUOTES for example you can use \"Shadowmeld\" \"War Stomp\" so if War Stomp can't be found, it'll use Shadowmeld and vica versa."] = "/abs link \"\" \"\" - 連結法術,格式包含括號\"\" ,例如可用 \"影遁\" \"戰爭踐踏\" ,若未能找到 戰爭踐踏 就使用 影遁,反之亦然。" -L["/abs list - Lists all saved profiles."] = "/abs list - 列出所有已儲存之設定檔。" -L["/abs logout - Toggles auto saving of the current profile whenever you leave the world."] = "/abs logout - 切換當你登出時是否自動儲存現有設定檔。" -L["/abs macro - Attempts to restore macros that have been deleted for a profile."] = "/abs macro - 嘗試回復設定檔內被刪除的巨集。" -L["/abs rank - Toggles if ABS should restore the highest rank of the spell, or the one saved originally."] = "/abs rank - 切換 ABS 是否回復到法術之最高等級或回復到已儲存之法術等級。" -L["/abs rename - Renames a saved profile from oldProfile to newProfile."] = "/abs rename - 重新命名已儲存之設定檔名稱,由 (舊檔名) 改為 (新檔名)。" -L["/abs restore - Changes your action bars to the passed profile."] = "/abs restore - 更改動作條為已儲存之設定檔。" -L["/abs save - Saves your current action bar setup under the given profile."] = "/abs save - 儲存現有動作條為設定檔,為自定的設定檔名稱。" -L["/abs test - Tests restoring a profile, results will be outputted to chat."] = "/abs test - 測試回復設定檔,結果會在對話框顯示。" -L["Also moved from the unknown category to %s."] = "並由未知類別移動到 %s。" -L["Auto macro restoration is now disabled!"] = "巨集自動回復已停用!" -L["Auto macro restoration is now enabled!"] = "巨集自動回復已啟用!" -L["Auto profile save on logout is disabled!"] = "登出時自動儲存設定檔已停用!" -L["Auto profile save on logout is enabled!"] = "登出時自動儲存設定檔已啟用!" -L["Auto restoring highest spell rank is now disabled!"] = "自動回復至法術的最高等級已最停用!" -L["Auto restoring highest spell rank is now enabled!"] = "自動回復至法術的最高等級已最啟用!" -L["Cannot rename \"%s\" to \"%s\" a profile already exists for %s."] = "不能重新命名 \"%s\" 至 \"%s\" %s 該名稱已存在。" -L["Cannot restore profile \"%s\", you can only restore profiles saved to your class."] = "不能回復設定檔 \"%s\",只能回復相同職業所儲存之設定檔。" -L["Cannot test restore profile \"%s\", you can only test restore profiles saved to your class."] = "不能測試回復設定檔 \"%s\",只能測試回復相同職業所儲存之設定檔。" -L["Checking item count is now disabled!"] = "物檢查品已停用!" -L["Checking item count is now enabled!"] = "物檢查品已啟用!" -L["DEATHKNIGHT"] = "死亡騎士" -L["Deleted saved profile %s."] = "刪除已儲存的設定檔 %s。" -L["DRUID"] = "德魯伊" -L["Errors found: %d"] = "發生錯誤:%d" -L["HUNTER"] = "獵人" -L["Instant"] = "立刻" -L["Invalid spells passed, remember you must put quotes around both of them."] = "無效的法術名稱,法術名稱必需有括號。" -L["MAGE"] = "法師" -L["Miscellaneous"] = "雜項" -L["MONK"] = "武僧" -L["No errors found!"] = "無錯誤發生!" -L["No name specified to rename \"%s\" to."] = "重新命名 \"%s\" 時,未有設定名稱。" -L["No profile with the name \"%s\" exists."] = "沒有名為 \"%s\" 的設定檔。" -L["PALADIN"] = "聖騎士" -L["PRIEST"] = "牧師" -L["Profile List"] = "設定檔列表" -L["Renamed \"%s\" to \"%s\""] = "重新命名 \"%s\" 為 \"%s\"" -L["Restored profile %s!"] = "已回復到設定檔 %s!" -L["Restored profile %s, failed to restore %d buttons type /abs errors for more information."] = "已回復到設定檔 %s, 未能回復 %d 按鍵,輸入 /abs errors 以取得更多資料。" -L["ROGUE"] = "盜賊" -L["Saved profile %s!"] = "已儲存設定檔 %s!" -L["SHAMAN"] = "薩滿" -L["Slash commands"] = "斜線指令" -L["Spells \"%s\" and \"%s\" are now linked."] = "法術 \"%s\" 和 \"%s\" 已連結。" -L["The profile %s has been moved from the unknown category to %s."] = "設定檔 %s 已由未知類別移動到 %s。" -L["Unable to restore companion \"%s\" to slot #%d, it does not appear to exist yet."] = "未能回復 小寵物 \"%s\" 至 位置 #%d,小寵物 \"%s\" 未存在。" -L["Unable to restore equipment set \"%s\" to slot #%d, it does not appear to exist anymore."] = "未能回復套裝 \"%s\" 至 位置 #%d,套裝未存在。" -L["Unable to restore item \"%s\" to slot #%d, cannot be found in inventory."] = "未能回復物品 \"%s\" 至 位置 #%d,物品不在庫存中。" -L["Unable to restore item \"%s\" to slot #%d, you on the Arena Tournament Realms and attempting to restore that item would cause a disconnect."] = "未能回復物品 \"%s\" 至 位置 #%d, 你現處身於競技場區,嘗試回復會導致中斷。" -L["Unable to restore macro id #%d to slot #%d, it appears to have been deleted."] = "未能回復巨集 #%d 至 位置 #%d,巨集已被刪除。" -L["Unable to restore macros, you already have 36 global and 18 per character ones created."] = "未能回復巨集,你已創建了 36 個共享巨集及 18 個每個角色獨有的巨集。" -L["Unable to restore profile \"%s\", you are in combat."] = "未能回復設定檔 \"%s\",你處於戰鬥中。" -L["Unable to restore spell \"%s\" to slot #%d, it does not appear to have been learned yet."] = "未能回復法術 \"%s\" 至 位置 #%d,你並未學習到此法術。" -L["UNKNOWN"] = "未知" -L["WARLOCK"] = "術士" -L["WARRIOR"] = "戰士" -L["You cannot rename \"%s\" to \"%s\" they are the same profile names."] = "不能重新命名 \"%s\" 為 \"%s\",名稱相同。" -L["Your DB has been upgraded to the new storage format."] = "你的 DB 已升級為新儲存格式。" local ABS = select(2, ...) ABS.L = setmetatable(L, {__index = ABS.L})