TabMacros: tab-on-action-bar service shared with other addons
The character sheet's tab macros move to TabMacros.lua, which any addon or AIO window can call (Register, Pickup, EnableDrag); ActionBar's ActionButton_Update hook shows each registered tab's icon. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -439,9 +439,9 @@ end
|
||||
-- The client rewrites the normal texture on every button update: silence it again after.
|
||||
if hooksecurefunc then
|
||||
hooksecurefunc("ActionButton_Update", function(self)
|
||||
-- a character sheet tab on the bar shows the tab's icon (CharacterFrame.lua)
|
||||
if ForeverUI.ShowCharacterTabIcon then
|
||||
ForeverUI.ShowCharacterTabIcon(self)
|
||||
-- a window tab on the bar shows the tab's icon (TabMacros.lua)
|
||||
if ForeverUI.TabMacros then
|
||||
ForeverUI.TabMacros.ShowIcon(self)
|
||||
end
|
||||
if self and self.foreverSkinned then
|
||||
silenceNormalTexture(self)
|
||||
|
||||
@@ -1710,20 +1710,15 @@ if hooksecurefunc and type(_G["CharacterFrame_TabBoundsCheck"]) == "function" th
|
||||
hooksecurefunc("CharacterFrame_TabBoundsCheck", keepTabWidth)
|
||||
end
|
||||
|
||||
-- Side tabs on the action bars. 3.3.5 bars hold spells, items, macros, equipment sets and
|
||||
-- companions only: a dragged tab becomes an account macro whose body opens its screen, made once
|
||||
-- and found again by its body. On a bar the macro shows the tab's icon (ActionButton_Update hook
|
||||
-- below). Making a macro needs a free slot and is refused in combat; picking up an existing one
|
||||
-- is not.
|
||||
-- Side tabs on the action bars (TabMacros.lua): a dragged tab becomes a macro whose body opens
|
||||
-- its screen; on a bar it shows the tab's icon.
|
||||
local TAB_MACRO_BODY = "/run ForeverUI.ToggleCharacterTab(%s)"
|
||||
local TAB_MACRO_NAMES = {
|
||||
[1] = "CHARACTER", [2] = "PET", [3] = "REPUTATION", [4] = "SKILLS", [5] = "CURRENCY",
|
||||
pvp = "PVP", stats = "STATISTICS", mounts = "MOUNTS",
|
||||
}
|
||||
local MACRO_NAME_BYTES = 16
|
||||
|
||||
-- Macro icon, seen on the cursor and in the macro window: the nearest icon of the client's
|
||||
-- macro list (Interface\Icons), the question mark (index 1) when none is there
|
||||
-- Macro icon, seen on the cursor and in the macro window: the nearest game icon
|
||||
local TAB_MACRO_ICONS = {
|
||||
[1] = "INV_Chest_Cloth_17", [3] = "Achievement_Reputation_01", [4] = "Trade_Engineering",
|
||||
[5] = "INV_Misc_Coin_01", stats = "INV_Misc_Note_01", mounts = "Ability_Mount_RidingHorse",
|
||||
@@ -1735,18 +1730,6 @@ local function tabMacroBody(key)
|
||||
type(key) == "number" and tostring(key) or ('"' .. key .. '"'))
|
||||
end
|
||||
|
||||
-- The tab a macro body opens, or nil
|
||||
local function tabMacroKey(body)
|
||||
local key = body and body:match('ForeverUI%.ToggleCharacterTab%("?(%w+)"?%)')
|
||||
if not key then
|
||||
return nil
|
||||
end
|
||||
key = tonumber(key) or key
|
||||
if TAB_MACRO_NAMES[key] then
|
||||
return key
|
||||
end
|
||||
end
|
||||
|
||||
-- The tab's icon, also before the sheet was ever opened (its tabs do not exist yet)
|
||||
local function tabIcon(key)
|
||||
local tab = tabs[key]
|
||||
@@ -1765,94 +1748,35 @@ local function tabIcon(key)
|
||||
return TAB_ICONS[key]
|
||||
end
|
||||
|
||||
-- Cuts a name to the macro limit without splitting a UTF-8 character
|
||||
local function macroName(key)
|
||||
local name = _G[TAB_MACRO_NAMES[key]] or TAB_MACRO_NAMES[key]
|
||||
if #name <= MACRO_NAME_BYTES then
|
||||
return name
|
||||
end
|
||||
local cut = MACRO_NAME_BYTES
|
||||
while cut > 0 and name:byte(cut + 1) and name:byte(cut + 1) >= 0x80
|
||||
and name:byte(cut + 1) < 0xC0 do
|
||||
cut = cut - 1
|
||||
end
|
||||
return name:sub(1, cut)
|
||||
end
|
||||
|
||||
local function findTabMacro(key)
|
||||
if not GetMacroInfo then
|
||||
return nil
|
||||
end
|
||||
local body = tabMacroBody(key)
|
||||
local last = (MAX_ACCOUNT_MACROS or 36) + (MAX_CHARACTER_MACROS or 18)
|
||||
for index = 1, last do
|
||||
local _, _, macroBody = GetMacroInfo(index)
|
||||
if macroBody and macroBody:gsub("%s+$", "") == body then
|
||||
return index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function macroIconIndex(key)
|
||||
local function tabMacroIcon(key)
|
||||
local wanted = TAB_MACRO_ICONS[key]
|
||||
if key == 2 then
|
||||
wanted = PET_TAB[select(2, UnitClass("player")) or ""] or PET_TAB.HUNTER
|
||||
return PET_TAB[select(2, UnitClass("player")) or ""] or PET_TAB.HUNTER
|
||||
elseif type(wanted) == "table" then
|
||||
wanted = wanted[(UnitFactionGroup and UnitFactionGroup("player")) or "Alliance"]
|
||||
return wanted[(UnitFactionGroup and UnitFactionGroup("player")) or "Alliance"]
|
||||
or wanted.Alliance
|
||||
end
|
||||
if not wanted or not GetNumMacroIcons or not GetMacroIconInfo then
|
||||
return 1
|
||||
end
|
||||
wanted = "\\" .. wanted:lower()
|
||||
for index = 1, GetNumMacroIcons() do
|
||||
local texture = GetMacroIconInfo(index)
|
||||
if texture and texture:lower():sub(-#wanted) == wanted then
|
||||
return index
|
||||
end
|
||||
end
|
||||
return 1
|
||||
return wanted
|
||||
end
|
||||
|
||||
-- Puts the tab's macro on the cursor, making it first if needed
|
||||
local function pickupTab(key)
|
||||
if not PickupMacro or not TAB_MACRO_NAMES[key] then
|
||||
return
|
||||
end
|
||||
local index = findTabMacro(key)
|
||||
if not index then
|
||||
if InCombatLockdown() then
|
||||
UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT, 1, 0.1, 0.1, 1)
|
||||
return
|
||||
end
|
||||
local account, character = GetNumMacros()
|
||||
local perCharacter
|
||||
if (account or 0) >= (MAX_ACCOUNT_MACROS or 36) then
|
||||
if (character or 0) >= (MAX_CHARACTER_MACROS or 18) then
|
||||
UIErrorsFrame:AddMessage(L.CHARACTERFRAME_TAB_MACROS_FULL, 1, 0.1, 0.1, 1)
|
||||
return
|
||||
end
|
||||
perCharacter = 1
|
||||
end
|
||||
-- On the bars the tab's own icon replaces the macro's
|
||||
index = CreateMacro(macroName(key), macroIconIndex(key), tabMacroBody(key),
|
||||
perCharacter, perCharacter)
|
||||
if not index then
|
||||
return
|
||||
end
|
||||
end
|
||||
PickupMacro(index)
|
||||
local function tabMacroInfo(key)
|
||||
return {
|
||||
name = function() return _G[TAB_MACRO_NAMES[key]] or TAB_MACRO_NAMES[key] end,
|
||||
icon = function() return tabIcon(key) end,
|
||||
macroIcon = function() return tabMacroIcon(key) end,
|
||||
}
|
||||
end
|
||||
|
||||
-- The bars show the tabs' icons from login, before the sheet is opened
|
||||
for key in pairs(TAB_MACRO_NAMES) do
|
||||
ForeverUI.TabMacros.Register(tabMacroBody(key), tabMacroInfo(key))
|
||||
end
|
||||
|
||||
local function enableTabDrag(tab, key)
|
||||
if tab.foreverDrag then
|
||||
return
|
||||
end
|
||||
tab:RegisterForDrag("LeftButton")
|
||||
tab:SetScript("OnDragStart", function()
|
||||
GameTooltip:Hide()
|
||||
pickupTab(key)
|
||||
end)
|
||||
ForeverUI.TabMacros.EnableDrag(tab, tabMacroBody(key), tabMacroInfo(key))
|
||||
tab.foreverDrag = true
|
||||
end
|
||||
|
||||
@@ -1891,31 +1815,6 @@ function ForeverUI.ToggleCharacterTab(key)
|
||||
openOwnScreen(group)
|
||||
end
|
||||
|
||||
-- A tab macro on a bar shows the tab's icon, not the macro's question mark
|
||||
local function showTabIcon(button)
|
||||
local action = button and button.action
|
||||
if not action or not GetActionInfo then
|
||||
return
|
||||
end
|
||||
local kind, id = GetActionInfo(action)
|
||||
if kind ~= "macro" or not GetMacroInfo then
|
||||
return
|
||||
end
|
||||
local _, _, body = GetMacroInfo(id)
|
||||
local key = tabMacroKey(body)
|
||||
local icon = key and _G[(button:GetName() or "") .. "Icon"]
|
||||
local texture = key and tabIcon(key)
|
||||
if icon and texture then
|
||||
icon:SetTexture(texture)
|
||||
end
|
||||
end
|
||||
|
||||
-- Called from ActionBar.lua's ActionButton_Update hook (one hook for every button)
|
||||
ForeverUI.ShowCharacterTabIcon = showTabIcon
|
||||
|
||||
ForeverUI.CharacterTabMacro = { body = tabMacroBody, key = tabMacroKey, icon = tabIcon,
|
||||
pickup = pickupTab }
|
||||
|
||||
-- Creates one of our side tabs, skinned like the client's.
|
||||
-- key: tabs table key; name: frame name; group: ForeverUI.Panes group it opens
|
||||
local function createSideTab(key, name, icon, tooltip, group)
|
||||
|
||||
@@ -40,6 +40,7 @@ RaidFrame.lua
|
||||
CastBar.lua
|
||||
ActionBar.lua
|
||||
MultiBars.lua
|
||||
TabMacros.lua
|
||||
StanceBar.lua
|
||||
PetBar.lua
|
||||
TotemBar.lua
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
-- Window tabs on the action bars. 3.3.5 bars hold spells, items, macros, equipment sets and
|
||||
-- companions only: a dragged tab becomes an account macro whose body opens its window, made once
|
||||
-- and found again by its body. On a bar the macro shows the tab's icon, not the macro's. Making a
|
||||
-- macro needs a free slot and is refused in combat; picking up an existing one is not.
|
||||
-- The character sheet's side tabs use it (CharacterFrame.lua), and so can other addons and the
|
||||
-- server modules' AIO windows when ForeverUI is there:
|
||||
-- ForeverUI.TabMacros.Register(body, info): the macro with this body is a tab. info:
|
||||
-- name macro name, cut to 16 bytes (a value, or a function returning it)
|
||||
-- icon texture shown on the bars (same)
|
||||
-- macroIcon an Interface\Icons file name, for the cursor and the macro window; the question
|
||||
-- mark when the client's macro icon list does not have it (same)
|
||||
-- ForeverUI.TabMacros.Pickup(body, info): registers, then puts the macro on the cursor.
|
||||
-- ForeverUI.TabMacros.EnableDrag(button, body, info): a left drag of the button does Pickup.
|
||||
-- body may be a function(button) returning body, info, for a button reused by several tabs.
|
||||
|
||||
local M = {}
|
||||
ForeverUI.TabMacros = M
|
||||
|
||||
local L = ForeverUI.L
|
||||
local MACRO_NAME_BYTES = 16
|
||||
local BAR_PREFIXES = { "ActionButton", "BonusActionButton", "MultiBarBottomLeftButton",
|
||||
"MultiBarBottomRightButton", "MultiBarRightButton", "MultiBarLeftButton" }
|
||||
|
||||
-- body -> info
|
||||
local registry = {}
|
||||
|
||||
local function value(v)
|
||||
if type(v) == "function" then
|
||||
return v()
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
local function trim(body)
|
||||
return type(body) == "string" and (body:gsub("%s+$", "")) or nil
|
||||
end
|
||||
|
||||
-- Cuts a name to the macro limit without splitting a UTF-8 character
|
||||
local function cutName(name)
|
||||
if #name <= MACRO_NAME_BYTES then
|
||||
return name
|
||||
end
|
||||
local cut = MACRO_NAME_BYTES
|
||||
while cut > 0 and name:byte(cut + 1) and name:byte(cut + 1) >= 0x80
|
||||
and name:byte(cut + 1) < 0xC0 do
|
||||
cut = cut - 1
|
||||
end
|
||||
return name:sub(1, cut)
|
||||
end
|
||||
|
||||
local function find(body)
|
||||
if not GetMacroInfo then
|
||||
return nil
|
||||
end
|
||||
local last = (MAX_ACCOUNT_MACROS or 36) + (MAX_CHARACTER_MACROS or 18)
|
||||
for index = 1, last do
|
||||
local _, _, macroBody = GetMacroInfo(index)
|
||||
if trim(macroBody) == body then
|
||||
return index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Index of an icon in the client's macro list, 1 (the question mark) when absent
|
||||
local function iconIndex(wanted)
|
||||
if type(wanted) ~= "string" or not GetNumMacroIcons or not GetMacroIconInfo then
|
||||
return 1
|
||||
end
|
||||
wanted = "\\" .. wanted:lower()
|
||||
for index = 1, GetNumMacroIcons() do
|
||||
local texture = GetMacroIconInfo(index)
|
||||
if texture and texture:lower():sub(-#wanted) == wanted then
|
||||
return index
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
-- An action button holding a tab macro shows the tab's icon. Called after ActionButton_Update
|
||||
-- (ActionBar.lua) and on each button when a tab is registered.
|
||||
function M.ShowIcon(button)
|
||||
local action = button and button.action
|
||||
if not action or not GetActionInfo or not GetMacroInfo then
|
||||
return
|
||||
end
|
||||
local kind, id = GetActionInfo(action)
|
||||
if kind ~= "macro" then
|
||||
return
|
||||
end
|
||||
local _, _, body = GetMacroInfo(id)
|
||||
local info = registry[trim(body) or ""]
|
||||
local texture = info and value(info.icon)
|
||||
local icon = texture and button.GetName and _G[(button:GetName() or "") .. "Icon"]
|
||||
if icon then
|
||||
icon:SetTexture(texture)
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshBars()
|
||||
for _, prefix in ipairs(BAR_PREFIXES) do
|
||||
for index = 1, NUM_ACTIONBAR_BUTTONS or 12 do
|
||||
local button = _G[prefix .. index]
|
||||
if button then
|
||||
M.ShowIcon(button)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.Register(body, info)
|
||||
body = trim(body)
|
||||
if not body or type(info) ~= "table" then
|
||||
return
|
||||
end
|
||||
local known = registry[body]
|
||||
registry[body] = info
|
||||
-- A module loaded after the bars: its macros get their icon now
|
||||
if not known then
|
||||
refreshBars()
|
||||
end
|
||||
end
|
||||
|
||||
function M.Pickup(body, info)
|
||||
body = trim(body)
|
||||
if not body or not PickupMacro then
|
||||
return
|
||||
end
|
||||
M.Register(body, info)
|
||||
local index = find(body)
|
||||
if not index then
|
||||
if InCombatLockdown() then
|
||||
UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT, 1, 0.1, 0.1, 1)
|
||||
return
|
||||
end
|
||||
local account, character = GetNumMacros()
|
||||
local perCharacter
|
||||
if (account or 0) >= (MAX_ACCOUNT_MACROS or 36) then
|
||||
if (character or 0) >= (MAX_CHARACTER_MACROS or 18) then
|
||||
UIErrorsFrame:AddMessage(L.TABMACROS_FULL, 1, 0.1, 0.1, 1)
|
||||
return
|
||||
end
|
||||
perCharacter = 1
|
||||
end
|
||||
local name = cutName(tostring(info and value(info.name) or ""))
|
||||
if name == "" then
|
||||
name = "?"
|
||||
end
|
||||
index = CreateMacro(name, iconIndex(info and value(info.macroIcon)), body,
|
||||
perCharacter, perCharacter)
|
||||
if not index then
|
||||
return
|
||||
end
|
||||
end
|
||||
PickupMacro(index)
|
||||
end
|
||||
|
||||
function M.EnableDrag(button, body, info)
|
||||
if not button then
|
||||
return
|
||||
end
|
||||
if type(body) ~= "function" then
|
||||
M.Register(body, info)
|
||||
end
|
||||
button:RegisterForDrag("LeftButton")
|
||||
button:SetScript("OnDragStart", function(self)
|
||||
local b, i = body, info
|
||||
if type(body) == "function" then
|
||||
b, i = body(self)
|
||||
end
|
||||
GameTooltip:Hide()
|
||||
M.Pickup(b, i)
|
||||
end)
|
||||
end
|
||||
|
||||
M.registry = registry
|
||||
@@ -77,7 +77,6 @@ ForeverUI.AddTexts("deDE", {
|
||||
CHARACTERFRAME_MODEL_USAGE = "Modell: echelle <n> | position <x> <y> <z> | position defaut",
|
||||
CHARACTERFRAME_PANES_MISSING = "Panes.lua ist nicht geladen. Eine dem Addon hinzugefügte Datei wird erst beim nächsten Spielstart geladen: Schließt den Client und öffnet ihn erneut. Bis dahin bleibt das Charakterfenster inaktiv.",
|
||||
CHARACTERFRAME_SHOW_DETAILS = "Details anzeigen",
|
||||
CHARACTERFRAME_TAB_MACROS_FULL = "Kein freier Makroplatz: Löscht ein Makro, um diesen Reiter auf eine Leiste zu legen.",
|
||||
CHARACTERFRAME_TITLES = "Titel",
|
||||
|
||||
-- Chat.lua
|
||||
@@ -388,6 +387,9 @@ ForeverUI.AddTexts("deDE", {
|
||||
STATUSBARS_EDIT_LABEL_EXPERIENCE = "Erfahrungsleiste",
|
||||
STATUSBARS_EDIT_LABEL_REPUTATION = "Rufleiste",
|
||||
|
||||
-- TabMacros.lua
|
||||
TABMACROS_FULL = "Kein freier Makroplatz: Löscht ein Makro, um diesen Reiter auf eine Leiste zu legen.",
|
||||
|
||||
-- TabardFrame.lua
|
||||
TABARDFRAME_POSITION_USAGE = "Wappenrock: /fui tabard position <Tiefe> <seitlich> <Höhe>",
|
||||
TABARDFRAME_STATE = "Wappenrock: Kamera=%s Skalierung=%s Position=(%s, %s, %s)",
|
||||
|
||||
@@ -77,7 +77,6 @@ ForeverUI.AddTexts("enUS", {
|
||||
CHARACTERFRAME_MODEL_USAGE = "model: echelle <n> | position <x> <y> <z> | position defaut",
|
||||
CHARACTERFRAME_PANES_MISSING = "Panes.lua is not loaded. A file added to the addon only arrives at the next game start: close and reopen the client. The character sheet stays inactive until then.",
|
||||
CHARACTERFRAME_SHOW_DETAILS = "Show details",
|
||||
CHARACTERFRAME_TAB_MACROS_FULL = "No free macro slot: delete a macro to put this tab on a bar.",
|
||||
CHARACTERFRAME_TITLES = "Titles",
|
||||
|
||||
-- Chat.lua
|
||||
@@ -388,6 +387,9 @@ ForeverUI.AddTexts("enUS", {
|
||||
STATUSBARS_EDIT_LABEL_EXPERIENCE = "Experience Bar",
|
||||
STATUSBARS_EDIT_LABEL_REPUTATION = "Reputation Bar",
|
||||
|
||||
-- TabMacros.lua
|
||||
TABMACROS_FULL = "No free macro slot: delete a macro to put this tab on a bar.",
|
||||
|
||||
-- TabardFrame.lua
|
||||
TABARDFRAME_POSITION_USAGE = "tabard: /fui tabard position <depth> <lateral> <height>",
|
||||
TABARDFRAME_STATE = "tabard: camera=%s scale=%s position=(%s, %s, %s)",
|
||||
|
||||
@@ -77,7 +77,6 @@ ForeverUI.AddTexts("esES", {
|
||||
CHARACTERFRAME_MODEL_USAGE = "modelo: echelle <n> | position <x> <y> <z> | position defaut",
|
||||
CHARACTERFRAME_PANES_MISSING = "Panes.lua no está cargado. Un archivo añadido al accesorio solo llega en el siguiente inicio del juego: cierra y vuelve a abrir el cliente. La ficha de personaje permanece inactiva hasta entonces.",
|
||||
CHARACTERFRAME_SHOW_DETAILS = "Mostrar detalles",
|
||||
CHARACTERFRAME_TAB_MACROS_FULL = "No queda espacio para macros: borra una para poner esta pestaña en una barra.",
|
||||
CHARACTERFRAME_TITLES = "Títulos",
|
||||
|
||||
-- Chat.lua
|
||||
@@ -388,6 +387,9 @@ ForeverUI.AddTexts("esES", {
|
||||
STATUSBARS_EDIT_LABEL_EXPERIENCE = "Barra de experiencia",
|
||||
STATUSBARS_EDIT_LABEL_REPUTATION = "Barra de reputación",
|
||||
|
||||
-- TabMacros.lua
|
||||
TABMACROS_FULL = "No queda espacio para macros: borra una para poner esta pestaña en una barra.",
|
||||
|
||||
-- TabardFrame.lua
|
||||
TABARDFRAME_POSITION_USAGE = "tabardo: /fui tabard position <profundidad> <lateral> <altura>",
|
||||
TABARDFRAME_STATE = "tabardo: cámara=%s escala=%s posición=(%s, %s, %s)",
|
||||
|
||||
@@ -77,7 +77,6 @@ ForeverUI.AddTexts("frFR", {
|
||||
CHARACTERFRAME_MODEL_USAGE = "modèle : echelle <n> | position <x> <y> <z> | position defaut",
|
||||
CHARACTERFRAME_PANES_MISSING = "Panes.lua n'est pas chargé. Un fichier ajouté à l'addon n'arrive qu'au prochain démarrage du jeu : fermez et rouvrez le client. La feuille de personnage reste inactive d'ici là.",
|
||||
CHARACTERFRAME_SHOW_DETAILS = "Afficher les détails",
|
||||
CHARACTERFRAME_TAB_MACROS_FULL = "Plus de place pour une macro : supprimez-en une pour poser cet onglet sur une barre.",
|
||||
CHARACTERFRAME_TITLES = "Titres",
|
||||
|
||||
-- Chat.lua
|
||||
@@ -388,6 +387,9 @@ ForeverUI.AddTexts("frFR", {
|
||||
STATUSBARS_EDIT_LABEL_EXPERIENCE = "Barre d'expérience",
|
||||
STATUSBARS_EDIT_LABEL_REPUTATION = "Barre de réputation",
|
||||
|
||||
-- TabMacros.lua
|
||||
TABMACROS_FULL = "Plus de place pour une macro : supprimez-en une pour poser cet onglet sur une barre.",
|
||||
|
||||
-- TabardFrame.lua
|
||||
TABARDFRAME_POSITION_USAGE = "tabard : /fui tabard position <profondeur> <latéral> <hauteur>",
|
||||
TABARDFRAME_STATE = "tabard : caméra=%s échelle=%s position=(%s, %s, %s)",
|
||||
|
||||
@@ -77,7 +77,6 @@ ForeverUI.AddTexts("ruRU", {
|
||||
CHARACTERFRAME_MODEL_USAGE = "модель: echelle <n> | position <x> <y> <z> | position defaut",
|
||||
CHARACTERFRAME_PANES_MISSING = "Panes.lua не загружен. Файл, добавленный в модификацию, появляется только при следующем запуске игры: закройте и снова откройте клиент. До тех пор окно персонажа будет неактивно.",
|
||||
CHARACTERFRAME_SHOW_DETAILS = "Показать подробности",
|
||||
CHARACTERFRAME_TAB_MACROS_FULL = "Нет места для нового макроса: удалите макрос, чтобы поместить эту вкладку на панель.",
|
||||
CHARACTERFRAME_TITLES = "Звания",
|
||||
|
||||
-- Chat.lua
|
||||
@@ -388,6 +387,9 @@ ForeverUI.AddTexts("ruRU", {
|
||||
STATUSBARS_EDIT_LABEL_EXPERIENCE = "Индикатор опыта",
|
||||
STATUSBARS_EDIT_LABEL_REPUTATION = "Индикатор репутации",
|
||||
|
||||
-- TabMacros.lua
|
||||
TABMACROS_FULL = "Нет места для нового макроса: удалите макрос, чтобы поместить эту вкладку на панель.",
|
||||
|
||||
-- TabardFrame.lua
|
||||
TABARDFRAME_POSITION_USAGE = "гербовая накидка: /fui tabard position <глубина> <смещение> <высота>",
|
||||
TABARDFRAME_STATE = "гербовая накидка: камера=%s масштаб=%s положение=(%s, %s, %s)",
|
||||
|
||||
Reference in New Issue
Block a user