5842eb7a2b
Traduction - Identifiants en anglais dans tout le module : addon, ecrans d'accueil, outils Python, banc d'essai et patcheur C#. - Fichiers au nom francais renommes (Gabarits.lua -> Templates.lua, Textes_*.lua -> Texts_*.lua, deployer.py -> deploy.py, tools/patcheur -> tools/patcher, etc.). - Commandes /fui et options de deploy.py en anglais (--check, --server, --remove-dbc). - Cles des variables sauvegardees et de data/dbc/statistics.json traduites, sans reprise des anciennes cles. - API de la micro-barre : ForeverUI.AddMicroButton(def) avec les champs name, atlasSet, after, tooltip, onClick, ready, et ForeverUI.UpdateMicro(name, isOpen). - Commentaires reecrits en anglais, courts, sans dates ni historique ; les fonctions au nom peu parlant et leurs parametres sont expliques. Code mort - Exports, fonctions et variables jamais lus retires. - Retires a la demande des modules : ForeverUI.PvPJauge, les exports FondEntete / TuilerEntete / Polices de TradeSkill, l'art legacy-up-c60, honorfill(half)blue et inv_misc_book_09, leurs entrees d'atlas et les parties d'outils correspondantes. Verifications : liaisons des noms comparees avant et apres, banc vert, chemins de textures inchanges, generateurs reproduisant les fichiers, patcheur identique octet pour octet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
329 lines
12 KiB
Lua
329 lines
12 KiB
Lua
-- Merchant window (MerchantFrame) in camelot style.
|
|
-- The client's frames and logic stay, placed and dressed as in camelot's merchantframe.xml /
|
|
-- .lua (ButtonFrameTemplate 336 x 444); N holds its offsets. What the client re-places on
|
|
-- every update (repair buttons, portrait, title, buyback background) is redone after it.
|
|
-- Item names take their quality color and icons a quality outline
|
|
-- (MerchantFrameItem_UpdateQuality).
|
|
-- Tabs are the Social window's (PanelTabButtonTemplate); they drive the client's tabs, which
|
|
-- are hidden. Portrait: the character sheet's, 48 wide, centered in the ring hole (a 60
|
|
-- unit portrait overflows the circle).
|
|
-- Missing in 3.3.5, so absent: filter by specialization (SetMerchantFilter) and sell all
|
|
-- junk (C_MerchantFrame.SellAllJunkItems).
|
|
|
|
local ForeverUI = ForeverUI or {}
|
|
_G.ForeverUI = ForeverUI
|
|
|
|
local Tpl = ForeverUI.Templates
|
|
|
|
local M = {}
|
|
ForeverUI.Merchant = M
|
|
|
|
local SEP = string.char(92)
|
|
|
|
local N = {
|
|
window = { 336, 444 },
|
|
portrait = { side = 48, x = 1, y = 1.5 },
|
|
inset = { 4, -60, -6, 26 },
|
|
buybackBackground = { 7, -60, -7, 26, a = 0.2 },
|
|
bottomFrame = { l = 334, h = 61, x = 1, y = 26 },
|
|
first = { 11, -69 },
|
|
page = { x = 0, y = 86, l = 104 },
|
|
previous = { 25, 96 }, following = { 310, 96 },
|
|
repair = { side = 36, background = { 64, -13, 14 }, single = { x = 118, y = 33, gap = -8 },
|
|
guild = { x = 96, y = 33, gap = -9, right = 8 } },
|
|
buyback = { l = 115, h = 37, x = 30, y = -53, nameFrame = { 90, 64 }, name = { 70, 35, -5, 2 },
|
|
arrow = { side = 20, x = 0, y = -1 }, count = 0.65 },
|
|
money = { inset = { -171, 27, -5, 4 }, edge = { -166, 6, -7, 25 }, purse = { -4, 8 } },
|
|
tab = { x = 50, y = -15, gap = 3 },
|
|
}
|
|
|
|
local ART = {
|
|
backgroundBottom = "ui-merchant-botframe",
|
|
repairAll = "spellicon-256x256-repairall",
|
|
repair = "spellicon-256x256-repair",
|
|
guild = "spellicon-256x256-repairallguild",
|
|
cancel = "common-icon-undo",
|
|
cell = "Interface" .. SEP .. "Buttons" .. SEP .. "UI-EmptySlot",
|
|
money = "Interface" .. SEP .. "ForeverUI" .. SEP .. "common" .. SEP .. "moneyframe",
|
|
marble = "interface" .. SEP .. "ForeverUI" .. SEP .. "framegeneral" .. SEP .. "ui-background-marble",
|
|
buyback = "Interface" .. SEP .. "MerchantFrame" .. SEP .. "UI-BuyBack-Icon",
|
|
}
|
|
|
|
local function place(r, ...)
|
|
r:ClearAllPoints()
|
|
r:SetPoint(...)
|
|
end
|
|
|
|
-- InsetFrameTemplate: marble and trim as regions of the window, fitted to a helper frame
|
|
-- (camelot's insets are at the window's level). x1, y1: top left offset from f's point p1;
|
|
-- x2, y2: bottom right offset from p2. Returns the helper frame, marble and trim.
|
|
local function inset(f, x1, y1, p1, x2, y2, p2)
|
|
local rect = CreateFrame("Frame", nil, f)
|
|
rect:EnableMouse(false)
|
|
rect:SetPoint("TOPLEFT", f, p1, x1, y1)
|
|
rect:SetPoint("BOTTOMRIGHT", f, p2, x2, y2)
|
|
local marble = f:CreateTexture(nil, "BACKGROUND")
|
|
marble:SetTexture(ART.marble, true)
|
|
if marble.SetHorizTile then marble:SetHorizTile(true) marble:SetVertTile(true) end
|
|
marble:SetAllPoints(rect)
|
|
return rect, marble, Tpl.NineSlice(f, "InsetFrameTemplate", rect)
|
|
end
|
|
|
|
-- ThinGoldEdgeTemplate: Interface\Common\Moneyframe in three pieces
|
|
local function goldBorder(f, rect)
|
|
local function piece(u1, u2, v1, v2)
|
|
local t = f:CreateTexture(nil, "ARTWORK")
|
|
t:SetTexture(ART.money)
|
|
t:SetTexCoord(u1, u2, v1, v2)
|
|
return t
|
|
end
|
|
local g = piece(0.953125, 0.9921875, 0, 0.296875)
|
|
g:SetWidth(7)
|
|
g:SetPoint("TOPLEFT", rect, "TOPLEFT")
|
|
g:SetPoint("BOTTOMLEFT", rect, "BOTTOMLEFT")
|
|
local d = piece(0, 0.0546875, 0, 0.296875)
|
|
d:SetWidth(7)
|
|
d:SetPoint("TOPRIGHT", rect, "TOPRIGHT")
|
|
d:SetPoint("BOTTOMRIGHT", rect, "BOTTOMRIGHT")
|
|
local m = piece(0, 0.9921875, 0.3125, 0.609375)
|
|
m:SetPoint("TOPLEFT", g, "TOPRIGHT")
|
|
m:SetPoint("BOTTOMRIGHT", d, "BOTTOMLEFT")
|
|
return { g, m, d }
|
|
end
|
|
|
|
-- Quality color on the name and outline on the icon (Tpl.Quality)
|
|
local function quality(name, button, link)
|
|
Tpl.Quality(name, button, link)
|
|
end
|
|
|
|
local outline = Tpl.Outline
|
|
|
|
-- Repair buttons, re-placed after MerchantFrame_UpdateRepairButtons (which puts them at
|
|
-- their 3.3.5 places and shrinks them to 32 when the guild button shows).
|
|
function M.PlaceRepair()
|
|
local R = N.repair
|
|
local f = MerchantFrame
|
|
for _, b in ipairs({ MerchantRepairAllButton, MerchantRepairItemButton, MerchantGuildBankRepairButton }) do
|
|
b:SetWidth(R.side)
|
|
b:SetHeight(R.side)
|
|
end
|
|
local guild = MerchantGuildBankRepairButton:IsShown()
|
|
local P = guild and R.guild or R.single
|
|
place(MerchantRepairAllButton, "BOTTOMRIGHT", f, "BOTTOMLEFT", P.x, P.y)
|
|
place(MerchantRepairItemButton, "RIGHT", MerchantRepairAllButton, "LEFT", P.gap, 0)
|
|
place(MerchantGuildBankRepairButton, "LEFT", MerchantRepairAllButton, "RIGHT", R.guild.right, 0)
|
|
end
|
|
|
|
-- Buyback arrow: greyed out when there is nothing to buy back
|
|
local function updateArrow()
|
|
local t = M.arrow
|
|
if t then t:SetDesaturated(GetNumBuybackItems() == 0) end
|
|
end
|
|
|
|
-- After the client: merchant tab
|
|
function M.AfterMerchant()
|
|
local h = MerchantFrame.foreverSkin
|
|
if not h then return end
|
|
SetPortraitTexture(h.portrait, "npc")
|
|
M.buybackBackground:Hide()
|
|
local number = MerchantFrame.page or 1
|
|
for i = 1, MERCHANT_ITEMS_PER_PAGE do
|
|
local index = (number - 1) * MERCHANT_ITEMS_PER_PAGE + i
|
|
local b = _G["MerchantItem" .. i .. "ItemButton"]
|
|
if index <= GetMerchantNumItems() then
|
|
quality(_G["MerchantItem" .. i .. "Name"], b, GetMerchantItemLink(index))
|
|
else
|
|
outline(b):Hide()
|
|
end
|
|
end
|
|
local n = GetNumBuybackItems()
|
|
quality(MerchantBuyBackItemName, MerchantBuyBackItemItemButton, n > 0 and GetBuybackItemLink(n) or nil)
|
|
updateArrow()
|
|
end
|
|
|
|
-- After the client: buyback tab
|
|
function M.AfterBuyback()
|
|
local h = MerchantFrame.foreverSkin
|
|
if not h then return end
|
|
h.portrait:SetTexture(ART.buyback)
|
|
M.buybackBackground:Show()
|
|
local n = GetNumBuybackItems()
|
|
for i = 1, BUYBACK_ITEMS_PER_PAGE do
|
|
local b = _G["MerchantItem" .. i .. "ItemButton"]
|
|
if i <= n then
|
|
quality(_G["MerchantItem" .. i .. "Name"], b, GetBuybackItemLink(i))
|
|
else
|
|
outline(b):Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Bottom tabs follow the client's selected tab
|
|
function M.UpdateTabs()
|
|
local S = ForeverUI.Social
|
|
for i, o in ipairs(M.tabs or {}) do
|
|
S.selectTab(o, MerchantFrame.selectedTab == i, true)
|
|
o:SetWidth(S.tabWidth(o))
|
|
end
|
|
end
|
|
|
|
local function tabs(f)
|
|
local S = ForeverUI.Social
|
|
local O = N.tab
|
|
M.tabs = {}
|
|
for i, text in ipairs({ MERCHANT, BUYBACK }) do
|
|
local o = S.createTab(f, "ForeverUIMerchantTab" .. i, false)
|
|
o:SetText(text)
|
|
if i == 1 then
|
|
o:SetPoint("CENTER", f, "BOTTOMLEFT", O.x, O.y)
|
|
else
|
|
o:SetPoint("TOPLEFT", M.tabs[i - 1], "TOPRIGHT", O.gap, 0)
|
|
end
|
|
-- what the client's tab does (MerchantFrameTab<i>, OnClick)
|
|
o:SetScript("OnClick", function()
|
|
PlaySound("igCharacterInfoTab")
|
|
PanelTemplates_SetTab(MerchantFrame, i)
|
|
MerchantFrame_Update()
|
|
end)
|
|
M.tabs[i] = o
|
|
ForeverUI.Suppress(_G["MerchantFrameTab" .. i])
|
|
end
|
|
M.UpdateTabs()
|
|
end
|
|
|
|
-- A camelot repair icon on its slot background. icon: the button's icon texture
|
|
local function repair(b, icon, atlas)
|
|
local F = N.repair.background
|
|
local background = b:CreateTexture(nil, "BACKGROUND")
|
|
background:SetTexture(ART.cell)
|
|
background:SetWidth(F[1])
|
|
background:SetHeight(F[1])
|
|
background:SetPoint("TOPLEFT", b, "TOPLEFT", F[2], F[3])
|
|
ForeverUI.SetAtlas(icon, atlas)
|
|
icon:ClearAllPoints()
|
|
icon:SetAllPoints(b)
|
|
b.foreverBackground = background
|
|
end
|
|
|
|
-- MerchantRepairItemButton's icon has no name: find it among the button's BORDER regions
|
|
local function unnamedIcon(b)
|
|
for _, r in ipairs({ b:GetRegions() }) do
|
|
if r:GetObjectType() == "Texture" and r ~= b:GetNormalTexture() and r ~= b:GetPushedTexture()
|
|
and r ~= b:GetHighlightTexture() and r:GetDrawLayer() == "BORDER" then
|
|
return r
|
|
end
|
|
end
|
|
end
|
|
|
|
local function buyback()
|
|
local R = N.buyback
|
|
local it = MerchantBuyBackItem
|
|
it:SetWidth(R.l)
|
|
it:SetHeight(R.h)
|
|
place(it, "TOPLEFT", MerchantItem10, "BOTTOMLEFT", R.x, R.y)
|
|
MerchantBuyBackItemNameFrame:SetWidth(R.nameFrame[1])
|
|
MerchantBuyBackItemNameFrame:SetHeight(R.nameFrame[2])
|
|
MerchantBuyBackItemNameFrame:Hide()
|
|
MerchantBuyBackItemName:SetWidth(R.name[1])
|
|
MerchantBuyBackItemName:SetHeight(R.name[2])
|
|
place(MerchantBuyBackItemName, "LEFT", MerchantBuyBackItemSlotTexture, "RIGHT", R.name[3], R.name[4])
|
|
-- SetItemButtonScale(0.65) on the count only: 3.3.5 cannot scale a text, so its font size
|
|
-- is scaled instead
|
|
local count = MerchantBuyBackItemItemButtonCount
|
|
local path, size, flags = count:GetFont()
|
|
if path and size then count:SetFont(path, size * R.count, flags) end
|
|
-- arrow, above the icon
|
|
local veil = CreateFrame("Frame", nil, MerchantBuyBackItemItemButton)
|
|
veil:SetAllPoints(MerchantBuyBackItemItemButton)
|
|
veil:EnableMouse(false)
|
|
local t = veil:CreateTexture(nil, "ARTWORK")
|
|
ForeverUI.SetAtlas(t, ART.cancel)
|
|
t:SetWidth(R.arrow.side)
|
|
t:SetHeight(R.arrow.side)
|
|
t:SetPoint("CENTER", veil, "CENTER", R.arrow.x, R.arrow.y)
|
|
M.arrow = t
|
|
MerchantBuyBackItemItemButton:HookScript("OnShow", updateArrow)
|
|
end
|
|
|
|
function M.Skin()
|
|
local f = MerchantFrame
|
|
if not f or f.foreverSkin then return end
|
|
|
|
-- 3.3.5 art: the four unnamed pieces, portrait, name, repair text, buyback background,
|
|
-- bottom right border
|
|
for _, r in ipairs({ f:GetRegions() }) do
|
|
if r:GetObjectType() == "Texture" and not r:GetName() then
|
|
r:SetAlpha(0)
|
|
end
|
|
end
|
|
for _, r in ipairs({ MerchantFramePortrait, MerchantNameText, MerchantRepairText, BuybackFrameTopLeft,
|
|
BuybackFrameTopRight, BuybackFrameBotLeft, BuybackFrameBotRight, MerchantFrameBottomRightBorder }) do
|
|
r:SetAlpha(0)
|
|
end
|
|
f:SetWidth(N.window[1])
|
|
f:SetHeight(N.window[2])
|
|
f:SetHitRectInsets(0, 0, 0, 0)
|
|
|
|
-- ButtonFrameTemplate: stone, streaks, metal, portrait, title
|
|
local skin = Tpl.PortraitWindow(f, {
|
|
portraitSide = N.portrait.side, portraitX = N.portrait.x, portraitY = N.portrait.y,
|
|
title = MerchantNameText:GetText(),
|
|
})
|
|
f.foreverSkin = skin
|
|
hooksecurefunc(MerchantNameText, "SetText", function(_, text)
|
|
skin.title:SetText(text or "")
|
|
end)
|
|
-- inset, then the buyback background (white at 0.2) over it
|
|
local E = N.inset
|
|
skin.inset, skin.marble, skin.frameBox = inset(f, E[1], E[2], "TOPLEFT", E[3], E[4], "BOTTOMRIGHT")
|
|
local RF = N.buybackBackground
|
|
local background = f:CreateTexture(nil, "BACKGROUND")
|
|
background:SetTexture(1, 1, 1, RF.a)
|
|
background:SetPoint("TOPLEFT", f, "TOPLEFT", RF[1], RF[2])
|
|
background:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", RF[3], RF[4])
|
|
background:Hide()
|
|
M.buybackBackground = background
|
|
-- bottom background: the client's own texture, which the client shows and hides
|
|
local B = N.bottomFrame
|
|
local down = MerchantFrameBottomLeftBorder
|
|
ForeverUI.SetAtlas(down, ART.backgroundBottom)
|
|
down:SetWidth(B.l)
|
|
down:SetHeight(B.h)
|
|
place(down, "BOTTOMLEFT", f, "BOTTOMLEFT", B.x, B.y)
|
|
-- money: its inset, gold edge and purse
|
|
local A = N.money
|
|
skin.moneyInset = inset(f, A.inset[1], A.inset[2], "BOTTOMRIGHT", A.inset[3], A.inset[4], "BOTTOMRIGHT")
|
|
local edge = CreateFrame("Frame", nil, f)
|
|
edge:EnableMouse(false)
|
|
edge:SetPoint("BOTTOMLEFT", f, "BOTTOMRIGHT", A.edge[1], A.edge[2])
|
|
edge:SetPoint("TOPRIGHT", f, "BOTTOMRIGHT", A.edge[3], A.edge[4])
|
|
skin.moneyBorder = edge
|
|
skin.goldBorder = goldBorder(f, edge)
|
|
place(MerchantMoneyFrame, "BOTTOMRIGHT", f, "BOTTOMRIGHT", A.purse[1], A.purse[2])
|
|
-- close button, above the metal
|
|
Tpl.CloseButton(MerchantFrameCloseButton, f)
|
|
MerchantFrameCloseButton:SetFrameLevel(f:GetFrameLevel() + 22)
|
|
|
|
-- items and pages
|
|
place(MerchantItem1, "TOPLEFT", f, "TOPLEFT", N.first[1], N.first[2])
|
|
MerchantPageText:SetWidth(N.page.l)
|
|
place(MerchantPageText, "BOTTOM", f, "BOTTOM", N.page.x, N.page.y)
|
|
place(MerchantPrevPageButton, "CENTER", f, "BOTTOMLEFT", N.previous[1], N.previous[2])
|
|
place(MerchantNextPageButton, "CENTER", f, "BOTTOMLEFT", N.following[1], N.following[2])
|
|
|
|
-- repair buttons
|
|
repair(MerchantRepairAllButton, MerchantRepairAllIcon, ART.repairAll)
|
|
repair(MerchantRepairItemButton, unnamedIcon(MerchantRepairItemButton), ART.repair)
|
|
repair(MerchantGuildBankRepairButton, MerchantGuildBankRepairButtonIcon, ART.guild)
|
|
hooksecurefunc("MerchantFrame_UpdateRepairButtons", M.PlaceRepair)
|
|
M.PlaceRepair()
|
|
|
|
buyback()
|
|
tabs(f)
|
|
hooksecurefunc("MerchantFrame_UpdateMerchantInfo", M.AfterMerchant)
|
|
hooksecurefunc("MerchantFrame_UpdateBuybackInfo", M.AfterBuyback)
|
|
hooksecurefunc("MerchantFrame_Update", M.UpdateTabs)
|
|
end
|
|
|
|
M.Skin()
|