Files
moon-well-ui/data/addon/ForeverUI/Trainer.lua
T
Adrestie b1da47c3eb PNJ etapes 3-4 : maitre, vol, etable, sertissage, dialogues, metiers
Etape 3
- Maitre (Trainer.lua, nouveau) : liste de camelot (categories
  professions-recipe-header, lignes TrainerTextures), filtre, rang de
  metier lu dans les competences.
- Maitre de vol (Taxi.lua, nouveau) : TaxiFrame de camelot 590 x 608,
  cadre bronze, images de vol 1463 / 1464 (positions reportees du carre
  3.3.5), boutons et traits de camelot ; zones BC, Outreterre et Norfendre
  sur l'image de 3.3.5.
- Etable (Stable.lua, nouveau) : scene de camelot, fond selon la
  specialisation, rangee de 5 centree.
- Sertissage (Socketing.lua, nouveau) : decor et chasses de camelot.
- Boites de dialogue (Dialogues.lua, nouveau) : StaticPopup1-4 aux
  contours de camelot (fond sombre, bordure en losanges, croix).
- Gabarits : Gb.CadreSimple (repris de la banque de guilde), Gb.MenuFiltre.

Etape 4 (metiers, disposition de camelot)
- Fabrication (TradeSkill.lua, nouveau) : 673 x 594, liste en arbre,
  filtre, recherche, rang, fiche (carte du metier, resultat, reactifs),
  boutons ; noms mesures sur un texte a part (une ligne reutilisee coupait
  le nom suivant) ; eclat du rang rogne a la largeur du masque.
- Micro-bouton Professions (BottomBar.lua) apres la feuille de personnage.
- Livre des metiers (ProfessionsBook.lua, nouveau) : cartes de camelot,
  rangs, sorts securises, oubli ; plus de deux metiers principaux (zone a
  defilement, colonnes reduites) ; portrait cuit rond ; onglets lateraux
  (ensemble + metiers a fabrication, retrecis s'ils sont trop nombreux) ;
  fenetre deplacable (place commune livre / fabrication).
- DropDown : liste du filtre des metiers elargie a ses entrees.
- Art : feuilles et elements des metiers, icones d'onglets cuites
  (cuire_masque.py), portrait rond (cuire_portrait.py, nouveau).
- Banc : essais des etapes 3 et 4 ; micro-menu a neuf boutons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:02:35 +02:00

595 lines
23 KiB
Lua

-- ForeverUI : la fenetre du maitre (ClassTrainerFrame, Blizzard_TrainerUI
-- charge a la demande), a la DA de camelot (chantier des PNJ, etape 3,
-- demande de l'utilisateur du 2026-09-28).
--
-- RELEVE -- CAMELOT (blizzard_trainerui/mainline/blizzard_trainerui.xml et
-- .lua ; blizzard_trainerui_camelot.lua : TrainerUI_UseCategories = true) :
-- cadre ButtonFrameTemplate 338 x 424, portrait du PNJ, titre =
-- son nom ; encart (4, -60 / -6, 26) ; croix (-2, 1)
-- rang ClassTrainerStatusBar 130 x 18 a (64, -35) (maitre de
-- metier) : fond (0, 0, .75, .5), barre UI-Character-
-- Skills-Bar (0, 0, 1, .5), bords GuildFrame (gauche et
-- droite 18 a (-2, 0) / (2, 0), milieu entre eux), texte
-- GameFontHighlightSmall au centre
-- filtre WowStyle1FilterDropdownTemplate TOPRIGHT (-13, -35), 18
-- de haut (Gb.MenuFiltre)
-- liste ScrollBox 302 x 330 a (5, -5) de l'encart (Update) ; vue
-- en arbre : retrait 10, marges haut 1, bas 1, droite 1 ;
-- fond TrainerTextures (u .00195-.58594, v .00195-.65430)
-- de (-3, 4) a (3, -4) de la liste ; barre MinimalScrollBar
-- (5, -2 / 5, -2)
-- categorie TrainerUICategoryTemplate, 25 : Professions-recipe-
-- header-left / -right a leur taille (LEFT / RIGHT, y 2),
-- -middle entre eux ; nom GameFontNormal_NoShadow LEFT
-- (10, 2) sur 10 (Highlight au survol) ; -expand (repliee)
-- / -collapse a RIGHT (-10, 2), le meme en ADD au survol
-- competence ClassTrainerSkillButtonTemplate, 47 : plaque, survol
-- (ADD) et choix (ADD) TrainerTextures ; icone 36 a LEFT
-- (6, 0), desaturee indisponible ; nom GameFontNormal sur 12
-- a (6, -1) de l'icone ; rang (PARENS_TEMPLATE)
-- GameFontNormalSmall a (5, -1) du nom ; prerequis
-- SystemFont_Shadow_Small 240 x 30 a (0, -19) du nom
-- (REQUIRES_LABEL, TRAINER_REQ_*, ITEM_SPELL_KNOWN si
-- connue) ; prix SmallMoneyFrame TOPRIGHT (5, -7), rouge
-- si trop cher, cache si connue ; voile gris (.55) en MOD a
-- 2 du bord si indisponible ; infobulle SetTrainerService a
-- ANCHOR_RIGHT (35)
-- bas Former (TRAIN) 80 x 22 BOTTOMRIGHT (-6, 4) ; l'argent
-- UI-MoneyFrame-Border 148 x 34 a BOTTOMLEFT (5, -9), la
-- bourse a sa droite (8, 6)
--
-- RELEVE -- 3.3.5 (Blizzard_TrainerUI.xml / .lua) : 384 x 512 ; liste PLATE
-- de 11 lignes de 16 (les en-tetes dans l'index, GetTrainerServiceInfo :
-- nom, rang, type header / available / unavailable / used, deplie) ;
-- panneau de details sous la liste ; Tout replier ; Quitter ; texte
-- d'accueil ; ClassTrainerFrame_Update, ClassTrainer_SetSelection.
--
-- CE QUI DIFFERE, ET POURQUOI.
-- * La liste est a nous (lignes de camelot) ; le client en garde la
-- logique : un clic fait ce que fait sa ligne (ClassTrainerSkillButton_
-- OnClick), un en-tete se replie par Expand / CollapseTrainerSkillLine.
-- Ses lignes, sa liste et son panneau de details restent en place,
-- invisibles et sans souris (le panneau pilote le bouton Former).
-- * Pas de panneau de details ni de texte d'accueil, ni Tout replier ni
-- Quitter : camelot n'en a pas (la description est dans l'infobulle).
-- Un clic modifie sur une ligne fait ce que faisait l'icone du panneau
-- de 3.3.5 (HandleModifiedItemClick).
-- * La liste avance d'une ligne a la fois (3.3.5 ne rogne que dans une
-- ScrollFrame) ; la barre suit la regle de l'atelier : cachee si tout
-- tient, et sans elle la liste et son fond gardent a droite la marge
-- qu'ils ont a gauche (318 de large).
-- * Le rang : GetTrainerTradeskillRankValues n'existe pas en 3.3.5 ; il
-- est lu dans les competences du joueur (GetSkillLineInfo) par le nom
-- du metier du maitre (GetTrainerServiceSkillLine).
-- * Les polices sans ombre de camelot n'existent pas en 3.3.5 : creees.
local ForeverUI = ForeverUI or {}
_G.ForeverUI = ForeverUI
local Gb = ForeverUI.Gabarits
local L = ForeverUI.L
local T = {}
ForeverUI.Maitre = T
local SEP = string.char(92)
local TEXTURES = "Interface" .. SEP .. "ForeverUI" .. SEP .. "classtrainerframe" .. SEP .. "trainertextures"
local N = {
fenetre = { 338, 424 },
portrait = { cote = 48, x = 1, y = 1.5 },
encart = { 4, -60, -6, 26 },
rang = { 64, -35, 130, 18, bord = 18 },
filtre = { -13, -35, 18 },
liste = { 5, -5, 302, 330, sansBarre = 318, haut = 1, bas = 1, droite = 1, retrait = 10 },
fondListe = { -3, 4, 3, -4 },
barre = { 5, -2 },
categorie = { h = 25, nom = { 10, 2, 10 }, fleche = { -10, 2 }, bout = 2 },
competence = { h = 47, icone = { 36, 6 }, nom = { 6, -1, 12 }, rang = { 5, -1, 12 },
prerequis = { 0, -19, 240, 30 }, prix = { 5, -7 }, voile = 2, gris = 0.55, bulle = 35 },
former = { 80, 22, -6, 4 },
argent = { 148, 34, 5, -9, bourse = { 8, 6 } },
}
local COORDS = {
fond = { 0.00195313, 0.5859375, 0.00195313, 0.65429688 },
plaque = { 0.00195313, 0.57421875, 0.65820313, 0.75 },
survol = { 0.00195313, 0.57421875, 0.75390625, 0.84570313 },
choix = { 0.00195313, 0.57421875, 0.84960938, 0.94140625 },
rangG = { 0.60742188, 0.625, 0.78710938, 0.82226563 },
rangD = { 0.60742188, 0.625, 0.82617188, 0.86132813 },
rangM = { 0.60742188, 0.625, 0.74804688, 0.78320313 },
}
local ART = {
marbre = "interface" .. SEP .. "ForeverUI" .. SEP .. "framegeneral" .. SEP .. "ui-background-marble",
guilde = "Interface" .. SEP .. "ForeverUI" .. SEP .. "guildframe" .. SEP .. "guildframe",
barre = "Interface" .. SEP .. "PaperDollInfoFrame" .. SEP .. "UI-Character-Skills-Bar",
argent = "Interface" .. SEP .. "ForeverUI" .. SEP .. "moneyframe" .. SEP .. "ui-moneyframe-border",
}
-- GameFontNormal_NoShadow et GameFontHighlight_NoShadow de camelot
local function sansOmbre(nom, modele)
local p = CreateFont(nom)
p:SetFontObject(modele)
p:SetShadowOffset(0, 0)
p:SetShadowColor(0, 0, 0, 0)
return p
end
local POLICES = {
categorie = sansOmbre("ForeverUIFontNormalNoShadow", GameFontNormal),
categorieSurvol = sansOmbre("ForeverUIFontHighlightNoShadow", GameFontHighlight),
}
local function poser(r, ...)
r:ClearAllPoints()
r:SetPoint(...)
end
local function morceau(hote, couche, fichier, c)
local t = hote:CreateTexture(nil, couche)
t:SetTexture(fichier)
t:SetTexCoord(c[1], c[2], c[3], c[4])
return t
end
-- ------------------------------------------------------------ les lignes
local function creerCategorie(liste, n)
local C = N.categorie
local b = CreateFrame("Button", "ForeverUITrainerCategory" .. n, liste)
b:SetHeight(C.h)
local g = b:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(g, "professions-recipe-header-left")
g:SetPoint("LEFT", b, "LEFT", 0, C.bout)
local d = b:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(d, "professions-recipe-header-right")
d:SetPoint("RIGHT", b, "RIGHT", 0, C.bout)
local m = b:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(m, "professions-recipe-header-middle", true)
m:SetPoint("TOPLEFT", g, "TOPRIGHT", 0, 0)
m:SetPoint("BOTTOMRIGHT", d, "BOTTOMLEFT", 0, 0)
local nom = b:CreateFontString(nil, "OVERLAY")
nom:SetFontObject(POLICES.categorie)
nom:SetJustifyH("LEFT")
nom:SetHeight(C.nom[3])
nom:SetPoint("LEFT", b, "LEFT", C.nom[1], C.nom[2])
local fleche = b:CreateTexture(nil, "ARTWORK")
fleche:SetPoint("RIGHT", b, "RIGHT", C.fleche[1], C.fleche[2])
local lueur = b:CreateTexture(nil, "HIGHLIGHT")
lueur:SetBlendMode("ADD")
lueur:SetPoint("CENTER", fleche, "CENTER", 0, 0)
b.nom, b.fleche, b.lueur = nom, fleche, lueur
b:SetScript("OnEnter", function(self) self.nom:SetFontObject(POLICES.categorieSurvol) end)
b:SetScript("OnLeave", function(self) self.nom:SetFontObject(POLICES.categorie) end)
b:SetScript("OnClick", function(self)
if self.deplie then
CollapseTrainerSkillLine(self:GetID())
else
ExpandTrainerSkillLine(self:GetID())
end
end)
return b
end
local function creerCompetence(liste, n)
local C = N.competence
local nom = "ForeverUITrainerSkill" .. n
local b = CreateFrame("Button", nom, liste)
b:SetHeight(C.h)
b:RegisterForClicks("LeftButtonUp")
b:SetNormalTexture(TEXTURES)
local plaque = b:GetNormalTexture()
plaque:SetTexCoord(COORDS.plaque[1], COORDS.plaque[2], COORDS.plaque[3], COORDS.plaque[4])
plaque:ClearAllPoints()
plaque:SetAllPoints(b)
b:SetHighlightTexture(TEXTURES)
local h = b:GetHighlightTexture()
h:SetTexCoord(COORDS.survol[1], COORDS.survol[2], COORDS.survol[3], COORDS.survol[4])
h:ClearAllPoints()
h:SetAllPoints(b)
h:SetBlendMode("ADD")
local voile = b:CreateTexture(nil, "BACKGROUND")
voile:SetTexture(C.gris, C.gris, C.gris, 1)
voile:SetBlendMode("MOD")
voile:SetPoint("TOPLEFT", b, "TOPLEFT", C.voile, -C.voile)
voile:SetPoint("BOTTOMRIGHT", b, "BOTTOMRIGHT", -C.voile, C.voile)
voile:Hide()
local choix = morceau(b, "OVERLAY", TEXTURES, COORDS.choix)
choix:SetBlendMode("ADD")
choix:SetAllPoints(b)
choix:Hide()
local icone = b:CreateTexture(nil, "OVERLAY")
icone:SetWidth(C.icone[1])
icone:SetHeight(C.icone[1])
icone:SetPoint("LEFT", b, "LEFT", C.icone[2], 0)
local titre = b:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titre:SetJustifyH("LEFT")
titre:SetHeight(C.nom[3])
titre:SetPoint("TOPLEFT", icone, "TOPRIGHT", C.nom[1], C.nom[2])
local prerequis = b:CreateFontString(nil, "OVERLAY")
prerequis:SetFontObject(_G.SystemFont_Shadow_Small or GameFontHighlightSmall)
prerequis:SetJustifyH("LEFT")
prerequis:SetJustifyV("MIDDLE")
prerequis:SetWidth(C.prerequis[3])
prerequis:SetHeight(C.prerequis[4])
prerequis:SetPoint("LEFT", titre, "LEFT", C.prerequis[1], C.prerequis[2])
local rang = b:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
rang:SetJustifyH("LEFT")
rang:SetHeight(C.rang[3])
rang:SetPoint("BOTTOMLEFT", titre, "BOTTOMRIGHT", C.rang[1], C.rang[2])
local prix = CreateFrame("Frame", nom .. "Money", b, "SmallMoneyFrameTemplate")
prix:SetPoint("TOPRIGHT", b, "TOPRIGHT", C.prix[1], C.prix[2])
if MoneyFrame_SetType then MoneyFrame_SetType(prix, "STATIC") end
b.voile, b.choix, b.icone, b.titre, b.prerequis, b.rang, b.prix = voile, choix, icone, titre, prerequis, rang, prix
b:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT", C.bulle)
GameTooltip:SetTrainerService(self:GetID())
GameTooltip:Show()
end)
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
b:SetScript("OnClick", function(self, bouton)
if IsModifiedClick() then
HandleModifiedItemClick(GetTrainerServiceItemLink(self:GetID()))
return
end
ClassTrainerSkillButton_OnClick(self, bouton)
end)
return b
end
-- les prerequis d'une competence (ClassTrainerFrame_InitServiceButton de
-- camelot, avec les fonctions de 3.3.5)
local function prerequis(i, genre)
local texte, sep = "", ""
local niveau = GetTrainerServiceLevelReq(i)
if niveau and niveau > 1 then
if UnitLevel("player") >= niveau then
texte = texte .. format(TRAINER_REQ_LEVEL, niveau)
else
texte = texte .. format(TRAINER_REQ_LEVEL_RED, niveau)
end
sep = PLAYER_LIST_DELIMITER
end
local competence, rangReq, aRang = GetTrainerServiceSkillReq(i)
if competence then
texte = texte .. sep .. format(aRang and TRAINER_REQ_SKILL_RANK or TRAINER_REQ_SKILL_RANK_RED, competence, rangReq)
sep = PLAYER_LIST_DELIMITER
end
for j = 1, GetTrainerServiceNumAbilityReq(i) or 0 do
local sort, aSort = GetTrainerServiceAbilityReq(i, j)
if sort then
texte = texte .. sep .. format(aSort and TRAINER_REQ_ABILITY or TRAINER_REQ_ABILITY_RED, sort)
sep = PLAYER_LIST_DELIMITER
end
end
if genre == "used" then
return ITEM_SPELL_KNOWN, false
elseif texte ~= "" then
return REQUIRES_LABEL .. " " .. texte, true
end
return "", true
end
local function remplirCompetence(b, i, argent)
local nom, sousNom, genre = GetTrainerServiceInfo(i)
b:SetID(i)
b.icone:SetTexture(GetTrainerServiceIcon(i))
local texte, montrerPrix = prerequis(i, genre)
local indisponible = genre == "unavailable"
b.icone:SetDesaturated(indisponible)
Gb.Montrer(b.voile, indisponible)
b.titre:SetText(nom or UNKNOWN)
b.prerequis:SetText(texte)
b.rang:SetText((sousNom and sousNom ~= "") and format(PARENS_TEMPLATE, sousNom) or "")
local cout = GetTrainerServiceCost(i)
if montrerPrix and cout and cout > 0 then
MoneyFrame_Update(b.prix:GetName(), cout)
SetMoneyFrameColor(b.prix:GetName(), argent >= cout and "white" or "red")
b.prix:Show()
else
b.prix:Hide()
end
Gb.Montrer(b.choix, ClassTrainerFrame.selectedService == i)
end
-- combien de lignes tiennent depuis la i-eme (les hauteurs different)
local function hauteurDe(i)
local _, _, genre = GetTrainerServiceInfo(i)
return genre == "header" and N.categorie.h or N.competence.h
end
local function tiennent(depuis, total, place)
local y, n = N.liste.haut, 0
for i = depuis, total do
local h = hauteurDe(i)
if y + h > place then break end
y = y + h
n = n + 1
end
return n
end
-- la liste (et son fond) selon la barre : sa place de camelot, ou sans
-- barre la meme marge a droite qu'a gauche
local function poserListe(avec)
local h = ClassTrainerFrame.foreverHabit
local Li = N.liste
h.liste:SetWidth(avec and Li[3] or Li.sansBarre)
end
-- APRES ClassTrainerFrame_Update : la liste de camelot, sur les donnees du
-- client ; portrait, titre, rang
function T.Maj()
local f = ClassTrainerFrame
local h = f and f.foreverHabit
if not h then return end
SetPortraitTexture(h.portrait, "npc")
T.MajRang()
local total = GetNumTrainerServices() or 0
local place = N.liste[4] - N.liste.bas
-- le plus grand decalage : celui d'ou la fin tient
local maxi = 0
for d = 0, total do
if tiennent(d + 1, total, place) >= total - d then
maxi = d
break
end
end
h.maxi = maxi
-- la selection en vue quand elle change (le client choisit la premiere
-- competence apprenable a l'ouverture)
local choisi = f.selectedService
if choisi and choisi ~= h.dernierChoix then
h.dernierChoix = choisi
if choisi <= h.decalage then
h.decalage = choisi - 1
elseif choisi > h.decalage + tiennent(h.decalage + 1, total, place) then
local d = choisi - 1
while d > 0 and tiennent(d, total, place) >= choisi - d + 1 do d = d - 1 end
h.decalage = d
end
end
h.decalage = math.max(0, math.min(h.decalage or 0, maxi))
local avec = maxi > 0
if avec ~= h.avecBarre then
h.avecBarre = avec
poserListe(avec)
end
local largeur = h.liste:GetWidth() - N.liste.droite
local argent = GetMoney()
local y, nc, ns = N.liste.haut, 0, 0
local sousCategorie = false
-- un en-tete avant le decalage met les competences suivantes en retrait
for i = 1, h.decalage do
local _, _, genre = GetTrainerServiceInfo(i)
if genre == "header" then sousCategorie = true end
end
for i = h.decalage + 1, total do
local nom, _, genre, deplie = GetTrainerServiceInfo(i)
local ht = (genre == "header") and N.categorie.h or N.competence.h
if y + ht > place then break end
local ligne
if genre == "header" then
sousCategorie = true
nc = nc + 1
ligne = h.categories[nc] or creerCategorie(h.liste, nc)
h.categories[nc] = ligne
ligne:SetID(i)
ligne.deplie = deplie and true or false
ligne.nom:SetText(nom or "")
local atlas = deplie and "professions-recipe-header-collapse" or "professions-recipe-header-expand"
ForeverUI.SetAtlas(ligne.fleche, atlas)
ForeverUI.SetAtlas(ligne.lueur, atlas)
poser(ligne, "TOPLEFT", h.liste, "TOPLEFT", 0, -y)
ligne:SetWidth(largeur)
else
ns = ns + 1
ligne = h.competences[ns] or creerCompetence(h.liste, ns)
h.competences[ns] = ligne
remplirCompetence(ligne, i, argent)
local retrait = sousCategorie and N.liste.retrait or 0
poser(ligne, "TOPLEFT", h.liste, "TOPLEFT", retrait, -y)
ligne:SetWidth(largeur - retrait)
end
ligne:Show()
y = y + ht
end
for i = nc + 1, #h.categories do h.categories[i]:Hide() end
for i = ns + 1, #h.competences do h.competences[i]:Hide() end
h.barre:Regler(maxi + 1, 1, h.decalage)
end
-- le rang du metier du maitre (camelot : GetTrainerTradeskillRankValues)
function T.MajRang()
local h = ClassTrainerFrame.foreverHabit
local barre = h.rang
local metier
if IsTradeskillTrainer() then
for i = 1, GetNumTrainerServices() or 0 do
metier = GetTrainerServiceSkillLine(i)
if metier then break end
end
end
local rang, maxi, bonus
if metier then
for j = 1, GetNumSkillLines() or 0 do
local nom, entete, _, r, _, b, m = GetSkillLineInfo(j)
if not entete and nom == metier then
rang, bonus, maxi = r, b, m
break
end
end
end
if not rang or not maxi or maxi <= 0 then
barre:Hide()
return
end
barre:SetMinMaxValues(0, maxi)
barre:SetValue(rang)
if bonus and bonus > 0 then
barre.texte:SetFormattedText(L.TRAINER_RANK_BONUS, rang, bonus, maxi)
else
barre.texte:SetFormattedText(L.TRAINER_RANK, rang, maxi)
end
barre:Show()
end
-- ------------------------------------------------------------ la fenetre
-- l'ecran du client, sans souris et invisible : lignes, listes, details
local function etouffer()
for i = 1, CLASS_TRAINER_SKILLS_DISPLAYED or 11 do
local b = _G["ClassTrainerSkill" .. i]
if b then b:SetAlpha(0) b:EnableMouse(false) end
end
for _, nom in ipairs({ "ClassTrainerListScrollFrame", "ClassTrainerDetailScrollFrame" }) do
local fx = _G[nom]
if fx then
fx:SetAlpha(0)
fx:EnableMouse(false)
if fx.EnableMouseWheel then fx:EnableMouseWheel(false) end
for _, s in ipairs({ "ScrollBar", "ScrollBarScrollUpButton", "ScrollBarScrollDownButton" }) do
local c = _G[nom .. s]
if c then c:EnableMouse(false) end
end
end
end
if ClassTrainerSkillIcon then ClassTrainerSkillIcon:EnableMouse(false) end
for _, r in ipairs({ ClassTrainerSkillHighlightFrame, ClassTrainerGreetingText, ClassTrainerHorizontalBarLeft,
ClassTrainerNameText, ClassTrainerFramePortrait }) do
if r then r:SetAlpha(0) end
end
for _, c in ipairs({ ClassTrainerExpandButtonFrame, ClassTrainerCancelButton }) do
if c then ForeverUI.Suppress(c) end
end
end
function T.Habiller()
local f = ClassTrainerFrame
if not f or f.foreverHabit then return end
-- l'art de 3.3.5 : les quatre UI-ClassTrainer-* (deux sans nom) et le
-- morceau droit sans nom de la barre horizontale
for _, r in ipairs({ f:GetRegions() }) do
if r:GetObjectType() == "Texture" then
local t = r:GetTexture()
if type(t) == "string" then
t = string.lower(t)
if string.find(t, "ui-classtrainer-", 1, true) or string.find(t, "horizontalbar", 1, true) then
r:SetAlpha(0)
end
end
end
end
etouffer()
f:SetWidth(N.fenetre[1])
f:SetHeight(N.fenetre[2])
f:SetHitRectInsets(0, 0, 0, 0)
local habit = Gb.FenetrePortrait(f, {
portraitCote = N.portrait.cote, portraitX = N.portrait.x, portraitY = N.portrait.y,
titre = ClassTrainerNameText:GetText(),
})
f.foreverHabit = habit
local function suivre() habit.titre:SetText(ClassTrainerNameText:GetText() or "") end
hooksecurefunc(ClassTrainerNameText, "SetText", suivre)
-- l'encart : marbre (BORDER) ; fond de la liste (ARTWORK) ; liseré
-- (OVERLAY, au-dessus du fond qu'il borde, comme chez camelot)
local E = N.encart
local rect = CreateFrame("Frame", nil, f)
rect:EnableMouse(false)
rect:SetPoint("TOPLEFT", f, "TOPLEFT", E[1], E[2])
rect:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", E[3], E[4])
local marbre = f:CreateTexture(nil, "BORDER")
marbre:SetTexture(ART.marbre, true)
if marbre.SetHorizTile then marbre:SetHorizTile(true) marbre:SetVertTile(true) end
marbre:SetAllPoints(rect)
habit.encart = { rect = rect, marbre = marbre, lisere = Gb.NeufTranches(f, "InsetFrameTemplate", rect, "OVERLAY") }
-- la liste et son fond
local Li = N.liste
local liste = CreateFrame("Frame", "ForeverUITrainerList", f)
liste:SetPoint("TOPLEFT", rect, "TOPLEFT", Li[1], Li[2])
liste:SetWidth(Li[3])
liste:SetHeight(Li[4])
habit.liste = liste
habit.categories, habit.competences, habit.decalage = {}, {}, 0
local F = N.fondListe
local fond = morceau(f, "ARTWORK", TEXTURES, COORDS.fond)
fond:SetPoint("TOPLEFT", liste, "TOPLEFT", F[1], F[2])
fond:SetPoint("BOTTOMRIGHT", liste, "BOTTOMRIGHT", F[3], F[4])
habit.fondListe = fond
-- la barre de camelot, a droite de la liste
local barre = ForeverUI.CreateScrollBar("ForeverUITrainerScrollBar", f, liste)
barre:ClearAllPoints()
barre:SetPoint("TOPLEFT", liste, "TOPRIGHT", N.barre[1], N.barre[2])
barre:SetPoint("BOTTOMLEFT", liste, "BOTTOMRIGHT", N.barre[1], N.barre[2])
barre.surDefilement = function(nouveau)
habit.decalage = nouveau
T.Maj()
end
habit.barre = barre
liste:EnableMouseWheel(true)
liste:SetScript("OnMouseWheel", function(_, sens)
habit.decalage = math.max(0, math.min((habit.decalage or 0) - sens, habit.maxi or 0))
T.Maj()
end)
-- le rang (maitre de metier)
local R = N.rang
local rang = CreateFrame("StatusBar", "ForeverUITrainerRankBar", f)
rang:SetWidth(R[3])
rang:SetHeight(R[4])
rang:SetPoint("TOPLEFT", f, "TOPLEFT", R[1], R[2])
rang:SetStatusBarTexture(ART.barre)
rang:SetStatusBarColor(0, 0, 1, 0.5)
local fondRang = rang:CreateTexture(nil, "BACKGROUND")
fondRang:SetAllPoints(rang)
fondRang:SetTexture(0, 0, 0.75, 0.5)
local rg = morceau(rang, "ARTWORK", ART.guilde, COORDS.rangG)
rg:SetWidth(R.bord)
rg:SetPoint("TOPLEFT", rang, "TOPLEFT", -2, 0)
rg:SetPoint("BOTTOMLEFT", rang, "BOTTOMLEFT", -2, 0)
local rd = morceau(rang, "ARTWORK", ART.guilde, COORDS.rangD)
rd:SetWidth(R.bord)
rd:SetPoint("TOPRIGHT", rang, "TOPRIGHT", 2, 0)
rd:SetPoint("BOTTOMRIGHT", rang, "BOTTOMRIGHT", 2, 0)
local rm = morceau(rang, "ARTWORK", ART.guilde, COORDS.rangM)
rm:SetPoint("TOPLEFT", rg, "TOPRIGHT", 0, 0)
rm:SetPoint("BOTTOMRIGHT", rd, "BOTTOMLEFT", 0, 0)
rang.texte = rang:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
rang.texte:SetPoint("CENTER", rang, "CENTER", 0, 0)
rang:Hide()
habit.rang = rang
-- le filtre
local Fi = N.filtre
local dd = ClassTrainerFrameFilterDropDown
Gb.MenuFiltre(dd, Fi[3])
poser(dd, "TOPRIGHT", f, "TOPRIGHT", Fi[1], Fi[2])
-- Former, l'argent
local Fo = N.former
local b = ClassTrainerTrainButton
b:SetWidth(Fo[1])
b:SetHeight(Fo[2])
poser(b, "BOTTOMRIGHT", f, "BOTTOMRIGHT", Fo[3], Fo[4])
Gb.BoutonPanneau(b)
local A = N.argent
local cadreArgent = f:CreateTexture(nil, "ARTWORK")
cadreArgent:SetTexture(ART.argent)
cadreArgent:SetWidth(A[1])
cadreArgent:SetHeight(A[2])
cadreArgent:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", A[3], A[4])
habit.cadreArgent = cadreArgent
poser(ClassTrainerMoneyFrame, "RIGHT", cadreArgent, "RIGHT", A.bourse[1], A.bourse[2])
Gb.Croix(ClassTrainerFrameCloseButton, f)
ClassTrainerFrameCloseButton:SetFrameLevel(f:GetFrameLevel() + 22)
hooksecurefunc("ClassTrainerFrame_Update", T.Maj)
end
T.Habiller()
local veille = CreateFrame("Frame")
veille:RegisterEvent("ADDON_LOADED")
veille:SetScript("OnEvent", function(_, _, nom)
if nom == "Blizzard_TrainerUI" then
T.Habiller()
end
end)