053624b061
J'ai enfreint la regle de lecture des sources : AutoCastTemplates n'existe que dans mainline/, et seuls camelot/ et shared/ font foi. L'anneau que j'en avais tire -- coins fixes et fourmis tournantes -- est retire, avec ses deux petites feuilles, sa table d'atlas et l'outil qui les produisait. camelot garde ici le comportement de 3.3.5 : sa bordure scintillante et ses quatre etincelles. La regle est desormais ecrite en tete d'AMELIORATIONS : un fichier qui n'existe que dans mainline/ n'est pas une source, c'est un point a trancher. L'echelle, pas la taille : redimensionner le cadre des etincelles ne suffit pas, le client les pose a une taille fixe et AutoCastShine_OnUpdate les deplace sans les retailler -- d'ou des etincelles trop grosses sur un cercle trop petit. SetScale(30/36) sur le cadre fait suivre tailles et orbite. La bordure, elle, passe de 58 a 48,3. Le piege de SetRotation reste note : il efface le rectangle d'atlas. Plus aucun element ne tourne aujourd'hui, mais la note servira. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
367 lines
13 KiB
Lua
367 lines
13 KiB
Lua
-- ForeverUI : la barre du familier.
|
|
--
|
|
-- RELEVE DES SOURCES -- tout vient du code extrait de camelot.
|
|
--
|
|
-- mainline/PetActionBar.xml
|
|
-- PetActionButtonTemplate herite de SmallActionButtonTemplate : meme
|
|
-- bouton de 30 x 30 que les postures.
|
|
-- La barre : isHorizontal, numRows 1, numButtons 10, addButtonsToRight.
|
|
--
|
|
-- shared/ActionBar.lua -- minButtonPadding = 2, donc un pas de 32.
|
|
--
|
|
-- shared/ActionButton.lua, SmallActionButtonMixin_OnLoad
|
|
-- raccourci TOPRIGHT (-3, -4) ; quantite BOTTOMRIGHT (-3, 1) ; survol,
|
|
-- coche, bordure et eclat en 31,6 x 30,9 ; recharge sur l'icone en
|
|
-- (1,7 ; -1,7) et (-1 ; 1) ; cadre normal et enfonce ramenes a 35 x 35 ;
|
|
-- AutoCastOverlay en 31 x 31, centre a (0,5 ; -0,5).
|
|
--
|
|
-- L'AUTOLANCEMENT N'EST PAS REPRIS DE LA SOURCE. AutoCastTemplates n'existe
|
|
-- que dans mainline/, et seuls camelot/ et shared/ font foi : camelot garde
|
|
-- ici le comportement d'origine. On laisse donc au client sa bordure
|
|
-- scintillante ($parentAutoCastable) et ses quatre etincelles tournantes
|
|
-- ($parentShine), qu'il allume et eteint lui-meme dans PetActionBar_Update.
|
|
-- Elles sont seulement mises a l'echelle du bouton, qui passe de 36 a 30.
|
|
--
|
|
-- shared/PetActionBar.lua, PetActionButtonMixin:UpdateButtonState
|
|
-- l'icone prend la texture de l'action ; si isToken, le nom et la texture
|
|
-- sont des cles de variables GLOBALES et non des valeurs.
|
|
-- action active : le bouton est COCHE ; si c'est l'attaque, il clignote
|
|
-- et son coche tombe a 0,5 d'alpha -- "a pleine alpha on croirait une
|
|
-- capacite de plus selectionnee", dit le commentaire de la source.
|
|
-- action inutilisable : icone teintee a 0,4. Pas de texture : icone
|
|
-- masquee.
|
|
-- La barre se montre si PetHasActionBar() et UnitIsVisible("pet").
|
|
--
|
|
-- CE QUI DIFFERE, ET POURQUOI.
|
|
-- GetPetActionInfo ne rend pas la meme chose : le moderne donne
|
|
-- (nom, texture, isToken, active, autoPossible, autoActif, sort), 3.3.5
|
|
-- donne (nom, SOUS-TEXTE, texture, isToken, active, autoPossible,
|
|
-- autoActif). Un champ de plus au deuxieme rang : recopier la source au
|
|
-- mot pres prendrait le sous-texte pour la texture. Meme piege que sur la
|
|
-- barre des postures.
|
|
-- Les quatre etats sont CENTRES et non ancres TOPLEFT : un cadre de 35 sur
|
|
-- un bouton de 30 deborde de 5, et son trou sortirait de l'icone. Voir
|
|
-- StanceBar.lua, ou le calcul est detaille.
|
|
-- La marque de surbrillance (SpellHighlightTexture, atlas bags-newitem)
|
|
-- n'existe pas en 3.3.5 : HasPetActionHighlightMark n'y est pas.
|
|
-- Les boutons sont SECURISES : rhabilles, jamais recrees, et rien n'est
|
|
-- redimensionne ni deplace en combat.
|
|
|
|
local TAILLE = 30 -- SmallActionButtonTemplate
|
|
local ECART = 2 -- minButtonPadding
|
|
local PAS = TAILLE + ECART -- 32
|
|
local CADRE_L, CADRE_H = 35, 35 -- NormalTexture et PushedTexture
|
|
local ETAT_L, ETAT_H = 31.6, 30.9 -- survol, coche, bordure, eclat
|
|
local NB_BOUTONS = 10
|
|
local TAILLE_ORIGINE = 36 -- le bouton de 3.3.5
|
|
local AUTOCAST_BORDURE = 58 -- sa bordure d'autolancement
|
|
local GRISE = 0.4 -- action inutilisable
|
|
local COCHE_ATTAQUE = 0.5 -- alpha du coche sur l'attaque
|
|
|
|
-- LA PLACE PAR DEFAUT. La barre se pose juste au-dessus de la barre de
|
|
-- reputation, sur le meme bord gauche que la barre d'action. Si la barre
|
|
-- des postures est la, la barre du familier passe A SA DROITE, separee
|
|
-- d'elle par la largeur de deux de ses icones.
|
|
local BORD_GAUCHE = -587.5 -- le bord gauche de la barre d'action
|
|
local RANGEE = 84 -- au-dessus de la reputation
|
|
local ECART_BARRES = 2 * TAILLE -- deux icones entre les deux barres
|
|
|
|
local ATLAS = {
|
|
normal = "ui-hud-actionbar-iconframe",
|
|
pushed = "ui-hud-actionbar-iconframe-down",
|
|
highlight = "ui-hud-actionbar-iconframe-mouseover",
|
|
flash = "ui-hud-actionbar-iconframe-flash",
|
|
slot = "ui-hud-actionbar-iconframe-slot",
|
|
background = "ui-hud-actionbar-iconframe-background",
|
|
}
|
|
|
|
local nombreDeBoutons = NUM_PET_ACTION_SLOTS or NB_BOUTONS
|
|
|
|
local porteur = CreateFrame("Frame", "ForeverUIPetBarHolder", UIParent)
|
|
porteur:SetWidth(PAS)
|
|
porteur:SetHeight(TAILLE)
|
|
porteur:Hide()
|
|
|
|
local function taireNormale(bouton)
|
|
local normale = bouton:GetNormalTexture()
|
|
if normale then
|
|
normale:SetAlpha(0)
|
|
normale:SetVertexColor(1, 1, 1, 0)
|
|
end
|
|
end
|
|
|
|
-- Les quatre etats sont centres : voir l'entete et StanceBar.lua.
|
|
local function poserEtat(texture, atlas, largeur, hauteur, add)
|
|
if not texture then
|
|
return
|
|
end
|
|
|
|
ForeverUI.SetAtlas(texture, atlas, true)
|
|
texture:SetWidth(largeur)
|
|
texture:SetHeight(hauteur)
|
|
texture:ClearAllPoints()
|
|
texture:SetPoint("CENTER", 0, 0)
|
|
texture:SetBlendMode(add and "ADD" or "BLEND")
|
|
end
|
|
|
|
local function habiller(bouton)
|
|
if not bouton or bouton.foreverSkinned then
|
|
return
|
|
end
|
|
|
|
local nom = bouton:GetName()
|
|
bouton:SetWidth(TAILLE)
|
|
bouton:SetHeight(TAILLE)
|
|
taireNormale(bouton)
|
|
|
|
local flottant = _G[nom .. "FloatingBG"]
|
|
if flottant then
|
|
flottant:SetAlpha(0)
|
|
end
|
|
|
|
-- L'AUTOLANCEMENT RESTE CELUI DU CLIENT. AutoCastTemplates n'existe que
|
|
-- dans mainline/, et seuls camelot/ et shared/ font foi : camelot garde
|
|
-- donc ici le comportement d'origine, sa bordure scintillante et ses
|
|
-- quatre etincelles tournantes. On n'y touche pas -- on les met
|
|
-- seulement a l'echelle du bouton, qui passe de 36 a 30.
|
|
local echelle = TAILLE / TAILLE_ORIGINE
|
|
local scintillante = _G[nom .. "AutoCastable"]
|
|
if scintillante then
|
|
scintillante:SetWidth(AUTOCAST_BORDURE * echelle)
|
|
scintillante:SetHeight(AUTOCAST_BORDURE * echelle)
|
|
end
|
|
-- Les etincelles ne se redimensionnent pas : le client les pose lui-meme
|
|
-- autour du cadre, a une taille fixe, et AutoCastShine_OnUpdate les
|
|
-- deplace sans les retailler. Changer la taille du cadre laissait donc
|
|
-- des etincelles trop grosses tournant sur un cercle trop petit. On met
|
|
-- le cadre a l'ECHELLE : tout ce qu'il contient suit, tailles et orbite.
|
|
local etincelles = _G[nom .. "Shine"]
|
|
if etincelles then
|
|
etincelles:SetScale(echelle)
|
|
end
|
|
|
|
local fond = bouton:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(fond, ATLAS.background, true)
|
|
fond:SetAllPoints(bouton)
|
|
|
|
local emplacement = bouton:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(emplacement, ATLAS.slot, true)
|
|
emplacement:SetAllPoints(bouton)
|
|
bouton.foreverFond = fond
|
|
bouton.foreverEmplacement = emplacement
|
|
|
|
local icone = _G[nom .. "Icon"]
|
|
if icone then
|
|
icone:ClearAllPoints()
|
|
icone:SetAllPoints(bouton)
|
|
icone:SetTexCoord(0, 1, 0, 1)
|
|
icone:SetDrawLayer("BORDER")
|
|
bouton.foreverIcone = icone
|
|
end
|
|
|
|
local cadre = bouton:CreateTexture(nil, "OVERLAY")
|
|
poserEtat(cadre, ATLAS.normal, CADRE_L, CADRE_H)
|
|
bouton.foreverCadre = cadre
|
|
|
|
poserEtat(bouton:GetPushedTexture(), ATLAS.pushed, CADRE_L, CADRE_H)
|
|
poserEtat(bouton:GetHighlightTexture(), ATLAS.highlight, ETAT_L, ETAT_H)
|
|
poserEtat(bouton:GetCheckedTexture(), ATLAS.highlight, ETAT_L, ETAT_H, true)
|
|
poserEtat(_G[nom .. "Flash"], ATLAS.flash, ETAT_L, ETAT_H)
|
|
|
|
local recharge = _G[nom .. "Cooldown"]
|
|
if recharge and icone then
|
|
recharge:ClearAllPoints()
|
|
recharge:SetPoint("TOPLEFT", icone, "TOPLEFT", 1.7, -1.7)
|
|
recharge:SetPoint("BOTTOMRIGHT", icone, "BOTTOMRIGHT", -1, 1)
|
|
bouton.foreverRecharge = recharge
|
|
end
|
|
|
|
local raccourci = _G[nom .. "HotKey"]
|
|
if raccourci then
|
|
raccourci:ClearAllPoints()
|
|
raccourci:SetPoint("TOPRIGHT", bouton, "TOPRIGHT", -3, -4)
|
|
end
|
|
|
|
local quantite = _G[nom .. "Count"]
|
|
if quantite then
|
|
quantite:ClearAllPoints()
|
|
quantite:SetPoint("BOTTOMRIGHT", bouton, "BOTTOMRIGHT", -3, 1)
|
|
end
|
|
|
|
bouton.foreverSkinned = true
|
|
end
|
|
|
|
-- L'ART D'EPOQUE DE LA BARRE. 3.3.5 encadre sa barre de familier de deux
|
|
-- morceaux glissants, SlidingActionBarTexture0 et 1. On ne se fie pas a
|
|
-- leurs noms : TOUTES les regions du cadre lui-meme s'effacent, les boutons
|
|
-- etant des cadres fils et non des regions -- ils ne sont donc pas touches.
|
|
local function effacerArtDepoque()
|
|
local barre = PetActionBarFrame
|
|
if not barre or not barre.GetNumRegions then
|
|
return
|
|
end
|
|
|
|
local regions = { barre:GetRegions() }
|
|
for _, region in ipairs(regions) do
|
|
if region and region.GetObjectType and region:GetObjectType() == "Texture" then
|
|
region:SetAlpha(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function habillerTout()
|
|
for index = 1, nombreDeBoutons do
|
|
habiller(_G["PetActionButton" .. index])
|
|
end
|
|
effacerArtDepoque()
|
|
end
|
|
|
|
-- La barre se montre si le familier a une barre ET s'il est visible.
|
|
local function familierPresent()
|
|
if not PetHasActionBar or not PetHasActionBar() then
|
|
return false
|
|
end
|
|
return UnitIsVisible and UnitIsVisible("pet") and true or false
|
|
end
|
|
|
|
-- La place par defaut se recalcule : elle depend de la barre des postures,
|
|
-- qui va et vient avec les formes du personnage. SetDefaults ne repose le
|
|
-- cadre que si l'utilisateur ne l'a pas deja deplace lui-meme.
|
|
local function posePardefaut()
|
|
local x = BORD_GAUCHE
|
|
local postures = ForeverUI.StanceBar and ForeverUI.StanceBar.Holder
|
|
if postures and postures:IsShown() then
|
|
x = x + postures:GetWidth() + ECART_BARRES
|
|
end
|
|
ForeverUI.Layout.SetDefaults("familier", "BOTTOMLEFT", "BOTTOM", x, RANGEE)
|
|
end
|
|
|
|
local function poser()
|
|
if not familierPresent() then
|
|
porteur:Hide()
|
|
return
|
|
end
|
|
|
|
if InCombatLockdown() then
|
|
return
|
|
end
|
|
|
|
porteur:SetWidth(nombreDeBoutons * TAILLE + (nombreDeBoutons - 1) * ECART)
|
|
porteur:SetHeight(TAILLE)
|
|
|
|
for index = 1, nombreDeBoutons do
|
|
local bouton = _G["PetActionButton" .. index]
|
|
if bouton then
|
|
bouton:SetWidth(TAILLE)
|
|
bouton:SetHeight(TAILLE)
|
|
bouton:ClearAllPoints()
|
|
bouton:SetPoint("LEFT", porteur, "LEFT", (index - 1) * PAS, 0)
|
|
bouton:Show()
|
|
end
|
|
end
|
|
|
|
porteur:Show()
|
|
posePardefaut()
|
|
end
|
|
|
|
-- RELEVE -- PetActionButtonMixin:UpdateButtonState.
|
|
local function majEtat()
|
|
for index = 1, nombreDeBoutons do
|
|
local bouton = _G["PetActionButton" .. index]
|
|
if bouton and bouton.foreverSkinned then
|
|
-- 3.3.5 : (nom, SOUS-TEXTE, texture, isToken, active,
|
|
-- autoPossible, autoActif). Le moderne n'a pas le sous-texte.
|
|
local nomAction, _, texture, estCle, active, autoPossible, autoActif =
|
|
GetPetActionInfo(index)
|
|
local icone = bouton.foreverIcone
|
|
|
|
if icone then
|
|
-- isToken : le nom et la texture sont des CLES de variables
|
|
-- globales, pas des valeurs.
|
|
icone:SetTexture(estCle and _G[texture] or texture)
|
|
if texture then
|
|
local utilisable = not GetPetActionSlotUsable
|
|
or GetPetActionSlotUsable(index)
|
|
if utilisable then
|
|
icone:SetVertexColor(1, 1, 1)
|
|
else
|
|
icone:SetVertexColor(GRISE, GRISE, GRISE)
|
|
end
|
|
icone:Show()
|
|
else
|
|
icone:Hide()
|
|
end
|
|
end
|
|
|
|
local coche = bouton:GetCheckedTexture()
|
|
if active then
|
|
-- L'attaque clignote, et son coche est a demi transparent :
|
|
-- a pleine alpha on croirait une capacite selectionnee.
|
|
local attaque = IsPetAttackAction and IsPetAttackAction(index)
|
|
if coche then
|
|
coche:SetAlpha(attaque and COCHE_ATTAQUE or 1)
|
|
end
|
|
bouton:SetChecked(1)
|
|
else
|
|
bouton:SetChecked(nil)
|
|
end
|
|
|
|
local recharge = bouton.foreverRecharge
|
|
if recharge and GetPetActionCooldown then
|
|
local debut, duree, actif = GetPetActionCooldown(index)
|
|
if CooldownFrame_SetTimer then
|
|
CooldownFrame_SetTimer(recharge, debut, duree, actif)
|
|
elseif CooldownFrame_Set then
|
|
CooldownFrame_Set(recharge, debut, duree, actif)
|
|
end
|
|
end
|
|
|
|
taireNormale(bouton)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function tout()
|
|
habillerTout()
|
|
poser()
|
|
majEtat()
|
|
end
|
|
|
|
ForeverUI.PetBar = { Apply = tout, Holder = porteur }
|
|
|
|
if hooksecurefunc then
|
|
for _, nomFonction in ipairs({ "PetActionBar_Update", "PetActionBar_UpdateCooldowns" }) do
|
|
if type(_G[nomFonction]) == "function" then
|
|
hooksecurefunc(nomFonction, function()
|
|
poser()
|
|
majEtat()
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
local veilleur = CreateFrame("Frame", "ForeverUIPetBarWatcher")
|
|
veilleur:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
veilleur:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
veilleur:RegisterEvent("UNIT_PET")
|
|
veilleur:RegisterEvent("PET_BAR_UPDATE")
|
|
veilleur:RegisterEvent("PET_BAR_UPDATE_COOLDOWN")
|
|
veilleur:RegisterEvent("PET_BAR_UPDATE_USABLE")
|
|
veilleur:RegisterEvent("PET_UI_UPDATE")
|
|
veilleur:RegisterEvent("PLAYER_CONTROL_LOST")
|
|
veilleur:RegisterEvent("PLAYER_CONTROL_GAINED")
|
|
-- Les formes changent la largeur de la barre des postures, donc la place
|
|
-- de celle-ci. StanceBar.lua est charge avant : son gestionnaire passe en
|
|
-- premier, et la largeur est deja bonne quand on la lit.
|
|
veilleur:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
|
|
veilleur:SetScript("OnEvent", tout)
|
|
|
|
tout()
|
|
|
|
-- Comme les autres barres : aucune position definitive ici, tout passe par
|
|
-- /fui. Par defaut la barre du familier se pose au-dessus de celle des
|
|
-- postures, sur le meme bord gauche.
|
|
ForeverUI.Layout.Register(porteur, "familier", "Barre du familier",
|
|
"BOTTOMLEFT", "BOTTOM", BORD_GAUCHE, RANGEE)
|
|
posePardefaut()
|