Files
moon-well-ui/data/addon/ForeverUI/PlayerFrameExtras.lua
T
Adrestie 115de7ed41 Add mod-forever-ui: the modern interface rebuilt for a 3.3.5a client
The addon and the art it needs, read from a modern client and served to
3.3.5 through texture coordinates, since that client has no atlas.

What is in place: player frame with its states, death knight runes, target
frame and its classification rings, cast bar, action bar with its page block
and end caps, micro menu, bags bar, experience and reputation bars. Every
piece registers itself as a movable system.

This folder is the workspace. The addon in a client and the art in patch-Z
are copies tools/deployer.py makes, and what sits under Interface\ForeverUI
in the patch is exactly what data/art holds -- the deployer removes from the
archive anything this folder no longer carries. Each .blp comes with the .png
that shows what it holds.

docs/AMELIORATIONS.md lists what is known to be improvable: where the
reproduction departs from the reference and why, what the 2010 client cannot
do, and the debts left in the tooling.

The repository README also gains the row for mod-limit-break, which was
written earlier and had not been committed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 20:12:09 +02:00

227 lines
7.5 KiB
Lua

-- ForeverUI : les accessoires du cadre joueur.
--
-- Tout ce fichier s'accroche a ForeverUI.PlayerFrame et vit dans son porteur
-- de calques (overlayHolder), donc au-dessus de l'art. Rien n'est ancre ici a
-- UIParent : ces elements appartiennent au cadre et le suivent quand on le
-- deplace, comme dans l'editeur de camelot ou ils font partie du meme systeme.
--
-- RELEVE DES SOURCES (declaration -> ce qui la consomme -> calque) :
-- icone PvP camelot/PlayerFrame.lua PlayerFrame_ShowPvPIcon : cercle
-- UI-HUD-UnitFrame-SmallCircle a l'echelle 0.8, ancre TOP sur
-- le TOPLEFT du cadre en (20, -50), icone de faction centree.
-- groupe mainline/PlayerFrame.xml GroupIndicator : cadre 10x16 ancre
-- BOTTOMRIGHT sur TOPLEFT (210, -29), embouts gauche/droite,
-- piece centrale etiree, texte GameFontHighlightSmall a 0.7.
-- Contenu : 3.3.5 PlayerFrame_UpdateGroupIndicator, GROUP..
-- numero de sous-groupe, visible en raid seulement.
-- temps de jeu mainline/PlayerFrame.xml PlayerPlayTime : 29x29 ancre
-- TOPLEFT sur TOPRIGHT (-21, -24). Etat : PartialPlayTime()
-- puis NoPlayTime(), evenement PLAYTIME_CHANGED.
-- degats recus mainline/PlayerFrame.xml HitIndicator : texte centre sur le
-- TOPLEFT du cadre en (54, -50), NumberFontNormalHuge. En
-- 3.3.5 c'est CombatFeedback_OnCombatEvent qui l'anime, via
-- UNIT_COMBAT : on reutilise la fonction du client.
local frame = ForeverUI.PlayerFrame
local holder = frame.overlayHolder
local PVP_CIRCLE = "ui-hud-unitframe-smallcircle"
local PVP_FFA = "ui-hud-unitframe-player-pvp-ffaicon"
local PVP_FACTION = {
Alliance = "ui-hud-unitframe-smallcircle-alliance",
Horde = "ui-hud-unitframe-smallcircle-horde",
}
local GROUP_LEFT = "ui-hud-unitframe-player-groupindicatorleft"
local GROUP_RIGHT = "ui-hud-unitframe-player-groupindicatorright"
local GROUP_MID = "_ui-hud-unitframe-player-groupindicatormid"
local PLAYTIME_TIRED_ATLAS = "ui-hud-unitframe-player-playtimetired"
local PLAYTIME_UNHEALTHY_ATLAS = "ui-hud-unitframe-player-playtimeunhealthy"
-- ------------------------------------------------------------------- PvP
local pvpCircle = holder:CreateTexture(nil, "ARTWORK")
ForeverUI.SetAtlas(pvpCircle, PVP_CIRCLE)
pvpCircle:SetPoint("TOP", frame, "TOPLEFT", 20, -50)
pvpCircle:SetWidth(39 * 0.8)
pvpCircle:SetHeight(39 * 0.8)
pvpCircle:Hide()
local pvpIcon = holder:CreateTexture(nil, "OVERLAY")
pvpIcon:SetPoint("CENTER", pvpCircle, "CENTER", 0, 0)
pvpIcon:Hide()
local function updatePvP()
local faction = UnitFactionGroup("player")
if UnitIsPVPFreeForAll("player") then
if ForeverUI.SetAtlas(pvpIcon, PVP_FFA) then
pvpIcon:SetWidth(24 * 0.8)
pvpIcon:SetHeight(27 * 0.8)
pvpCircle:Show()
pvpIcon:Show()
return
end
elseif faction and faction ~= "Neutral" and UnitIsPVP("player") then
local atlas = PVP_FACTION[faction]
if atlas and ForeverUI.SetAtlas(pvpIcon, atlas) then
pvpIcon:SetWidth(24 * 0.8)
pvpIcon:SetHeight(27 * 0.8)
pvpCircle:Show()
pvpIcon:Show()
return
end
end
pvpCircle:Hide()
pvpIcon:Hide()
end
-- --------------------------------------------------------------- groupe
local groupIndicator = CreateFrame("Frame", nil, holder)
groupIndicator:SetWidth(10)
groupIndicator:SetHeight(16)
groupIndicator:SetPoint("BOTTOMRIGHT", frame, "TOPLEFT", 210, -29)
groupIndicator:Hide()
local groupLeft = groupIndicator:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(groupLeft, GROUP_LEFT)
groupLeft:SetPoint("TOPLEFT")
local groupRight = groupIndicator:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(groupRight, GROUP_RIGHT)
groupRight:SetPoint("TOPRIGHT")
local groupMid = groupIndicator:CreateTexture(nil, "BACKGROUND")
ForeverUI.SetAtlas(groupMid, GROUP_MID, true)
groupMid:SetPoint("LEFT", groupLeft, "RIGHT")
groupMid:SetPoint("RIGHT", groupRight, "LEFT")
local groupText = groupIndicator:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
groupText:SetAlpha(0.7)
groupText:SetPoint("LEFT", 20, 2)
local function updateGroup()
local members = GetNumRaidMembers and GetNumRaidMembers() or 0
if members == 0 then
groupIndicator:Hide()
return
end
local playerName = UnitName("player")
for index = 1, members do
local name, _rank, subgroup = GetRaidRosterInfo(index)
if name == playerName and subgroup then
groupText:SetText((GROUP or "Groupe") .. " " .. subgroup)
groupIndicator:SetWidth(groupText:GetWidth() + 40)
groupIndicator:Show()
return
end
end
groupIndicator:Hide()
end
-- --------------------------------------------------------- temps de jeu
local playTime = CreateFrame("Frame", nil, holder)
playTime:SetWidth(29)
playTime:SetHeight(29)
playTime:SetPoint("TOPLEFT", frame, "TOPRIGHT", -21, -24)
playTime:EnableMouse(true)
playTime:Hide()
local playTimeIcon = playTime:CreateTexture(nil, "ARTWORK")
playTimeIcon:SetAllPoints(playTime)
playTime:SetScript("OnEnter", function(self)
if not self.tooltip then
return
end
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:SetText(self.tooltip, nil, nil, nil, nil, true)
end)
playTime:SetScript("OnLeave", function()
GameTooltip:Hide()
end)
local function updatePlayTime()
if PartialPlayTime and PartialPlayTime() then
ForeverUI.SetAtlas(playTimeIcon, PLAYTIME_TIRED_ATLAS, true)
playTime.tooltip = PLAYTIME_TIRED or "Temps de jeu"
playTime:Show()
elseif NoPlayTime and NoPlayTime() then
ForeverUI.SetAtlas(playTimeIcon, PLAYTIME_UNHEALTHY_ATLAS, true)
playTime.tooltip = PLAYTIME_UNHEALTHY or "Temps de jeu"
playTime:Show()
else
playTime:Hide()
end
end
-- -------------------------------------------------------- degats recus
local hitText = holder:CreateFontString(nil, "OVERLAY", "NumberFontNormalHuge")
hitText:SetPoint("CENTER", frame, "TOPLEFT", 54, -50)
hitText:Hide()
if CombatFeedback_Initialize then
CombatFeedback_Initialize(frame, hitText, 30)
end
-- ------------------------------------------------------------- cablage
local extras = CreateFrame("Frame")
extras:RegisterEvent("PLAYER_ENTERING_WORLD")
extras:RegisterEvent("PLAYER_FLAGS_CHANGED")
extras:RegisterEvent("UNIT_FACTION")
extras:RegisterEvent("RAID_ROSTER_UPDATE")
extras:RegisterEvent("PARTY_MEMBERS_CHANGED")
extras:RegisterEvent("PLAYTIME_CHANGED")
extras:RegisterEvent("UNIT_COMBAT")
extras:SetScript("OnEvent", function(_self, event, unit, action, descriptor, damage, damageType)
if event == "UNIT_COMBAT" then
if unit == "player" and CombatFeedback_OnCombatEvent then
CombatFeedback_OnCombatEvent(frame, action, descriptor, damage, damageType)
end
return
end
if event == "PLAYTIME_CHANGED" then
updatePlayTime()
return
end
if event == "RAID_ROSTER_UPDATE" or event == "PARTY_MEMBERS_CHANGED" then
updateGroup()
return
end
if event == "UNIT_FACTION" and unit ~= "player" then
return
end
updatePvP()
if event == "PLAYER_ENTERING_WORLD" then
updateGroup()
updatePlayTime()
end
end)
-- L'animation des degats recus est celle du client : on lui passe la main a
-- chaque image, comme le fait PlayerFrame_OnUpdate.
extras:SetScript("OnUpdate", function(_self, elapsed)
if CombatFeedback_OnUpdate then
CombatFeedback_OnUpdate(frame, elapsed)
end
end)
ForeverUI.PlayerFrameExtras = {
pvpCircle = pvpCircle,
pvpIcon = pvpIcon,
groupIndicator = groupIndicator,
groupText = groupText,
playTime = playTime,
playTimeIcon = playTimeIcon,
hitText = hitText,
updatePvP = updatePvP,
updateGroup = updateGroup,
updatePlayTime = updatePlayTime,
}