0880e155a9
PVPRankFrame.xml et pvprankframe.lua lus en entier. camelot tire tout de C_MajorFactions -- le renom -- qui n'existe pas ici. Mais les trois fonctions de l'epoque des rangs sont TOUJOURS dans le binaire, verifie dans Wow.exe : UnitPVPRank, GetPVPRankInfo et GetPVPRankProgress. WotLK a simplement cesse de s'en servir dans son FrameXML. Heureuse coincidence : la planche c60 de camelot porte QUATORZE icones de rang, exactement les quatorze rangs classiques. Son art est celui de l'epoque. Tout cet art vit sur une feuille que le listfile ne nomme pas : ajouter_feuilles.py accepte desormais "fdid:<n>.blp => interface/...", et retrouve ses entrees d'atlas par ce meme identifiant. Trois ecarts assumes. La jauge circulaire n'est pas portable -- camelot la fait avec un Cooldown dont il remplace la texture de balayage, SetSwipeTexture, ABSENT du binaire ; l'anneau, la lueur, le fond de faction et le badge sont poses, la progression s'ecrit en toutes lettres. GameFontNormalMed2 n'existe pas. Le compte a rebours de saison demande un C_SeasonInfo absent. Le volet droit porte ce que WotLK sait vraiment donner : l'honneur. Temoin : /fui pvp, qui dit ce que les trois fonctions rendent sur ce serveur. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
338 lines
9.0 KiB
Lua
338 lines
9.0 KiB
Lua
-- ForeverUI : positions modifiables.
|
|
--
|
|
-- POURQUOI CE FICHIER EXISTE AVANT LES CADRES. Sur camelot, aucun element
|
|
-- d'interface n'a de position figee : chacun est un "systeme" que le joueur
|
|
-- deplace, et sa position est retenue. On reprend le principe ici : tout ce que
|
|
-- ForeverUI construit s'enregistre avec une position par defaut, et c'est cette
|
|
-- table qui decide ou le cadre se pose au chargement. Un cadre qui poserait
|
|
-- lui-meme son SetPoint definitif serait le seul a ne pas etre deplacable.
|
|
--
|
|
-- Tout est ancre a UIParent, jamais a un autre cadre de ForeverUI : sinon
|
|
-- deplacer un element en entrainerait un autre, et le joueur ne pourrait plus
|
|
-- defaire l'enchainement.
|
|
|
|
ForeverUI = ForeverUI or {}
|
|
|
|
-- Neutraliser un cadre du client. Le masquer ne suffit pas : son propre code
|
|
-- le reaffiche a la premiere occasion (changement de page, sortie de vehicule,
|
|
-- mise a jour de runes). On coupe donc ses evenements, on le masque, et on
|
|
-- accroche son OnShow pour qu'il se remasque si quelque chose insiste.
|
|
function ForeverUI.Suppress(frame)
|
|
if not frame or frame.foreverSuppressed then
|
|
return
|
|
end
|
|
|
|
if frame.UnregisterAllEvents then
|
|
frame:UnregisterAllEvents()
|
|
end
|
|
frame:Hide()
|
|
|
|
if frame.HookScript then
|
|
frame:HookScript("OnShow", function(self)
|
|
self:Hide()
|
|
end)
|
|
end
|
|
|
|
frame.foreverSuppressed = true
|
|
end
|
|
|
|
local Layout = {}
|
|
ForeverUI.Layout = Layout
|
|
|
|
Layout.systems = {} -- id -> { frame, label, defaults }
|
|
Layout.order = {} -- ids, dans l'ordre d'enregistrement
|
|
Layout.editing = false
|
|
|
|
local PREFIX = "|cff66ccffForeverUI|r : "
|
|
|
|
local function say(message)
|
|
DEFAULT_CHAT_FRAME:AddMessage(PREFIX .. message)
|
|
end
|
|
|
|
local function positions()
|
|
ForeverUIDB = ForeverUIDB or {}
|
|
ForeverUIDB.positions = ForeverUIDB.positions or {}
|
|
return ForeverUIDB.positions
|
|
end
|
|
|
|
-- Pose le cadre a sa position retenue, ou a sa position par defaut.
|
|
function Layout.Apply(id)
|
|
local system = Layout.systems[id]
|
|
if not system then
|
|
return false
|
|
end
|
|
|
|
local saved = positions()[id]
|
|
local p = saved or system.defaults
|
|
|
|
system.frame:ClearAllPoints()
|
|
system.frame:SetPoint(p.point, UIParent, p.relativePoint, p.x, p.y)
|
|
return true
|
|
end
|
|
|
|
function Layout.Save(id)
|
|
local system = Layout.systems[id]
|
|
if not system then
|
|
return false
|
|
end
|
|
|
|
local point, _relativeTo, relativePoint, x, y = system.frame:GetPoint(1)
|
|
if not point then
|
|
return false
|
|
end
|
|
|
|
positions()[id] = {
|
|
point = point,
|
|
relativePoint = relativePoint or point,
|
|
x = x or 0,
|
|
y = y or 0,
|
|
}
|
|
return true
|
|
end
|
|
|
|
function Layout.Reset(id)
|
|
if id then
|
|
if not Layout.systems[id] then
|
|
return false
|
|
end
|
|
positions()[id] = nil
|
|
Layout.Apply(id)
|
|
return true
|
|
end
|
|
|
|
for _, systemID in ipairs(Layout.order) do
|
|
positions()[systemID] = nil
|
|
Layout.Apply(systemID)
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- L'enregistrement fait tout : rendre le cadre deplacable, le poser, et le
|
|
-- rendre visible en mode edition.
|
|
function Layout.Register(frame, id, label, point, relativePoint, x, y)
|
|
Layout.systems[id] = {
|
|
frame = frame,
|
|
label = label,
|
|
defaults = { point = point, relativePoint = relativePoint, x = x, y = y },
|
|
}
|
|
table.insert(Layout.order, id)
|
|
|
|
frame:SetMovable(true)
|
|
frame:SetClampedToScreen(true)
|
|
Layout.Apply(id)
|
|
|
|
if Layout.editing then
|
|
Layout.ShowOverlay(id)
|
|
end
|
|
return frame
|
|
end
|
|
|
|
-- Corriger la position par defaut d'un element deja enregistre. Le bas de
|
|
-- l'ecran est une chaine : la barre d'action et les sacs se posent de part et
|
|
-- d'autre du micro-menu, dont la largeur n'est connue qu'une fois ses boutons
|
|
-- comptes. Un element que le joueur a deja deplace garde sa position.
|
|
function Layout.SetDefaults(id, point, relativePoint, x, y)
|
|
local system = Layout.systems[id]
|
|
if not system then
|
|
return false
|
|
end
|
|
|
|
system.defaults = { point = point, relativePoint = relativePoint, x = x, y = y }
|
|
if not positions()[id] then
|
|
Layout.Apply(id)
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function buildOverlay(id, system)
|
|
local overlay = CreateFrame("Frame", nil, system.frame)
|
|
overlay:SetAllPoints(system.frame)
|
|
overlay:SetFrameStrata("DIALOG")
|
|
overlay:EnableMouse(true)
|
|
overlay:RegisterForDrag("LeftButton")
|
|
|
|
local background = overlay:CreateTexture(nil, "BACKGROUND")
|
|
background:SetAllPoints(overlay)
|
|
background:SetTexture(0.1, 0.6, 1, 0.35)
|
|
|
|
local text = overlay:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
text:SetPoint("CENTER")
|
|
text:SetText(system.label)
|
|
|
|
overlay:SetScript("OnDragStart", function()
|
|
if InCombatLockdown() then
|
|
say("deplacement impossible en combat.")
|
|
return
|
|
end
|
|
system.frame:StartMoving()
|
|
end)
|
|
|
|
overlay:SetScript("OnDragStop", function()
|
|
system.frame:StopMovingOrSizing()
|
|
Layout.Save(id)
|
|
end)
|
|
|
|
system.overlay = overlay
|
|
return overlay
|
|
end
|
|
|
|
function Layout.ShowOverlay(id)
|
|
local system = Layout.systems[id]
|
|
if not system then
|
|
return
|
|
end
|
|
|
|
local overlay = system.overlay or buildOverlay(id, system)
|
|
overlay:Show()
|
|
end
|
|
|
|
function Layout.HideOverlay(id)
|
|
local system = Layout.systems[id]
|
|
if system and system.overlay then
|
|
system.overlay:Hide()
|
|
end
|
|
end
|
|
|
|
function Layout.SetEditMode(enabled)
|
|
if enabled and InCombatLockdown() then
|
|
say("le mode edition n'est pas disponible en combat.")
|
|
return false
|
|
end
|
|
|
|
Layout.editing = enabled and true or false
|
|
|
|
for _, id in ipairs(Layout.order) do
|
|
if Layout.editing then
|
|
Layout.ShowOverlay(id)
|
|
else
|
|
Layout.HideOverlay(id)
|
|
end
|
|
end
|
|
|
|
if Layout.editing then
|
|
say("mode edition actif : glissez les elements, /fui pour terminer.")
|
|
else
|
|
say("mode edition termine, positions retenues.")
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- Le mode edition se coupe tout seul a l'entree en combat : un cadre securise
|
|
-- ne peut plus etre deplace a ce moment, et laisser les surfaces bleues
|
|
-- affichees ferait croire le contraire.
|
|
local watcher = CreateFrame("Frame")
|
|
watcher:RegisterEvent("PLAYER_LOGIN")
|
|
watcher:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
watcher:SetScript("OnEvent", function(_self, event)
|
|
if event == "PLAYER_LOGIN" then
|
|
for _, id in ipairs(Layout.order) do
|
|
Layout.Apply(id)
|
|
end
|
|
elseif event == "PLAYER_REGEN_DISABLED" and Layout.editing then
|
|
Layout.SetEditMode(false)
|
|
end
|
|
end)
|
|
|
|
SLASH_FOREVERUI1 = "/fui"
|
|
SLASH_FOREVERUI2 = "/foreverui"
|
|
|
|
SlashCmdList["FOREVERUI"] = function(message)
|
|
local command, argument = string.match(message or "", "^(%S*)%s*(.*)$")
|
|
argument = argument or ""
|
|
command = string.lower(command or "")
|
|
|
|
if command == "" or command == "edit" then
|
|
Layout.SetEditMode(not Layout.editing)
|
|
elseif command == "reset" then
|
|
if argument ~= "" then
|
|
if Layout.Reset(argument) then
|
|
say("position remise par defaut : " .. argument)
|
|
else
|
|
say("element inconnu : " .. argument)
|
|
end
|
|
else
|
|
Layout.Reset()
|
|
say("toutes les positions sont remises par defaut.")
|
|
end
|
|
elseif command == "bar" or command == "barre" then
|
|
if ForeverUI.ActionBarDebug then
|
|
ForeverUI.ActionBarDebug()
|
|
else
|
|
say("aucun diagnostic de barre disponible.")
|
|
end
|
|
elseif command == "bas" then
|
|
if ForeverUI.BottomBarDebug then
|
|
ForeverUI.BottomBarDebug()
|
|
else
|
|
say("aucun diagnostic du bas de l ecran disponible.")
|
|
end
|
|
elseif command == "barres" then
|
|
if ForeverUI.StatusBarsDebug then
|
|
ForeverUI.StatusBarsDebug()
|
|
else
|
|
say("aucun diagnostic des barres d etat disponible.")
|
|
end
|
|
elseif command == "sacs" then
|
|
local cle, valeur = string.match(argument, "^(%S+)%s+(%S+)$")
|
|
if cle and ForeverUI.BagsSet then
|
|
ForeverUI.BagsSet(cle, valeur)
|
|
elseif ForeverUI.BagsDebug then
|
|
ForeverUI.BagsDebug()
|
|
else
|
|
say("aucun diagnostic des sacs disponible.")
|
|
end
|
|
elseif command == "modele" then
|
|
if ForeverUI.CharacterModelTune then
|
|
ForeverUI.CharacterModelTune(argument)
|
|
else
|
|
say("aucun reglage du modele disponible.")
|
|
end
|
|
elseif command == "perso" then
|
|
if ForeverUI.CharacterSheetDebug then
|
|
ForeverUI.CharacterSheetDebug()
|
|
else
|
|
say("aucun diagnostic de la feuille disponible.")
|
|
end
|
|
elseif command == "pvp" then
|
|
if ForeverUI.PvPDebug then
|
|
ForeverUI.PvPDebug()
|
|
else
|
|
say("aucun diagnostic PvP disponible.")
|
|
end
|
|
elseif command == "skills" then
|
|
if ForeverUI.SkillsDebug then
|
|
ForeverUI.SkillsDebug()
|
|
else
|
|
say("aucun diagnostic des competences disponible.")
|
|
end
|
|
elseif command == "reput" then
|
|
if ForeverUI.ReputationDebug then
|
|
ForeverUI.ReputationDebug()
|
|
else
|
|
say("aucun diagnostic de la reputation disponible.")
|
|
end
|
|
elseif command == "sets" then
|
|
if ForeverUI.EquipmentSetsDebug then
|
|
ForeverUI.EquipmentSetsDebug()
|
|
else
|
|
say("aucun diagnostic des ensembles disponible.")
|
|
end
|
|
elseif command == "debug" then
|
|
if ForeverUI.PlayerFrameDebug then
|
|
ForeverUI.PlayerFrameDebug()
|
|
else
|
|
say("aucun diagnostic disponible.")
|
|
end
|
|
elseif command == "list" then
|
|
say("elements enregistres :")
|
|
for _, id in ipairs(Layout.order) do
|
|
local system = Layout.systems[id]
|
|
local saved = positions()[id]
|
|
DEFAULT_CHAT_FRAME:AddMessage(string.format(" %s (%s)%s", id, system.label,
|
|
saved and " - deplace" or ""))
|
|
end
|
|
else
|
|
say("commandes : /fui (mode edition), /fui reset [element], /fui list, /fui debug, /fui barre, /fui bas, /fui barres, /fui sacs, /fui perso, /fui modele, /fui sets, /fui reput, /fui skills, /fui pvp")
|
|
end
|
|
end
|