Files
ShaguTweaks-Extras-ClassicAPI/mods/minimap-framerate-latency.lua
Dusk 02b1ce13d2 Tighten minimap stats spacing
Slightly overlap the framerate and latency borders with the MiniMap Clock for a tighter visual grouping without changing ticker behavior.
2026-09-08 11:38:34 +02:00

163 lines
5.0 KiB
Lua

-- Adapted from TokensWorth/ShaguTweaks-mods (MIT, original copyright GryllsAddons).
local _G = ShaguTweaks.GetGlobalEnv()
local T = ShaguTweaks.T
local floor = math.floor
local module = ShaguTweaks:register({
title = T["MiniMap Framerate & Latency"],
description = T["Adds a small framerate & latency display to the mini map."],
expansions = { ["vanilla"] = true, ["tbc"] = nil },
category = T["Minimap & World Map"],
enabled = nil,
})
local TARGET_FPS = 60
local LOW_LATENCY = tonumber(_G.PERFORMANCEBAR_LOW_LATENCY) or 300
local MEDIUM_LATENCY = tonumber(_G.PERFORMANCEBAR_MEDIUM_LATENCY) or 600
local function CreateStatusFrame(width)
local frame = CreateFrame("Frame", nil, Minimap)
frame:SetFrameLevel(64)
frame:SetWidth(width)
frame:SetHeight(23)
frame:SetClampedToScreen(true)
frame:EnableMouse(true)
frame:SetBackdrop({
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true,
tileSize = 8,
edgeSize = 16,
insets = { left = 3, right = 3, top = 3, bottom = 3 },
})
frame:SetBackdropBorderColor(.9, .8, .5, 1)
frame:SetBackdropColor(.4, .4, .4, 1)
frame.text = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
frame.text:SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
frame.text:SetAllPoints(frame)
frame.text:SetFontObject(GameFontWhite)
return frame
end
local function SetFPSColor(text, fps)
local perc = fps / TARGET_FPS
if perc < 0 then perc = 0 elseif perc > 1 then perc = 1 end
local r, g
if perc <= .5 then
r = 1
g = perc * 2
else
r = (1 - perc) * 2
g = 1
end
text:SetTextColor(r, g, 0, 1)
end
local function SetLatencyColor(text, latency)
if latency > MEDIUM_LATENCY then
text:SetTextColor(1, 0, 0, 1)
elseif latency > LOW_LATENCY then
text:SetTextColor(1, 1, 0, 1)
else
text:SetTextColor(0, 1, 0, 1)
end
end
module.enable = function(self)
if self.ticker then
self.ticker:Cancel()
self.ticker = nil
end
-- Extras is ClassicAPI-first. Do not restore the original permanent
-- OnUpdate implementation when the native scheduler is unavailable.
if type(_G.C_Timer) ~= "table" or type(_G.C_Timer.NewTicker) ~= "function" then
return
end
if not self.fpsFrame then
self.fpsFrame = CreateStatusFrame(49)
self.latencyFrame = CreateStatusFrame(51)
end
local fpsFrame = self.fpsFrame
local latencyFrame = self.latencyFrame
local lowFPS, highFPS
local lowMS, highMS
-- Follow the existing ShaguTweaks MiniMap Clock instead of independently
-- anchoring to MinimapCluster. MiniMap Square and mover integrations already
-- reposition that clock, so these counters follow automatically regardless
-- of module initialization order.
fpsFrame:ClearAllPoints()
latencyFrame:ClearAllPoints()
if _G.MinimapClock then
fpsFrame:SetPoint("RIGHT", _G.MinimapClock, "LEFT", 2, 0)
latencyFrame:SetPoint("LEFT", _G.MinimapClock, "RIGHT", -2, 0)
else
fpsFrame:SetPoint("BOTTOM", Minimap, "BOTTOM", -28, -25)
latencyFrame:SetPoint("BOTTOM", Minimap, "BOTTOM", 28, -25)
end
local function Update()
local fps = floor(GetFramerate() or 0)
local _, _, latency = GetNetStats()
latency = floor(latency or 0)
if fps > 0 and (not lowFPS or fps < lowFPS) then lowFPS = fps end
if not highFPS or fps > highFPS then highFPS = fps end
if latency > 0 and (not lowMS or latency < lowMS) then lowMS = latency end
if not highMS or latency > highMS then highMS = latency end
fpsFrame.text:SetText(tostring(fps))
latencyFrame.text:SetText(tostring(latency))
SetFPSColor(fpsFrame.text, fps)
SetLatencyColor(latencyFrame.text, latency)
end
fpsFrame:SetScript("OnEnter", function()
GameTooltip:ClearLines()
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
GameTooltip:AddLine(T["Framerate"])
GameTooltip:AddDoubleLine(T["High"], tostring(highFPS or 0) .. " " .. T["fps"], 1,1,1,1,1,1)
GameTooltip:AddDoubleLine(T["Low"], tostring(lowFPS or 0) .. " " .. T["fps"], 1,1,1,1,1,1)
GameTooltip:Show()
end)
latencyFrame:SetScript("OnEnter", function()
GameTooltip:ClearLines()
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
GameTooltip:AddLine(T["Latency"])
GameTooltip:AddDoubleLine(T["High"], tostring(highMS or 0) .. " " .. T["ms"], 1,1,1,1,1,1)
GameTooltip:AddDoubleLine(T["Low"], tostring(lowMS or 0) .. " " .. T["ms"], 1,1,1,1,1,1)
GameTooltip:Show()
end)
fpsFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
latencyFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
fpsFrame:Show()
latencyFrame:Show()
Update()
-- One native ClassicAPI ticker services both displays. Lua only wakes once
-- per second instead of running two permanent OnUpdate handlers every frame.
self.ticker = _G.C_Timer.NewTicker(1, Update)
end
module.disable = function(self)
if self.ticker then
self.ticker:Cancel()
self.ticker = nil
end
if self.fpsFrame then self.fpsFrame:Hide() end
if self.latencyFrame then self.latencyFrame:Hide() end
end