arruma este tab para mta:Salocal screenW, screenH = guiGetScreenSize()local panelVisible = falselocal scroll = 0local maxVisible = 15local font = dxCreateFont("default-bold"local aclGroups = { "Console", "SubDono", "Moderator", "SuperModerator", "Supervisor", "SupervisorGeral", "RAIO", "AdminGeral", "Admin", "Ajudante", "Youtuber", "VIP", "VIP GOLD", "GM"}local groupPlayers = {}function getACLGroup(player) for _, group in ipairs(aclGroups) do if isObjectInACLGroup("user." .. getAccountName(getPlayerAccount(player)), aclGetGroup(group)) then return group end end return "Jogadores"endfunction updateGroups() groupPlayers = {} for _, player in ipairs(getElementsByType("player")) do local group = getACLGroup(player) if not groupPlayers[group] then groupPlayers[group] = {} end table.insert(groupPlayers[group], player) endendsetTimer(updateGroups, 3000, 0)function drawPanel() if not panelVisible then return end dxDrawRectangle(screenW0.25, screenH0.1, screenW0.5, screenH0.8, tocolor(20, 20, 20, 220), true) dxDrawText("Painel de Jogadores", screenW0.25, screenH0.075, screenW0.75, screenH0.1, tocolor(255,255,255), 1, font, "center", "center", false, false, true) local y = screenH0.13 local lineHeight = 22 local count = 0 for group, players in pairs(groupPlayers) do dxDrawText("[" .. group .. "]", screenW0.26, y, screenW0.74, y+lineHeight, tocolor(80,180,255), 1, font, "left", "center", false, false, true) y = y + lineHeight for i, player in ipairs(players) do count = count + 1 if count > scroll and count <= scroll + maxVisible then local ping = getPlayerPing(player) local fps = getElementData(player, "fps") or "?" local id = getElementData(player, "playerid") or getElementID(player) or "" local nick = getPlayerName(player):gsub("#%x%x%x%x%x%x", "") local team = getTeamName(getPlayerTeam(player) or getTeamFromName("Sem Equipe")) local downloading = getElementData(player, "isClientDownloading") and "Baixando" or "Completo" dxDrawText("ID: "..getElementData(player, "ID") or getElementID(player) or "-", screenW0.26, y, screenW0.34, y+lineHeight, tocolor(255,255,255), 1, font, "left", "center", false, false, true) dxDrawText(nick, screenW0.34, y, screenW0.50, y+lineHeight, tocolor(200, 200, 200), 1, font, "left", "center", false, false, true) dxDrawText(downloading, screenW0.50, y, screenW0.58, y+lineHeight, tocolor(255,255,100), 1, font, "left", "center", false, false, true) dxDrawText("FPS: "..fps, screenW0.58, y, screenW0.66, y+lineHeight, tocolor(100,255,100), 1, font, "left", "center", false, false, true) dxDrawText("Ping: "..ping, screenW0.66, y, screenW0.74, y+lineHeight, tocolor(255,150,150), 1, font, "left", "center", false, false, true) dxDrawText(team, screenW0.74, y, screenW*0.76, y+lineHeight, tocolor(150,150,255), 1, font, "left", "center", false, false, true) y = y + lineHeight end end endendaddEventHandler("onClientRender", root, drawPanel)bindKey("tab", "both", function() panelVisible = not panelVisible showCursor(panelVisible)end)addEventHandler("onClientKey", root, function(key, press) if not panelVisible then return end if key == "mouse_wheel_up" and press then scroll = math.max(0, scroll - 1) elseif key == "mouse_wheel_down" and press then scroll = scroll + 1 endend)
-- MTA Client-Side Player Panel (TAB)
-- Global variables for screen dimensions and panel state
local screenW, screenH = guiGetScreenSize()
local panelVisible = false
local scrollOffset = 0 -- Tracks the current scroll position (line index)
local lineHeight = 22 -- Height of each line of text (group header or player info)
-- Panel dimensions and positions, calculated relative to screen size for responsiveness
local panelWidth = screenW * 0.5
local panelHeight = screenH * 0.8
local panelX = screenW * 0.25
local panelY = screenH * 0.1
-- Calculate maximum visible lines within the panel's content area
-- Reserve space for the title and some padding at the top of the content area
local contentStartY = panelY + screenH * 0.035 -- Starting Y position for the first content line
local contentHeight = panelHeight - (contentStartY - panelY) -- Usable height for content
local maxVisibleLines = math.floor(contentHeight / lineHeight) -- Max number of lines that can be displayed
-- Create a font for drawing text. Using "arial" as a common system font, bold, size 10.
-- If "default-bold" refers to a custom font file, its path should be used here.
local font = dxCreateFont("arial", 10, true)
if not font then -- Fallback if font creation fails
font = dxCreateFont("default", 10)
outputDebugString("Failed to create 'arial' font, falling back to 'default'.")
end
-- Define the order of ACL groups to be displayed
local aclGroups = {
"Console", "SubDono", "Moderator", "SuperModerator", "Supervisor", "SupervisorGeral",
"RAIO", "AdminGeral", "Admin", "Ajudante", "Youtuber", "VIP", "VIP GOLD", "GM"
}
local groupPlayers = {} -- Table to store players, grouped by their ACL group
-- Function to determine a player's highest ACL group based on the predefined order
function getACLGroup(player)
for _, group in ipairs(aclGroups) do
-- Check if the player's account is in the current ACL group
if isObjectInACLGroup("user." .. getAccountName(getPlayerAccount(player)), aclGetGroup(group)) then
return group
end
end
return "Jogadores" -- Default group for players who don't belong to any defined ACL group
end
-- Function to update the groupPlayers table with current player data
function updateGroups()
groupPlayers = {} -- Clear previous data
for _, player in ipairs(getElementsByType("player")) do
-- Ensure the element is a valid player before processing
if isElement(player) and getElementType(player) == "player" then
local group = getACLGroup(player)
if not groupPlayers[group] then
groupPlayers[group] = {} -- Initialize table for new group if it doesn't exist
end
table.insert(groupPlayers[group], player) -- Add player to their respective group
end
end
end
-- Set a timer to periodically update the player groups (every 3 seconds)
setTimer(updateGroups, 3000, 0)
-- Main drawing function, called on every client render frame
function drawPanel()
if not panelVisible then return end -- Only draw if the panel is visible
-- Draw the main panel background rectangle
dxDrawRectangle(panelX, panelY, panelWidth, panelHeight, tocolor(20, 20, 20, 220), true)
-- Draw the panel title at the top
dxDrawText("Painel de Jogadores", panelX, screenH * 0.075, panelX + panelWidth, panelY, tocolor(255, 255, 255), 1, font, "center", "center", false, false, true)
local currentLineIndex = 0 -- Tracks the absolute line index for scrolling logic
local drawY = contentStartY -- Current Y position where content will be drawn
-- Calculate the total number of content lines (group headers + players) for scroll limit
local totalContentLines = 0
for _, groupName in ipairs(aclGroups) do
local playersInGroup = groupPlayers[groupName]
if playersInGroup and #playersInGroup > 0 then
totalContentLines = totalContentLines + 1 -- Account for the group header line
totalContentLines = totalContentLines + #playersInGroup -- Account for each player line in the group
end
end
-- Iterate through ACL groups in the predefined order to maintain display consistency
for _, groupName in ipairs(aclGroups) do
local playersInGroup = groupPlayers[groupName]
if playersInGroup and #playersInGroup > 0 then
-- Check if the group header line is within the visible scroll range
if currentLineIndex >= scrollOffset and currentLineIndex < scrollOffset + maxVisibleLines then
dxDrawText("[" .. groupName .. "]", panelX + screenW * 0.01, drawY, panelX + panelWidth - screenW * 0.01, drawY + lineHeight, tocolor(80, 180, 255), 1, font, "left", "center", false, false, true)
drawY = drawY + lineHeight -- Move Y down for the next line
end
currentLineIndex = currentLineIndex + 1 -- Increment line index for the group header
-- Iterate through players in the current group
for _, player in ipairs(playersInGroup) do
-- Check if the player's line is within the visible scroll range
if currentLineIndex >= scrollOffset and currentLineIndex < scrollOffset + maxVisibleLines then
local ping = getPlayerPing(player)
local fps = getElementData(player, "fps") or "?" -- Get FPS, default to "?" if not available
local id = getElementData(player, "playerid") or getElementID(player) -- Prefer custom player ID, fallback to element ID
local nick = getPlayerName(player):gsub("#%x%x%x%x%x%x", "") -- Get player name and remove color codes
local team = getPlayerTeam(player)
local teamName = team and getTeamName(team) or "Sem Equipe" -- Get team name, default to "Sem Equipe" if no team
-- Check if client is downloading resources
local downloading = getElementData(player, "isClientDownloading") and "Baixando" or "Completo"
-- Define column widths as percentages of the panel width for flexible layout
local col1Width = panelWidth * 0.12 -- ID column
local col2Width = panelWidth * 0.28 -- Nickname column
local col3Width = panelWidth * 0.15 -- Downloading status column
local col4Width = panelWidth * 0.12 -- FPS column
local col5Width = panelWidth * 0.12 -- Ping column
local col6Width = panelWidth * 0.21 -- Team column (remaining width)
local currentX = panelX + screenW * 0.01 -- Starting X position for the first column (with padding)
-- Draw player details in columns
dxDrawText("ID: " .. id, currentX, drawY, currentX + col1Width, drawY + lineHeight, tocolor(255, 255, 255), 1, font, "left", "center", false, false, true)
currentX = currentX + col1Width
dxDrawText(nick, currentX, drawY, currentX + col2Width, drawY + lineHeight, tocolor(200, 200, 200), 1, font, "left", "center", false, false, true)
currentX = currentX + col2Width
dxDrawText(downloading, currentX, drawY, currentX + col3Width, drawY + lineHeight, tocolor(255, 255, 100), 1, font, "left", "center", false, false, true)
currentX = currentX + col3Width
dxDrawText("FPS: " .. fps, currentX, drawY, currentX + col4Width, drawY + lineHeight, tocolor(100, 255, 100), 1, font, "left", "center", false, false, true)
currentX = currentX + col4Width
dxDrawText("Ping: " .. ping, currentX, drawY, currentX + col5Width, drawY + lineHeight, tocolor(255, 150, 150), 1, font, "left", "center", false, false, true)
currentX = currentX + col5Width
dxDrawText(teamName, currentX, drawY, currentX + col6Width, drawY + lineHeight, tocolor(150, 150, 255), 1, font, "left", "center", false, false, true)
drawY = drawY + lineHeight -- Move Y down for the next player line
end
currentLineIndex = currentLineIndex + 1 -- Increment line index for the player
end
end
end
-- Adjust scrollOffset to ensure it stays within valid bounds
-- It cannot be less than 0, and cannot exceed the maximum scrollable content
scrollOffset = math.min(scrollOffset, math.max(0, totalContentLines - maxVisibleLines))
scrollOffset = math.max(0, scrollOffset)
end
addEventHandler("onClientRender", root, drawPanel)
-- Key binding for toggling the panel visibility with the "tab" key
bindKey("tab", "both", function()
panelVisible = not panelVisible
showCursor(panelVisible) -- Show/hide mouse cursor based on panel visibility
if panelVisible then
scrollOffset = 0 -- Reset scroll position to top when opening the panel
updateGroups() -- Force an immediate update of player data when opening
end
end)
-- Event handler for mouse wheel scrolling when the panel is visible
addEventHandler("onClientKey", root, function(key, press)
if not panelVisible then return end -- Only process scroll if panel is visible
-- Recalculate total content lines to ensure accurate scroll limits
local totalContentLines = 0
for _, groupName in ipairs(aclGroups) do
local playersInGroup = groupPlayers[groupName]
if playersInGroup and #playersInGroup > 0 then
totalContentLines = totalContentLines + 1 -- For group header
totalContentLines = totalContentLines + #playersInGroup -- For each player
end
end
if key == "mouse_wheel_up" and press then
scrollOffset = math.max(0, scrollOffset - 1) -- Scroll up, ensuring not to go below 0
elseif key == "mouse_wheel_down" and press then
-- Scroll down, ensuring not to go past the end of content
scrollOffset = math.min(scrollOffset + 1, math.max(0, totalContentLines - maxVisibleLines))
end
end)
-- Add an event handler to perform an initial update of player groups when the resource starts
addEventHandler("onClientResourceStart", resourceRoot, updateGroups)