Jump to content

مود الافك


Recommended Posts

9 hours ago, Jack Tom said:

شباب ولا مود اشتغل --__--

 

 

9 hours ago, Killer Project said:

@Jack Tom

سوي ملف جديد سيرفر وميتا وضيف ذا بملف السيرفر

 


-- server

exports.scoreboard:addScoreboardColumn( 'AFK' )
function killerProjectScoreboard ( )

    for _, v in pairs( getElementsByType( "player" ) ) do

        if getElementData ( v,"AFKstats" ) == "AFK" then
            setElementData( v, "AFK" , "AFK" )
        elseif getElementData ( v,"AFKstats" ) == "notAFK" then
            setElementData( v, "AFK" , "" )
        end

    end

end
addEventHandler("onElementDataChange",root, killerProjectScoreboard )

for _, v in pairs( getElementsByType( "player" ) ) do

    setElementData( v, "AFKstats" , "notAFK" )

end

function killerProjectAFKstats ( player )

    if getElementData ( player,"AFKstats" ) == "AFK" then
        setElementData ( player,"AFKstats","notAFK" )
        outputChatBox ( "you are now not afk", player )
    elseif getElementData ( player,"AFKstats" ) == "notAFK" then
        setElementData ( player,"AFKstats","AFK" )
        outputChatBox ( "you are now afk", player )
    end

end

addCommandHandler ( "AFK", killerProjectAFKstats )
addCommandHandler ( "afk", killerProjectAFKstats )



@#BrosS sorry bross :D



طبق اللي قلت عليه .. ترا مجربه الحين ذذ

Link to comment
9 hours ago, Jack Tom said:

اعمل /afk
ولا اسيبو فترة |؟

بص اعمل ملف meta.xml
واعمل ملف server.lua
ضيف ملف السيرفر داخل الميتا طبيعي

وضيف الكود اللي ارسلته لك في ملف سيرفر
واكتب في اف 8
afk او AFK
اذا كنت افك مارح تكون افك واذا ما كنت افك رح تكون افك

Link to comment
Just now, Killer Project said:

بص اعمل ملف meta.xml
واعمل ملف server.lua
ضيف ملف السيرفر داخل الميتا طبيعي

وضيف الكود اللي ارسلته لك في ملف سيرفر
واكتب في اف 8
afk او AFK
اذا كنت افك مارح تكون افك واذا ما كنت افك رح تكون افك

بس برضو ما بيظهر في تاب

Link to comment
9 hours ago, Jack Tom said:

<meta>
	<info author="TEst" name="AFK Script" version="1.0.0" type="script"/>
		
	<script src="server.lua" type="server" />
</meta>

اهوز

المشكلة من عندك والله اعلم .. لأني جربت المود وشغال طبيعي

بس للتأكيد على ملف ميتا


 

<meta>

<script src="server.lua" type="server" />

</meta>


غير كدة اكتب في اف 8
debugscript 3

واكتب ايه المشاكل اللي بتطلع لك

Link to comment
Just now, Master_MTA said:

انت حياه واقعيه اطرح سكوربورد حقك

--
-- vgScoreboard v1.0
-- Client-side script.
-- By Alberto "ryden" Alonso
--

--[[ Configuration ]]--
local SCOREBOARD_WIDTH				= 460				-- The scoreboard window width
local SCOREBOARD_HEIGHT				= 500				-- The scoreboard window height
local SCOREBOARD_HEADER_HEIGHT		= 30				-- Height for the header in what you can see the server info
local SCOREBOARD_TOGGLE_CONTROL		= "tab"				-- Control/Key to toggle the scoreboard visibility
local SCOREBOARD_PGUP_CONTROL		= "mouse_wheel_up"	-- Control/Key to move one page up
local SCOREBOARD_PGDN_CONTROL		= "mouse_wheel_down"-- Control/Key to move one page down
local SCOREBOARD_DISABLED_CONTROLS	= { "next_weapon",	-- Controls that are disabled when the scoreboard is showing
										"previous_weapon",
										"aim_weapon",
										"radio_next",
										"radio_previous" }
local SCOREBOARD_TOGGLE_TIME		= 200				-- Time in miliseconds to make the scoreboard (dis)appear
local SCOREBOARD_POSTGUI			= true				-- Set to true if it must be drawn over the GUI
local SCOREBOARD_INFO_BACKGROUND	= { 0, 0, 0, 150 }			-- RGBA color for the info header background
local SCOREBOARD_SERVER_NAME_COLOR	= { 255, 255, 255, 255 }		-- RGBA color for the server name text
local SCOREBOARD_PLAYERCOUNT_COLOR	= { 255, 255, 255, 255 }	-- RGBA color for the server player count text
local SCOREBOARD_BACKGROUND			= { 0, 0, 0, 140 }			-- RGBA color for the background
local SCOREBOARD_BACKGROUND_IMAGE	= { 255, 255, 255, 40 }		-- RGBA color for the background image
local SCOREBOARD_HEADERS_COLOR		= { 255, 255, 255, 180 }	-- RGBA color for the headers
local SCOREBOARD_SEPARATOR_COLOR	= { 82, 82, 82, 140 }		-- RGBA color for the separator line between headers and body content
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_FOREGROUND	= { 255, 255, 255, 255 }		-- RGBA color for the scroll foreground
local SCOREBOARD_SCROLL_HEIGHT		= 40						-- Size for the scroll marker
local SCOREBOARD_COLUMNS_WIDTH		= { 0.08, 0.57, 0.2, 0.14, 0.02 }	-- Relative width for each column: id, player name, ping and scroll position
local SCOREBOARD_ROW_GAP			= 1							-- Gap between rows

--[[ Uncomment to test with dummies ]]--
--[[
local _getPlayerName = getPlayerName
local _getPlayerPing = getPlayerPing
local _getPlayerNametagColor = getPlayerNametagColor

function getPlayerName ( player )
	if getElementType ( player ) == "player" then return _getPlayerName ( player ) end
	return getElementData ( player, "name" )
end

function getPlayerPing ( player )
	if getElementType ( player ) == "player" then return _getPlayerPing ( player ) end
	return getElementData ( player, "ping" )
end

function getPlayerNametagColor ( player )
	if getElementType ( player ) == "player" then return _getPlayerNametagColor ( player )
	else return unpack(getElementData(player, "color")) end
end
--]]


--[[ Global variables to this context ]]--
local g_isShowing = false		-- Marks if the scoreboard is showing
local g_currentWidth = 0		-- Current window width. Used for the fade in/out effect.
local g_currentHeight = 0		-- Current window height. Used for the fade in/out effect.
local g_scoreboardDummy			-- Will contain the scoreboard dummy element to gather info from.
local g_windowSize = { guiGetScreenSize () }	-- The window size
local g_localPlayer = getLocalPlayer ()			-- The local player...
local g_currentPage = 0			-- The current scroll page
local g_players					-- We will keep a cache of the conected player list
local g_oldControlStates		-- To save the old control states before disabling them for scrolling

--[[ Pre-calculate some stuff ]]--
-- Scoreboard position
local SCOREBOARD_X = math.floor ( ( g_windowSize[1] - SCOREBOARD_WIDTH ) / 2 )
local SCOREBOARD_Y = math.floor ( ( g_windowSize[2] - SCOREBOARD_HEIGHT ) / 2 )
-- Scoreboard colors
SCOREBOARD_INFO_BACKGROUND = tocolor ( unpack ( SCOREBOARD_INFO_BACKGROUND ) )
SCOREBOARD_SERVER_NAME_COLOR = tocolor ( unpack ( SCOREBOARD_SERVER_NAME_COLOR ) )
SCOREBOARD_PLAYERCOUNT_COLOR = tocolor ( unpack ( SCOREBOARD_PLAYERCOUNT_COLOR ) )
SCOREBOARD_BACKGROUND = tocolor ( unpack ( SCOREBOARD_BACKGROUND ) )
SCOREBOARD_BACKGROUND_IMAGE = tocolor ( unpack ( SCOREBOARD_BACKGROUND_IMAGE ) )
SCOREBOARD_HEADERS_COLOR = tocolor ( unpack ( SCOREBOARD_HEADERS_COLOR ) )
SCOREBOARD_SCROLL_BACKGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_BACKGROUND ) )
SCOREBOARD_SCROLL_FOREGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_FOREGROUND ) )
SCOREBOARD_SEPARATOR_COLOR = tocolor ( unpack ( SCOREBOARD_SEPARATOR_COLOR ) )
-- Columns width in absolute units
for k=1,#SCOREBOARD_COLUMNS_WIDTH do
	SCOREBOARD_COLUMNS_WIDTH[k] = math.floor ( SCOREBOARD_COLUMNS_WIDTH[k] * SCOREBOARD_WIDTH )
end
-- Pre-calculate each row horizontal bounding box.
local rowsBoundingBox = { { SCOREBOARD_X, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }
-- ID
rowsBoundingBox[1][2] = SCOREBOARD_X + SCOREBOARD_COLUMNS_WIDTH[1]
-- Name
rowsBoundingBox[2][1] = rowsBoundingBox[1][2]
rowsBoundingBox[2][2] = rowsBoundingBox[2][1] + SCOREBOARD_COLUMNS_WIDTH[2]
-- Hoursplayed
rowsBoundingBox[3][1] = rowsBoundingBox[2][2]
rowsBoundingBox[3][2] = rowsBoundingBox[3][1] + SCOREBOARD_COLUMNS_WIDTH[3]
-- Ping
rowsBoundingBox[4][1] = rowsBoundingBox[3][2]
rowsBoundingBox[4][2] = rowsBoundingBox[4][1] + SCOREBOARD_COLUMNS_WIDTH[4]
-- Scrollbar
rowsBoundingBox[5][1] = rowsBoundingBox[4][2]
rowsBoundingBox[5][2] = SCOREBOARD_X + SCOREBOARD_WIDTH


--[[ Pre-declare some functions ]]--
local onRender
local fadeScoreboard
local drawBackground
local drawScoreboard


--[[
* clamp
Clamps a value into a range.
--]]
local function clamp ( valueMin, current, valueMax )
	if current < valueMin then
		return valueMin
	elseif current > valueMax then
		return valueMax
	else
		return current
	end
end

--[[
* createPlayerCache
Generates a new player cache.
--]]
local function createPlayerCache ( ignorePlayer )
	-- Optimize the function in case of not having to ignore a player
	if ignorePlayer then
		-- Clear the gloal table
		g_players = {}
		
		-- Get the list of connected players
		local players = getElementsByType ( "player" )
	
		-- Dump them to the global table
		for k, player in ipairs(players) do
			if ignorePlayer ~= player then
				table.insert ( g_players, player )
			end
		end
	else
		g_players = getElementsByType ( "player" )
	end
	
	--[[ Uncomment to test with dummies ]]--
	--[[
	for k,v in ipairs(getElementsByType("playerDummy")) do
		table.insert(g_players, v)
	end
	--]]
	
	-- Sort the player list by their ID, giving priority to the local player
	table.sort ( g_players, function ( a, b )
		local idA = getElementData ( a, "playerid" ) or 0
		local idB = getElementData ( b, "playerid" ) or 0

		-- Perform the checks to always set the local player at the beggining
		if a == g_localPlayer then
			idA = -1
		elseif b == g_localPlayer then
			idB = -1
		end
		
		return tonumber(idA) < tonumber(idB)
	end )
end

--[[
* onClientResourceStart
Handles the resource start event to create the initial player cache
--]]
addEventHandler ( "onClientResourceStart", getResourceRootElement(getThisResource()), function ()
	createPlayerCache ()
end, false )

--[[
* onClientElementDataChange
Handles the element data changes event to update the player cache
if the playerid was changed.
--]]
addEventHandler ( "onClientElementDataChange", root, function ( dataName, dataValue )
	if dataName == "playerid" then
		createPlayerCache ()
	end
end )

--[[
* onClientPlayerQuit
Handles the player quit event to update the player cache.
--]]
addEventHandler ( "onClientPlayerQuit", root, function ()
	createPlayerCache ( source )
end )

--[[
* toggleScoreboard
Toggles the visibility of the scoreboard.
--]]
local function toggleScoreboard ( show )
	if not getControlState( 'aim_weapon' ) then
		-- Force the parameter to be a boolean
		local show = show == true
		
		-- Check if the status has changed
		if show ~= g_isShowing then
			g_isShowing = show
			
			if g_isShowing and g_currentWidth == 0 and g_currentHeight == 0 then
				-- Handle the onClientRender event to start drawing the scoreboard.
				addEventHandler ( "onClientPreRender", root, onRender, false )
			end
			
			-- Little hack to avoid switching weapons while moving through the scoreboard pages.
			if g_isShowing then
				g_oldControlStates = {}
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					g_oldControlStates[k] = isControlEnabled ( control )
					toggleControl ( control, false )
				end
			else
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					toggleControl ( control, g_oldControlStates[k] )
				end
				g_oldControlStates = nil
			end
		end
	end
end

--[[
* onToggleKey
Function to bind to the appropiate key the function to toggle the scoreboard visibility.
--]]
local function onToggleKey ( key, keyState )
	-- Check if the scoreboard element has been created
	if not g_scoreboardDummy then
		local elementTable = getElementsByType ( "scoreboard" )
		if #elementTable > 0 then
			g_scoreboardDummy = elementTable[1]
		else
			return
		end
	end
	
	-- Toggle the scoreboard, and check that it's allowed.
	toggleScoreboard ( keyState == "down" and getElementData ( g_scoreboardDummy, "allow" ) )
end
bindKey ( SCOREBOARD_TOGGLE_CONTROL, "both", onToggleKey )

--[[
* onScrollKey
Function to bind to the appropiate key the function to change the current page.
--]]
local function onScrollKey ( direction )
	if g_isShowing then
		if direction then
			g_currentPage = g_currentPage + 1
		else
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then
				g_currentPage = 0
			end
		end
	end
end
bindKey ( SCOREBOARD_PGUP_CONTROL, "down", function () onScrollKey ( false ) end )
bindKey ( SCOREBOARD_PGDN_CONTROL, "down", function () onScrollKey ( true ) end )

--[[
* onRender
Event handler for onClientPreRender. It will forward the flow to the most appropiate
function: fading-in, fading-out or drawScoreboard.
--]]
onRender = function ( timeshift )
	-- Boolean to check if we must draw the scoreboard.
	local drawIt = false
	
	if g_isShowing then
		-- Check if the scoreboard has been disallowed
		if not getElementData ( g_scoreboardDummy, "allow" ) then
			toggleScoreboard ( false )
		-- If it's showing, check if it got fully faded in. Else, draw it normally.
		elseif g_currentWidth < SCOREBOARD_WIDTH or g_currentHeight < SCOREBOARD_HEIGHT then
			drawIt = fadeScoreboard ( timeshift, 1 )
		else
			-- Allow drawing the full scoreboard
			drawIt = true
		end
	else
		-- If it shouldn't be showing, make another step to fade it out.
		drawIt = fadeScoreboard ( timeshift, -1 )
	end
	
	-- Draw the scoreboard if allowed.
	if drawIt then
		drawScoreboard ()
	end
end

--[[
* fadeScoreboard
Makes a step of the fade effect. Gets a multiplier to make it either fading in or out.
--]]
fadeScoreboard = function ( timeshift, multiplier )
	-- Get the percentage of the final size that it should grow for this step.
	local growth = ( timeshift / SCOREBOARD_TOGGLE_TIME ) * multiplier
	
	-- Apply the growth to the scoreboard size
	g_currentWidth = clamp ( 0, g_currentWidth + ( SCOREBOARD_WIDTH * growth ), SCOREBOARD_WIDTH )
	g_currentHeight = clamp ( 0, g_currentHeight + ( SCOREBOARD_HEIGHT * growth ), SCOREBOARD_HEIGHT )
	
	-- Check if the scoreboard has collapsed. If so, unregister the onClientRender event.
	if g_currentWidth == 0 or g_currentHeight == 0 then
		g_currentWidth = 0
		g_currentHeight = 0
		removeEventHandler ( "onClientPreRender", root, onRender )
		return false
	else
		return true
	end
end

--[[
* drawBackground
Draws the scoreboard background.
--]]
drawBackground = function ()

	dxDrawImage(SCOREBOARD_X, SCOREBOARD_Y, g_currentWidth, g_currentHeight, ":hud/images/hud/box.png")
	
end

--[[
* drawRowBounded
Draws a scoreboard body row with the pre-calculated row bounding boxes.
--]]
local function drawRowBounded ( id, name, hours, ping, colors, font, top )
	-- Precalculate some constants
	local bottom = clamp ( 0, top + dxGetFontHeight ( 1, font ), SCOREBOARD_Y + g_currentHeight )
	local maxWidth = SCOREBOARD_X + g_currentWidth
	
	-- If the row doesn't fit, just avoid any further calculations.
	if bottom < top then return end
	
	-- ID
	local left = rowsBoundingBox[1][1]
	local right = clamp ( 0, rowsBoundingBox[1][2], maxWidth )
	if left < right then
		dxDrawText ( id, left, top, right, bottom,
					 colors[1], 1, font, "right", "top",
					 true, false, SCOREBOARD_POSTGUI )
		
		-- Name
		left = rowsBoundingBox[2][1] + 17 -- Grant some padding to the name column
		right = clamp ( 0, rowsBoundingBox[2][2], maxWidth )
		if left < right then
			dxDrawText ( name, left, top, right, bottom,
						 colors[2], 1, font, "left", "top",
						 true, false, SCOREBOARD_POSTGUI )
			
			-- Hoursplayed
			left = rowsBoundingBox[3][1]
			right = clamp ( 0, rowsBoundingBox[3][2], maxWidth )
			--outputDebugString(left.." vs ".. right)
			if left < right then
				dxDrawText ( hours, left, top, right, bottom,
							 colors[3], 1, font, "left", "top",
							 true, false, SCOREBOARD_POSTGUI )
				-- Ping
				left = rowsBoundingBox[4][1]
				right = clamp ( 0, rowsBoundingBox[4][2], maxWidth )
				--outputDebugString(left.." vs ".. right)
				if left < right then
					dxDrawText ( ping, left, top, right, bottom,
								 colors[3], 1, font, "left", "top",
								 true, false, SCOREBOARD_POSTGUI )
				end
			end
			

		end
	end
end

--[[
* drawScrollBar
Draws the scroll bar. Position ranges from 0 to 1.
--]]
local function drawScrollBar ( top, position )
	-- Get the bounding box
	local left = rowsBoundingBox[5][1]
	local right = clamp ( 0, rowsBoundingBox[5][2], SCOREBOARD_X + g_currentWidth )
	local bottom = clamp ( 0, SCOREBOARD_Y + SCOREBOARD_HEIGHT, SCOREBOARD_Y + g_currentHeight )
	
	-- Make sure that it'd be visible.
	if left < right and top < bottom then
		-- Draw the background
		dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_BACKGROUND, SCOREBOARD_POSTGUI )
		
		-- Get the current Y position for the scroll marker
		local top = top + position * ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - SCOREBOARD_SCROLL_HEIGHT - top )
		bottom = clamp ( 0, top + SCOREBOARD_SCROLL_HEIGHT, SCOREBOARD_Y + g_currentHeight )
		
		-- Make sure that it'd be visible
		if top < bottom then
			dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_FOREGROUND, SCOREBOARD_POSTGUI )
		end
	end
end

function makeFont()
	if not theFont then
		theFont = dxCreateFont ( ':resources/cartwheel.otf' )
	end
	return theFont
end


--[[
* drawScoreboard
Draws the scoreboard contents.
--]]
drawScoreboard = function ()
	-- Check that we got the list of players
	if not g_players then return end

	-- First draw the background
	drawBackground ()
	
	-- Get the server information
	local serverName = getElementData ( g_scoreboardDummy, "serverName" ) or "MTA server"
	local maxPlayers = getElementData ( root, "server:Slots" ) or 0
	serverName = tostring ( serverName )
	maxPlayers = tonumber ( maxPlayers )
	
	-- Render the header
	-- Calculate the bounding box for the header texts
	local left, top, right, bottom = SCOREBOARD_X + 2, SCOREBOARD_Y + 2, SCOREBOARD_X + g_currentWidth - 2, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT - 2
	
	-- Render the server name
	dxDrawText ( serverName, left, top, right, bottom,
				 SCOREBOARD_SERVER_NAME_COLOR, 1, makeFont() or "default-bold", "center", "center",
				 true, false, SCOREBOARD_POSTGUI )


	-- Render the player count
	local usagePercent = (#g_players / maxPlayers) * 100
	local strPlayerCount = "Players: " .. tostring(#g_players) .. "/" .. tostring(maxPlayers) .. " (" .. math.floor(usagePercent + 0.5) .. "%)"
	
	-- We need to recalculate the left position, to make it not move when fading.
	local offset = SCOREBOARD_WIDTH - dxGetTextWidth ( strPlayerCount, 1, makeFont() or "default" ) - 4
	left = left + offset
	-- Make sure of that it needs to be rendered now
	
	-- Draw the body.
	-- Update the bounding box.
	left, top, bottom = SCOREBOARD_X, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + 2, SCOREBOARD_Y + g_currentHeight - 2

	-- Pre-calculate how much height will each row have.
	local rowHeight = dxGetFontHeight ( 1, "default-bold" )
	
	-- Draw the headers
	drawRowBounded ( "ID", "Player Name", "Hoursplayed", "Ping",
					 { SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR },
					 "default-bold", top )
	
				 
	-- Add the offset for a new row
	top = top + rowHeight + 3
	
	-- Draw the separator
	right = clamp ( 0, rowsBoundingBox[4][2] - 5, SCOREBOARD_X + g_currentWidth )
	if top < SCOREBOARD_Y + g_currentHeight then
		dxDrawLine ( SCOREBOARD_X + 5, top, right, top, SCOREBOARD_SEPARATOR_COLOR, 1, SCOREBOARD_POSTGUI )
	end
	top = top + 3
	
	-- Create a function to render a player entry
	local renderEntry = function ( player, seeUsername )
		-- Get the player data
		local playerID = getElementData ( player, "playerid" ) or 0
		playerID = tostring ( playerID )
		local playerUsername = ""
		if exports.integration:isPlayerTrialAdmin(getLocalPlayer()) or exports.integration:isPlayerSupporter(getLocalPlayer()) then
			local uname = getElementData( player, 'account:username' )
			playerUsername = uname and (" ("..uname..")") or ""
		end
		local playerName = exports.global:getPlayerName( player )..playerUsername
		local playerHours = getElementData( player, 'hoursplayed' ) or 0
		local playerPing = getPlayerPing ( player )
		playerPing = tostring ( playerPing )
		local r, g, b = getPlayerNametagColor ( player )
		local playerColor = tocolor ( r, g, b, 255 )
		
		-- Create the table of colors
		local colors = { playerColor, playerColor, playerColor, playerColor }
		
		-- Render it!
		drawRowBounded ( playerID, playerName, playerHours, playerPing, colors, "default-bold", top )
	end
	
	-- Calculate how much players can fit in the body window.
	local playersPerPage = math.floor ( ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - top ) / ( rowHeight + SCOREBOARD_ROW_GAP ) )
	
	-- Get the amount of shifted players per page
	local playerShift = math.floor ( playersPerPage / 2 )
	
	-- Get the number of players to skip
	local playersToSkip = playerShift * g_currentPage
	if (#g_players - playersToSkip) < playersPerPage then
		-- Check that they didn't go to an invalid page
		if (#g_players - playersToSkip) < playerShift then
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then g_currentPage = 0 end
		end

		-- Try to always fill pages
		playersToSkip = #g_players - playersPerPage + 1
	end
	
	-- Check for when there are too few players to fill one page.
	if playersToSkip < 0 then
		playersToSkip = 0
	end

	local isStaffOnDuty = exports.global:isStaffOnDuty( localPlayer )

	-- For every player in the cache, render a new entry.
	for k=playersToSkip + 1, #g_players do
		local player = g_players [ k ]
		local hasPerk, perkValue = exports.donators:hasPlayerPerk(player, 12)
		if not (hasPerk and tonumber(perkValue) == 1) or isStaffOnDuty then
			-- Check if it's gonna fit. If it doesn't stop rendering.
			if top < bottom - rowHeight - SCOREBOARD_ROW_GAP then
				renderEntry ( player, isStaffOnDuty )
				-- Update the height for the next entry
				top = top + rowHeight + SCOREBOARD_ROW_GAP
			else break end
		end
	end
	
	-- Draw the scrollbar. The maximum players to skip is #g_players - playersPerPage + 1, so when
	-- the scoreboard is fully scrolled it will become 1, while when it's not scrolled it will be
	-- 0 due to playersToSkip being 0.
	drawScrollBar ( SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + rowHeight + 10, playersToSkip / ( #g_players - playersPerPage + 1 ) )
end

--[[
* isVisible
Returns wherever or not the scoreboard is visible
--]]
function isVisible ( )
	return g_isShowing
end

ده الكلنت
 

--
-- vgScoreboard v1.0
-- Server-side script.
-- By Alberto "ryden" Alonso
--


local scoreboardDummy

--[[
* onResourceStart
Handles the resource start event to create a dummy entity with information about the server.
--]]
addEventHandler ( "onResourceStart", getResourceRootElement(getThisResource()), function ()
	scoreboardDummy = createElement ( "scoreboard" )
	setElementData ( scoreboardDummy, "serverName", "ALG-Adiga Live Gaming" )
	setElementData ( scoreboardDummy, "maxPlayers", getMaxPlayers () )
	setElementData ( scoreboardDummy, "allow", true )
	
	--[[ Uncomment to test with dummies ]]--
	--[[
	for k=70,270 do
		local dummy = createElement ( "playerDummy" )
		setElementData ( dummy, "playerid", k )
		setElementData ( dummy, "name", "dummy" .. tostring(k), false )
		setElementData ( dummy, "ping", math.random ( 1, 300 ) )
		setElementData ( dummy, "color", { math.random(0,255), math.random(0,255), math.random(0,255) } )
	end
	--]]
end, false )

--[[
* onResourceStop
Delete the dummy created on resource start.
--]]
addEventHandler ( "onResourceStop", getResourceRootElement(getThisResource()), function ()
	if scoreboardDummy then
		destroyElement ( scoreboardDummy )
	end
end, false )

ده السيرفر

Link to comment
1 minute ago, Jack Tom said:

--
-- vgScoreboard v1.0
-- Client-side script.
-- By Alberto "ryden" Alonso
--

--[[ Configuration ]]--
local SCOREBOARD_WIDTH				= 460				-- The scoreboard window width
local SCOREBOARD_HEIGHT				= 500				-- The scoreboard window height
local SCOREBOARD_HEADER_HEIGHT		= 30				-- Height for the header in what you can see the server info
local SCOREBOARD_TOGGLE_CONTROL		= "tab"				-- Control/Key to toggle the scoreboard visibility
local SCOREBOARD_PGUP_CONTROL		= "mouse_wheel_up"	-- Control/Key to move one page up
local SCOREBOARD_PGDN_CONTROL		= "mouse_wheel_down"-- Control/Key to move one page down
local SCOREBOARD_DISABLED_CONTROLS	= { "next_weapon",	-- Controls that are disabled when the scoreboard is showing
										"previous_weapon",
										"aim_weapon",
										"radio_next",
										"radio_previous" }
local SCOREBOARD_TOGGLE_TIME		= 200				-- Time in miliseconds to make the scoreboard (dis)appear
local SCOREBOARD_POSTGUI			= true				-- Set to true if it must be drawn over the GUI
local SCOREBOARD_INFO_BACKGROUND	= { 0, 0, 0, 150 }			-- RGBA color for the info header background
local SCOREBOARD_SERVER_NAME_COLOR	= { 255, 255, 255, 255 }		-- RGBA color for the server name text
local SCOREBOARD_PLAYERCOUNT_COLOR	= { 255, 255, 255, 255 }	-- RGBA color for the server player count text
local SCOREBOARD_BACKGROUND			= { 0, 0, 0, 140 }			-- RGBA color for the background
local SCOREBOARD_BACKGROUND_IMAGE	= { 255, 255, 255, 40 }		-- RGBA color for the background image
local SCOREBOARD_HEADERS_COLOR		= { 255, 255, 255, 180 }	-- RGBA color for the headers
local SCOREBOARD_SEPARATOR_COLOR	= { 82, 82, 82, 140 }		-- RGBA color for the separator line between headers and body content
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_FOREGROUND	= { 255, 255, 255, 255 }		-- RGBA color for the scroll foreground
local SCOREBOARD_SCROLL_HEIGHT		= 40						-- Size for the scroll marker
local SCOREBOARD_COLUMNS_WIDTH		= { 0.08, 0.57, 0.2, 0.14, 0.02 }	-- Relative width for each column: id, player name, ping and scroll position
local SCOREBOARD_ROW_GAP			= 1							-- Gap between rows

--[[ Uncomment to test with dummies ]]--
--[[
local _getPlayerName = getPlayerName
local _getPlayerPing = getPlayerPing
local _getPlayerNametagColor = getPlayerNametagColor

function getPlayerName ( player )
	if getElementType ( player ) == "player" then return _getPlayerName ( player ) end
	return getElementData ( player, "name" )
end

function getPlayerPing ( player )
	if getElementType ( player ) == "player" then return _getPlayerPing ( player ) end
	return getElementData ( player, "ping" )
end

function getPlayerNametagColor ( player )
	if getElementType ( player ) == "player" then return _getPlayerNametagColor ( player )
	else return unpack(getElementData(player, "color")) end
end
--]]


--[[ Global variables to this context ]]--
local g_isShowing = false		-- Marks if the scoreboard is showing
local g_currentWidth = 0		-- Current window width. Used for the fade in/out effect.
local g_currentHeight = 0		-- Current window height. Used for the fade in/out effect.
local g_scoreboardDummy			-- Will contain the scoreboard dummy element to gather info from.
local g_windowSize = { guiGetScreenSize () }	-- The window size
local g_localPlayer = getLocalPlayer ()			-- The local player...
local g_currentPage = 0			-- The current scroll page
local g_players					-- We will keep a cache of the conected player list
local g_oldControlStates		-- To save the old control states before disabling them for scrolling

--[[ Pre-calculate some stuff ]]--
-- Scoreboard position
local SCOREBOARD_X = math.floor ( ( g_windowSize[1] - SCOREBOARD_WIDTH ) / 2 )
local SCOREBOARD_Y = math.floor ( ( g_windowSize[2] - SCOREBOARD_HEIGHT ) / 2 )
-- Scoreboard colors
SCOREBOARD_INFO_BACKGROUND = tocolor ( unpack ( SCOREBOARD_INFO_BACKGROUND ) )
SCOREBOARD_SERVER_NAME_COLOR = tocolor ( unpack ( SCOREBOARD_SERVER_NAME_COLOR ) )
SCOREBOARD_PLAYERCOUNT_COLOR = tocolor ( unpack ( SCOREBOARD_PLAYERCOUNT_COLOR ) )
SCOREBOARD_BACKGROUND = tocolor ( unpack ( SCOREBOARD_BACKGROUND ) )
SCOREBOARD_BACKGROUND_IMAGE = tocolor ( unpack ( SCOREBOARD_BACKGROUND_IMAGE ) )
SCOREBOARD_HEADERS_COLOR = tocolor ( unpack ( SCOREBOARD_HEADERS_COLOR ) )
SCOREBOARD_SCROLL_BACKGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_BACKGROUND ) )
SCOREBOARD_SCROLL_FOREGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_FOREGROUND ) )
SCOREBOARD_SEPARATOR_COLOR = tocolor ( unpack ( SCOREBOARD_SEPARATOR_COLOR ) )
-- Columns width in absolute units
for k=1,#SCOREBOARD_COLUMNS_WIDTH do
	SCOREBOARD_COLUMNS_WIDTH[k] = math.floor ( SCOREBOARD_COLUMNS_WIDTH[k] * SCOREBOARD_WIDTH )
end
-- Pre-calculate each row horizontal bounding box.
local rowsBoundingBox = { { SCOREBOARD_X, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }
-- ID
rowsBoundingBox[1][2] = SCOREBOARD_X + SCOREBOARD_COLUMNS_WIDTH[1]
-- Name
rowsBoundingBox[2][1] = rowsBoundingBox[1][2]
rowsBoundingBox[2][2] = rowsBoundingBox[2][1] + SCOREBOARD_COLUMNS_WIDTH[2]
-- Hoursplayed
rowsBoundingBox[3][1] = rowsBoundingBox[2][2]
rowsBoundingBox[3][2] = rowsBoundingBox[3][1] + SCOREBOARD_COLUMNS_WIDTH[3]
-- Ping
rowsBoundingBox[4][1] = rowsBoundingBox[3][2]
rowsBoundingBox[4][2] = rowsBoundingBox[4][1] + SCOREBOARD_COLUMNS_WIDTH[4]
-- Scrollbar
rowsBoundingBox[5][1] = rowsBoundingBox[4][2]
rowsBoundingBox[5][2] = SCOREBOARD_X + SCOREBOARD_WIDTH


--[[ Pre-declare some functions ]]--
local onRender
local fadeScoreboard
local drawBackground
local drawScoreboard


--[[
* clamp
Clamps a value into a range.
--]]
local function clamp ( valueMin, current, valueMax )
	if current < valueMin then
		return valueMin
	elseif current > valueMax then
		return valueMax
	else
		return current
	end
end

--[[
* createPlayerCache
Generates a new player cache.
--]]
local function createPlayerCache ( ignorePlayer )
	-- Optimize the function in case of not having to ignore a player
	if ignorePlayer then
		-- Clear the gloal table
		g_players = {}
		
		-- Get the list of connected players
		local players = getElementsByType ( "player" )
	
		-- Dump them to the global table
		for k, player in ipairs(players) do
			if ignorePlayer ~= player then
				table.insert ( g_players, player )
			end
		end
	else
		g_players = getElementsByType ( "player" )
	end
	
	--[[ Uncomment to test with dummies ]]--
	--[[
	for k,v in ipairs(getElementsByType("playerDummy")) do
		table.insert(g_players, v)
	end
	--]]
	
	-- Sort the player list by their ID, giving priority to the local player
	table.sort ( g_players, function ( a, b )
		local idA = getElementData ( a, "playerid" ) or 0
		local idB = getElementData ( b, "playerid" ) or 0

		-- Perform the checks to always set the local player at the beggining
		if a == g_localPlayer then
			idA = -1
		elseif b == g_localPlayer then
			idB = -1
		end
		
		return tonumber(idA) < tonumber(idB)
	end )
end

--[[
* onClientResourceStart
Handles the resource start event to create the initial player cache
--]]
addEventHandler ( "onClientResourceStart", getResourceRootElement(getThisResource()), function ()
	createPlayerCache ()
end, false )

--[[
* onClientElementDataChange
Handles the element data changes event to update the player cache
if the playerid was changed.
--]]
addEventHandler ( "onClientElementDataChange", root, function ( dataName, dataValue )
	if dataName == "playerid" then
		createPlayerCache ()
	end
end )

--[[
* onClientPlayerQuit
Handles the player quit event to update the player cache.
--]]
addEventHandler ( "onClientPlayerQuit", root, function ()
	createPlayerCache ( source )
end )

--[[
* toggleScoreboard
Toggles the visibility of the scoreboard.
--]]
local function toggleScoreboard ( show )
	if not getControlState( 'aim_weapon' ) then
		-- Force the parameter to be a boolean
		local show = show == true
		
		-- Check if the status has changed
		if show ~= g_isShowing then
			g_isShowing = show
			
			if g_isShowing and g_currentWidth == 0 and g_currentHeight == 0 then
				-- Handle the onClientRender event to start drawing the scoreboard.
				addEventHandler ( "onClientPreRender", root, onRender, false )
			end
			
			-- Little hack to avoid switching weapons while moving through the scoreboard pages.
			if g_isShowing then
				g_oldControlStates = {}
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					g_oldControlStates[k] = isControlEnabled ( control )
					toggleControl ( control, false )
				end
			else
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					toggleControl ( control, g_oldControlStates[k] )
				end
				g_oldControlStates = nil
			end
		end
	end
end

--[[
* onToggleKey
Function to bind to the appropiate key the function to toggle the scoreboard visibility.
--]]
local function onToggleKey ( key, keyState )
	-- Check if the scoreboard element has been created
	if not g_scoreboardDummy then
		local elementTable = getElementsByType ( "scoreboard" )
		if #elementTable > 0 then
			g_scoreboardDummy = elementTable[1]
		else
			return
		end
	end
	
	-- Toggle the scoreboard, and check that it's allowed.
	toggleScoreboard ( keyState == "down" and getElementData ( g_scoreboardDummy, "allow" ) )
end
bindKey ( SCOREBOARD_TOGGLE_CONTROL, "both", onToggleKey )

--[[
* onScrollKey
Function to bind to the appropiate key the function to change the current page.
--]]
local function onScrollKey ( direction )
	if g_isShowing then
		if direction then
			g_currentPage = g_currentPage + 1
		else
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then
				g_currentPage = 0
			end
		end
	end
end
bindKey ( SCOREBOARD_PGUP_CONTROL, "down", function () onScrollKey ( false ) end )
bindKey ( SCOREBOARD_PGDN_CONTROL, "down", function () onScrollKey ( true ) end )

--[[
* onRender
Event handler for onClientPreRender. It will forward the flow to the most appropiate
function: fading-in, fading-out or drawScoreboard.
--]]
onRender = function ( timeshift )
	-- Boolean to check if we must draw the scoreboard.
	local drawIt = false
	
	if g_isShowing then
		-- Check if the scoreboard has been disallowed
		if not getElementData ( g_scoreboardDummy, "allow" ) then
			toggleScoreboard ( false )
		-- If it's showing, check if it got fully faded in. Else, draw it normally.
		elseif g_currentWidth < SCOREBOARD_WIDTH or g_currentHeight < SCOREBOARD_HEIGHT then
			drawIt = fadeScoreboard ( timeshift, 1 )
		else
			-- Allow drawing the full scoreboard
			drawIt = true
		end
	else
		-- If it shouldn't be showing, make another step to fade it out.
		drawIt = fadeScoreboard ( timeshift, -1 )
	end
	
	-- Draw the scoreboard if allowed.
	if drawIt then
		drawScoreboard ()
	end
end

--[[
* fadeScoreboard
Makes a step of the fade effect. Gets a multiplier to make it either fading in or out.
--]]
fadeScoreboard = function ( timeshift, multiplier )
	-- Get the percentage of the final size that it should grow for this step.
	local growth = ( timeshift / SCOREBOARD_TOGGLE_TIME ) * multiplier
	
	-- Apply the growth to the scoreboard size
	g_currentWidth = clamp ( 0, g_currentWidth + ( SCOREBOARD_WIDTH * growth ), SCOREBOARD_WIDTH )
	g_currentHeight = clamp ( 0, g_currentHeight + ( SCOREBOARD_HEIGHT * growth ), SCOREBOARD_HEIGHT )
	
	-- Check if the scoreboard has collapsed. If so, unregister the onClientRender event.
	if g_currentWidth == 0 or g_currentHeight == 0 then
		g_currentWidth = 0
		g_currentHeight = 0
		removeEventHandler ( "onClientPreRender", root, onRender )
		return false
	else
		return true
	end
end

--[[
* drawBackground
Draws the scoreboard background.
--]]
drawBackground = function ()

	dxDrawImage(SCOREBOARD_X, SCOREBOARD_Y, g_currentWidth, g_currentHeight, ":hud/images/hud/box.png")
	
end

--[[
* drawRowBounded
Draws a scoreboard body row with the pre-calculated row bounding boxes.
--]]
local function drawRowBounded ( id, name, hours, ping, colors, font, top )
	-- Precalculate some constants
	local bottom = clamp ( 0, top + dxGetFontHeight ( 1, font ), SCOREBOARD_Y + g_currentHeight )
	local maxWidth = SCOREBOARD_X + g_currentWidth
	
	-- If the row doesn't fit, just avoid any further calculations.
	if bottom < top then return end
	
	-- ID
	local left = rowsBoundingBox[1][1]
	local right = clamp ( 0, rowsBoundingBox[1][2], maxWidth )
	if left < right then
		dxDrawText ( id, left, top, right, bottom,
					 colors[1], 1, font, "right", "top",
					 true, false, SCOREBOARD_POSTGUI )
		
		-- Name
		left = rowsBoundingBox[2][1] + 17 -- Grant some padding to the name column
		right = clamp ( 0, rowsBoundingBox[2][2], maxWidth )
		if left < right then
			dxDrawText ( name, left, top, right, bottom,
						 colors[2], 1, font, "left", "top",
						 true, false, SCOREBOARD_POSTGUI )
			
			-- Hoursplayed
			left = rowsBoundingBox[3][1]
			right = clamp ( 0, rowsBoundingBox[3][2], maxWidth )
			--outputDebugString(left.." vs ".. right)
			if left < right then
				dxDrawText ( hours, left, top, right, bottom,
							 colors[3], 1, font, "left", "top",
							 true, false, SCOREBOARD_POSTGUI )
				-- Ping
				left = rowsBoundingBox[4][1]
				right = clamp ( 0, rowsBoundingBox[4][2], maxWidth )
				--outputDebugString(left.." vs ".. right)
				if left < right then
					dxDrawText ( ping, left, top, right, bottom,
								 colors[3], 1, font, "left", "top",
								 true, false, SCOREBOARD_POSTGUI )
				end
			end
			

		end
	end
end

--[[
* drawScrollBar
Draws the scroll bar. Position ranges from 0 to 1.
--]]
local function drawScrollBar ( top, position )
	-- Get the bounding box
	local left = rowsBoundingBox[5][1]
	local right = clamp ( 0, rowsBoundingBox[5][2], SCOREBOARD_X + g_currentWidth )
	local bottom = clamp ( 0, SCOREBOARD_Y + SCOREBOARD_HEIGHT, SCOREBOARD_Y + g_currentHeight )
	
	-- Make sure that it'd be visible.
	if left < right and top < bottom then
		-- Draw the background
		dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_BACKGROUND, SCOREBOARD_POSTGUI )
		
		-- Get the current Y position for the scroll marker
		local top = top + position * ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - SCOREBOARD_SCROLL_HEIGHT - top )
		bottom = clamp ( 0, top + SCOREBOARD_SCROLL_HEIGHT, SCOREBOARD_Y + g_currentHeight )
		
		-- Make sure that it'd be visible
		if top < bottom then
			dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_FOREGROUND, SCOREBOARD_POSTGUI )
		end
	end
end

function makeFont()
	if not theFont then
		theFont = dxCreateFont ( ':resources/cartwheel.otf' )
	end
	return theFont
end


--[[
* drawScoreboard
Draws the scoreboard contents.
--]]
drawScoreboard = function ()
	-- Check that we got the list of players
	if not g_players then return end

	-- First draw the background
	drawBackground ()
	
	-- Get the server information
	local serverName = getElementData ( g_scoreboardDummy, "serverName" ) or "MTA server"
	local maxPlayers = getElementData ( root, "server:Slots" ) or 0
	serverName = tostring ( serverName )
	maxPlayers = tonumber ( maxPlayers )
	
	-- Render the header
	-- Calculate the bounding box for the header texts
	local left, top, right, bottom = SCOREBOARD_X + 2, SCOREBOARD_Y + 2, SCOREBOARD_X + g_currentWidth - 2, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT - 2
	
	-- Render the server name
	dxDrawText ( serverName, left, top, right, bottom,
				 SCOREBOARD_SERVER_NAME_COLOR, 1, makeFont() or "default-bold", "center", "center",
				 true, false, SCOREBOARD_POSTGUI )


	-- Render the player count
	local usagePercent = (#g_players / maxPlayers) * 100
	local strPlayerCount = "Players: " .. tostring(#g_players) .. "/" .. tostring(maxPlayers) .. " (" .. math.floor(usagePercent + 0.5) .. "%)"
	
	-- We need to recalculate the left position, to make it not move when fading.
	local offset = SCOREBOARD_WIDTH - dxGetTextWidth ( strPlayerCount, 1, makeFont() or "default" ) - 4
	left = left + offset
	-- Make sure of that it needs to be rendered now
	
	-- Draw the body.
	-- Update the bounding box.
	left, top, bottom = SCOREBOARD_X, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + 2, SCOREBOARD_Y + g_currentHeight - 2

	-- Pre-calculate how much height will each row have.
	local rowHeight = dxGetFontHeight ( 1, "default-bold" )
	
	-- Draw the headers
	drawRowBounded ( "ID", "Player Name", "Hoursplayed", "Ping",
					 { SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR },
					 "default-bold", top )
	
				 
	-- Add the offset for a new row
	top = top + rowHeight + 3
	
	-- Draw the separator
	right = clamp ( 0, rowsBoundingBox[4][2] - 5, SCOREBOARD_X + g_currentWidth )
	if top < SCOREBOARD_Y + g_currentHeight then
		dxDrawLine ( SCOREBOARD_X + 5, top, right, top, SCOREBOARD_SEPARATOR_COLOR, 1, SCOREBOARD_POSTGUI )
	end
	top = top + 3
	
	-- Create a function to render a player entry
	local renderEntry = function ( player, seeUsername )
		-- Get the player data
		local playerID = getElementData ( player, "playerid" ) or 0
		playerID = tostring ( playerID )
		local playerUsername = ""
		if exports.integration:isPlayerTrialAdmin(getLocalPlayer()) or exports.integration:isPlayerSupporter(getLocalPlayer()) then
			local uname = getElementData( player, 'account:username' )
			playerUsername = uname and (" ("..uname..")") or ""
		end
		local playerName = exports.global:getPlayerName( player )..playerUsername
		local playerHours = getElementData( player, 'hoursplayed' ) or 0
		local playerPing = getPlayerPing ( player )
		playerPing = tostring ( playerPing )
		local r, g, b = getPlayerNametagColor ( player )
		local playerColor = tocolor ( r, g, b, 255 )
		
		-- Create the table of colors
		local colors = { playerColor, playerColor, playerColor, playerColor }
		
		-- Render it!
		drawRowBounded ( playerID, playerName, playerHours, playerPing, colors, "default-bold", top )
	end
	
	-- Calculate how much players can fit in the body window.
	local playersPerPage = math.floor ( ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - top ) / ( rowHeight + SCOREBOARD_ROW_GAP ) )
	
	-- Get the amount of shifted players per page
	local playerShift = math.floor ( playersPerPage / 2 )
	
	-- Get the number of players to skip
	local playersToSkip = playerShift * g_currentPage
	if (#g_players - playersToSkip) < playersPerPage then
		-- Check that they didn't go to an invalid page
		if (#g_players - playersToSkip) < playerShift then
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then g_currentPage = 0 end
		end

		-- Try to always fill pages
		playersToSkip = #g_players - playersPerPage + 1
	end
	
	-- Check for when there are too few players to fill one page.
	if playersToSkip < 0 then
		playersToSkip = 0
	end

	local isStaffOnDuty = exports.global:isStaffOnDuty( localPlayer )

	-- For every player in the cache, render a new entry.
	for k=playersToSkip + 1, #g_players do
		local player = g_players [ k ]
		local hasPerk, perkValue = exports.donators:hasPlayerPerk(player, 12)
		if not (hasPerk and tonumber(perkValue) == 1) or isStaffOnDuty then
			-- Check if it's gonna fit. If it doesn't stop rendering.
			if top < bottom - rowHeight - SCOREBOARD_ROW_GAP then
				renderEntry ( player, isStaffOnDuty )
				-- Update the height for the next entry
				top = top + rowHeight + SCOREBOARD_ROW_GAP
			else break end
		end
	end
	
	-- Draw the scrollbar. The maximum players to skip is #g_players - playersPerPage + 1, so when
	-- the scoreboard is fully scrolled it will become 1, while when it's not scrolled it will be
	-- 0 due to playersToSkip being 0.
	drawScrollBar ( SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + rowHeight + 10, playersToSkip / ( #g_players - playersPerPage + 1 ) )
end

--[[
* isVisible
Returns wherever or not the scoreboard is visible
--]]
function isVisible ( )
	return g_isShowing
end

ده الكلنت
 


---- vgScoreboard v1.0-- Server-side script.-- By Alberto "ryden" Alonso--local scoreboardDummy--[[* onResourceStartHandles the resource start event to create a dummy entity with information about the server.--]]addEventHandler ( "onResourceStart", getResourceRootElement(getThisResource()), function ()	scoreboardDummy = createElement ( "scoreboard" )	setElementData ( scoreboardDummy, "serverName", "ALG-Adiga Live Gaming" )	setElementData ( scoreboardDummy, "maxPlayers", getMaxPlayers () )	setElementData ( scoreboardDummy, "allow", true )		--[[ Uncomment to test with dummies ]]--	--[[	for k=70,270 do		local dummy = createElement ( "playerDummy" )		setElementData ( dummy, "playerid", k )		setElementData ( dummy, "name", "dummy" .. tostring(k), false )		setElementData ( dummy, "ping", math.random ( 1, 300 ) )		setElementData ( dummy, "color", { math.random(0,255), math.random(0,255), math.random(0,255) } )	end	--]]end, false )--[[* onResourceStopDelete the dummy created on resource start.--]]addEventHandler ( "onResourceStop", getResourceRootElement(getThisResource()), function ()	if scoreboardDummy then		destroyElement ( scoreboardDummy )	endend, false )

ده السيرفر

اكسبورت فنكشن بالميتا؟

Link to comment
2 minutes ago, Killer Project said:

المشكلة من عندك والله اعلم .. لأني جربت المود وشغال طبيعي

بس للتأكيد على ملف ميتا


 


<meta>

<script src="server.lua" type="server" />

</meta>


غير كدة اكتب في اف 8
debugscript 3

واكتب ايه المشاكل اللي بتطلع لك

ممكن تحط المود كلو في رابط و ترفعو لو سمحت 
@Killer Project

1 minute ago, Master_MTA said:

اكسبورت فنكشن بالميتا؟

يب في في الميتا اكسبورت 

	<export function="isVisible" type="client" />

 

Link to comment
9 hours ago, Jack Tom said:

scoreboard

مدري صراحة .. سوي اشارة لأحد الاشخاص وخله يجرب الكود اللي ارسلته لك
اذا نفس المشكلة اذن المشكلة عندي واذا لا وهذا الشي المتوقع فالمشكلة بتكون عندك لأني مجرب الكود قبل ما ارسله لك

Link to comment
17 minutes ago, Killer Project said:

مدري صراحة .. سوي اشارة لأحد الاشخاص وخله يجرب الكود اللي ارسلته لك
اذا نفس المشكلة اذن المشكلة عندي واذا لا وهذا الشي المتوقع فالمشكلة بتكون عندك لأني مجرب الكود قبل ما ارسله لك

خلاص اخي مشكور لا تاكل هم

Link to comment

جرب استبدل الكلنت حق السكوربورد حقك بذا 

وأمر الافك afk

--
-- vgScoreboard v1.0
-- Client-side script.
-- By Alberto "ryden" Alonso
--

--[[ Configuration ]]--
local SCOREBOARD_WIDTH				= 460				-- The scoreboard window width
local SCOREBOARD_HEIGHT				= 500				-- The scoreboard window height
local SCOREBOARD_HEADER_HEIGHT		= 30				-- Height for the header in what you can see the server info
local SCOREBOARD_TOGGLE_CONTROL		= "tab"				-- Control/Key to toggle the scoreboard visibility
local SCOREBOARD_PGUP_CONTROL		= "mouse_wheel_up"	-- Control/Key to move one page up
local SCOREBOARD_PGDN_CONTROL		= "mouse_wheel_down"-- Control/Key to move one page down
local SCOREBOARD_DISABLED_CONTROLS	= { "next_weapon",	-- Controls that are disabled when the scoreboard is showing
										"previous_weapon",
										"aim_weapon",
										"radio_next",
										"radio_previous" }
local SCOREBOARD_TOGGLE_TIME		= 200				-- Time in miliseconds to make the scoreboard (dis)appear
local SCOREBOARD_POSTGUI			= true				-- Set to true if it must be drawn over the GUI
local SCOREBOARD_INFO_BACKGROUND	= { 0, 0, 0, 150 }			-- RGBA color for the info header background
local SCOREBOARD_SERVER_NAME_COLOR	= { 255, 255, 255, 255 }		-- RGBA color for the server name text
local SCOREBOARD_PLAYERCOUNT_COLOR	= { 255, 255, 255, 255 }	-- RGBA color for the server player count text
local SCOREBOARD_BACKGROUND			= { 0, 0, 0, 140 }			-- RGBA color for the background
local SCOREBOARD_BACKGROUND_IMAGE	= { 255, 255, 255, 40 }		-- RGBA color for the background image
local SCOREBOARD_HEADERS_COLOR		= { 255, 255, 255, 180 }	-- RGBA color for the headers
local SCOREBOARD_SEPARATOR_COLOR	= { 82, 82, 82, 140 }		-- RGBA color for the separator line between headers and body content
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_FOREGROUND	= { 255, 255, 255, 255 }		-- RGBA color for the scroll foreground
local SCOREBOARD_SCROLL_HEIGHT		= 40						-- Size for the scroll marker
local SCOREBOARD_COLUMNS_WIDTH		= { 0.08, 0.57, 0.2, 0.14, 0.02 }	-- Relative width for each column: id, player name, ping and scroll position
local SCOREBOARD_ROW_GAP			= 1							-- Gap between rows

--[[ Uncomment to test with dummies ]]--
--[[
local _getPlayerName = getPlayerName
local _getPlayerPing = getPlayerPing
local _getPlayerNametagColor = getPlayerNametagColor

function getPlayerName ( player )
	if getElementType ( player ) == "player" then return _getPlayerName ( player ) end
	return getElementData ( player, "name" )
end

function getPlayerPing ( player )
	if getElementType ( player ) == "player" then return _getPlayerPing ( player ) end
	return getElementData ( player, "ping" )
end

function getPlayerNametagColor ( player )
	if getElementType ( player ) == "player" then return _getPlayerNametagColor ( player )
	else return unpack(getElementData(player, "color")) end
end
--]]


--[[ Global variables to this context ]]--
local g_isShowing = false		-- Marks if the scoreboard is showing
local g_currentWidth = 0		-- Current window width. Used for the fade in/out effect.
local g_currentHeight = 0		-- Current window height. Used for the fade in/out effect.
local g_scoreboardDummy			-- Will contain the scoreboard dummy element to gather info from.
local g_windowSize = { guiGetScreenSize () }	-- The window size
local g_localPlayer = getLocalPlayer ()			-- The local player...
local g_currentPage = 0			-- The current scroll page
local g_players					-- We will keep a cache of the conected player list
local g_oldControlStates		-- To save the old control states before disabling them for scrolling

--[[ Pre-calculate some stuff ]]--
-- Scoreboard position
local SCOREBOARD_X = math.floor ( ( g_windowSize[1] - SCOREBOARD_WIDTH ) / 2 )
local SCOREBOARD_Y = math.floor ( ( g_windowSize[2] - SCOREBOARD_HEIGHT ) / 2 )
-- Scoreboard colors
SCOREBOARD_INFO_BACKGROUND = tocolor ( unpack ( SCOREBOARD_INFO_BACKGROUND ) )
SCOREBOARD_SERVER_NAME_COLOR = tocolor ( unpack ( SCOREBOARD_SERVER_NAME_COLOR ) )
SCOREBOARD_PLAYERCOUNT_COLOR = tocolor ( unpack ( SCOREBOARD_PLAYERCOUNT_COLOR ) )
SCOREBOARD_BACKGROUND = tocolor ( unpack ( SCOREBOARD_BACKGROUND ) )
SCOREBOARD_BACKGROUND_IMAGE = tocolor ( unpack ( SCOREBOARD_BACKGROUND_IMAGE ) )
SCOREBOARD_HEADERS_COLOR = tocolor ( unpack ( SCOREBOARD_HEADERS_COLOR ) )
SCOREBOARD_SCROLL_BACKGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_BACKGROUND ) )
SCOREBOARD_SCROLL_FOREGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_FOREGROUND ) )
SCOREBOARD_SEPARATOR_COLOR = tocolor ( unpack ( SCOREBOARD_SEPARATOR_COLOR ) )
-- Columns width in absolute units
for k=1,#SCOREBOARD_COLUMNS_WIDTH do
	SCOREBOARD_COLUMNS_WIDTH[k] = math.floor ( SCOREBOARD_COLUMNS_WIDTH[k] * SCOREBOARD_WIDTH )
end
-- Pre-calculate each row horizontal bounding box.
local rowsBoundingBox = { { SCOREBOARD_X, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }
-- ID
rowsBoundingBox[1][2] = SCOREBOARD_X + SCOREBOARD_COLUMNS_WIDTH[1]
-- Name
rowsBoundingBox[2][1] = rowsBoundingBox[1][2]
rowsBoundingBox[2][2] = rowsBoundingBox[2][1] + SCOREBOARD_COLUMNS_WIDTH[2]
-- Hoursplayed
rowsBoundingBox[3][1] = rowsBoundingBox[2][2]
rowsBoundingBox[3][2] = rowsBoundingBox[3][1] + SCOREBOARD_COLUMNS_WIDTH[3]
-- Ping
rowsBoundingBox[4][1] = rowsBoundingBox[3][2]
rowsBoundingBox[4][2] = rowsBoundingBox[4][1] + SCOREBOARD_COLUMNS_WIDTH[4]
-- Scrollbar
rowsBoundingBox[5][1] = rowsBoundingBox[4][2]
rowsBoundingBox[5][2] = SCOREBOARD_X + SCOREBOARD_WIDTH


--[[ Pre-declare some functions ]]--
local onRender
local fadeScoreboard
local drawBackground
local drawScoreboard


--[[
* clamp
Clamps a value into a range.
--]]
local function clamp ( valueMin, current, valueMax )
	if current < valueMin then
		return valueMin
	elseif current > valueMax then
		return valueMax
	else
		return current
	end
end

--[[
* createPlayerCache
Generates a new player cache.
--]]
local function createPlayerCache ( ignorePlayer )
	-- Optimize the function in case of not having to ignore a player
	if ignorePlayer then
		-- Clear the gloal table
		g_players = {}
		
		-- Get the list of connected players
		local players = getElementsByType ( "player" )
	
		-- Dump them to the global table
		for k, player in ipairs(players) do
			if ignorePlayer ~= player then
				table.insert ( g_players, player )
			end
		end
	else
		g_players = getElementsByType ( "player" )
	end
	
	--[[ Uncomment to test with dummies ]]--
	--[[
	for k,v in ipairs(getElementsByType("playerDummy")) do
		table.insert(g_players, v)
	end
	--]]
	
	-- Sort the player list by their ID, giving priority to the local player
	table.sort ( g_players, function ( a, b )
		local idA = getElementData ( a, "playerid" ) or 0
		local idB = getElementData ( b, "playerid" ) or 0

		-- Perform the checks to always set the local player at the beggining
		if a == g_localPlayer then
			idA = -1
		elseif b == g_localPlayer then
			idB = -1
		end
		
		return tonumber(idA) < tonumber(idB)
	end )
end

--[[
* onClientResourceStart
Handles the resource start event to create the initial player cache
--]]
addEventHandler ( "onClientResourceStart", getResourceRootElement(getThisResource()), function ()
	createPlayerCache ()
end, false )

--[[
* onClientElementDataChange
Handles the element data changes event to update the player cache
if the playerid was changed.
--]]
addEventHandler ( "onClientElementDataChange", root, function ( dataName, dataValue )
	if dataName == "playerid" then
		createPlayerCache ()
	end
end )

--[[
* onClientPlayerQuit
Handles the player quit event to update the player cache.
--]]
addEventHandler ( "onClientPlayerQuit", root, function ()
	createPlayerCache ( source )
end )

--[[
* toggleScoreboard
Toggles the visibility of the scoreboard.
--]]
local function toggleScoreboard ( show )
	if not getControlState( 'aim_weapon' ) then
		-- Force the parameter to be a boolean
		local show = show == true
		
		-- Check if the status has changed
		if show ~= g_isShowing then
			g_isShowing = show
			
			if g_isShowing and g_currentWidth == 0 and g_currentHeight == 0 then
				-- Handle the onClientRender event to start drawing the scoreboard.
				addEventHandler ( "onClientPreRender", root, onRender, false )
			end
			
			-- Little hack to avoid switching weapons while moving through the scoreboard pages.
			if g_isShowing then
				g_oldControlStates = {}
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					g_oldControlStates[k] = isControlEnabled ( control )
					toggleControl ( control, false )
				end
			else
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					toggleControl ( control, g_oldControlStates[k] )
				end
				g_oldControlStates = nil
			end
		end
	end
end

--[[
* onToggleKey
Function to bind to the appropiate key the function to toggle the scoreboard visibility.
--]]
local function onToggleKey ( key, keyState )
	-- Check if the scoreboard element has been created
	if not g_scoreboardDummy then
		local elementTable = getElementsByType ( "scoreboard" )
		if #elementTable > 0 then
			g_scoreboardDummy = elementTable[1]
		else
			return
		end
	end
	
	-- Toggle the scoreboard, and check that it's allowed.
	toggleScoreboard ( keyState == "down" and getElementData ( g_scoreboardDummy, "allow" ) )
end
bindKey ( SCOREBOARD_TOGGLE_CONTROL, "both", onToggleKey )

--[[
* onScrollKey
Function to bind to the appropiate key the function to change the current page.
--]]
local function onScrollKey ( direction )
	if g_isShowing then
		if direction then
			g_currentPage = g_currentPage + 1
		else
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then
				g_currentPage = 0
			end
		end
	end
end
bindKey ( SCOREBOARD_PGUP_CONTROL, "down", function () onScrollKey ( false ) end )
bindKey ( SCOREBOARD_PGDN_CONTROL, "down", function () onScrollKey ( true ) end )

--[[
* onRender
Event handler for onClientPreRender. It will forward the flow to the most appropiate
function: fading-in, fading-out or drawScoreboard.
--]]
onRender = function ( timeshift )
	-- Boolean to check if we must draw the scoreboard.
	local drawIt = false
	
	if g_isShowing then
		-- Check if the scoreboard has been disallowed
		if not getElementData ( g_scoreboardDummy, "allow" ) then
			toggleScoreboard ( false )
		-- If it's showing, check if it got fully faded in. Else, draw it normally.
		elseif g_currentWidth < SCOREBOARD_WIDTH or g_currentHeight < SCOREBOARD_HEIGHT then
			drawIt = fadeScoreboard ( timeshift, 1 )
		else
			-- Allow drawing the full scoreboard
			drawIt = true
		end
	else
		-- If it shouldn't be showing, make another step to fade it out.
		drawIt = fadeScoreboard ( timeshift, -1 )
	end
	
	-- Draw the scoreboard if allowed.
	if drawIt then
		drawScoreboard ()
	end
end

--[[
* fadeScoreboard
Makes a step of the fade effect. Gets a multiplier to make it either fading in or out.
--]]
fadeScoreboard = function ( timeshift, multiplier )
	-- Get the percentage of the final size that it should grow for this step.
	local growth = ( timeshift / SCOREBOARD_TOGGLE_TIME ) * multiplier
	
	-- Apply the growth to the scoreboard size
	g_currentWidth = clamp ( 0, g_currentWidth + ( SCOREBOARD_WIDTH * growth ), SCOREBOARD_WIDTH )
	g_currentHeight = clamp ( 0, g_currentHeight + ( SCOREBOARD_HEIGHT * growth ), SCOREBOARD_HEIGHT )
	
	-- Check if the scoreboard has collapsed. If so, unregister the onClientRender event.
	if g_currentWidth == 0 or g_currentHeight == 0 then
		g_currentWidth = 0
		g_currentHeight = 0
		removeEventHandler ( "onClientPreRender", root, onRender )
		return false
	else
		return true
	end
end

--[[
* drawBackground
Draws the scoreboard background.
--]]
drawBackground = function ()

	dxDrawImage(SCOREBOARD_X, SCOREBOARD_Y, g_currentWidth, g_currentHeight, ":hud/images/hud/box.png")
	
end

--[[
* drawRowBounded
Draws a scoreboard body row with the pre-calculated row bounding boxes.
--]]
local function drawRowBounded ( id, name, hours, ping, colors, font, top )
	-- Precalculate some constants
	local bottom = clamp ( 0, top + dxGetFontHeight ( 1, font ), SCOREBOARD_Y + g_currentHeight )
	local maxWidth = SCOREBOARD_X + g_currentWidth
	
	-- If the row doesn't fit, just avoid any further calculations.
	if bottom < top then return end
	
	-- ID
	local left = rowsBoundingBox[1][1]
	local right = clamp ( 0, rowsBoundingBox[1][2], maxWidth )
	if left < right then
		dxDrawText ( id, left, top, right, bottom,
					 colors[1], 1, font, "right", "top",
					 true, false, SCOREBOARD_POSTGUI )
		
		-- Name
		left = rowsBoundingBox[2][1] + 17 -- Grant some padding to the name column
		right = clamp ( 0, rowsBoundingBox[2][2], maxWidth )
		if left < right then
			dxDrawText ( name, left, top, right, bottom,
						 colors[2], 1, font, "left", "top",
						 true, false, SCOREBOARD_POSTGUI )
			
			-- Hoursplayed
			left = rowsBoundingBox[3][1]
			right = clamp ( 0, rowsBoundingBox[3][2], maxWidth )
			--outputDebugString(left.." vs ".. right)
			if left < right then
				dxDrawText ( hours, left, top, right, bottom,
							 colors[3], 1, font, "left", "top",
							 true, false, SCOREBOARD_POSTGUI )
				-- Ping
				left = rowsBoundingBox[4][1]
				right = clamp ( 0, rowsBoundingBox[4][2], maxWidth )
				--outputDebugString(left.." vs ".. right)
				if left < right then
					dxDrawText ( ping, left, top, right, bottom,
								 colors[3], 1, font, "left", "top",
								 true, false, SCOREBOARD_POSTGUI )
				end
			end
			

		end
	end
end

--[[
* drawScrollBar
Draws the scroll bar. Position ranges from 0 to 1.
--]]
local function drawScrollBar ( top, position )
	-- Get the bounding box
	local left = rowsBoundingBox[5][1]
	local right = clamp ( 0, rowsBoundingBox[5][2], SCOREBOARD_X + g_currentWidth )
	local bottom = clamp ( 0, SCOREBOARD_Y + SCOREBOARD_HEIGHT, SCOREBOARD_Y + g_currentHeight )
	
	-- Make sure that it'd be visible.
	if left < right and top < bottom then
		-- Draw the background
		dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_BACKGROUND, SCOREBOARD_POSTGUI )
		
		-- Get the current Y position for the scroll marker
		local top = top + position * ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - SCOREBOARD_SCROLL_HEIGHT - top )
		bottom = clamp ( 0, top + SCOREBOARD_SCROLL_HEIGHT, SCOREBOARD_Y + g_currentHeight )
		
		-- Make sure that it'd be visible
		if top < bottom then
			dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_FOREGROUND, SCOREBOARD_POSTGUI )
		end
	end
end

function makeFont()
	if not theFont then
		theFont = dxCreateFont ( ':resources/cartwheel.otf' )
	end
	return theFont
end


--[[
* drawScoreboard
Draws the scoreboard contents.
--]]
drawScoreboard = function ()
	-- Check that we got the list of players
	if not g_players then return end

	-- First draw the background
	drawBackground ()
	
	-- Get the server information
	local serverName = getElementData ( g_scoreboardDummy, "serverName" ) or "MTA server"
	local maxPlayers = getElementData ( root, "server:Slots" ) or 0
	serverName = tostring ( serverName )
	maxPlayers = tonumber ( maxPlayers )
	
	-- Render the header
	-- Calculate the bounding box for the header texts
	local left, top, right, bottom = SCOREBOARD_X + 2, SCOREBOARD_Y + 2, SCOREBOARD_X + g_currentWidth - 2, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT - 2
	
	-- Render the server name
	dxDrawText ( serverName, left, top, right, bottom,
				 SCOREBOARD_SERVER_NAME_COLOR, 1, makeFont() or "default-bold", "center", "center",
				 true, false, SCOREBOARD_POSTGUI )


	-- Render the player count
	local usagePercent = (#g_players / maxPlayers) * 100
	local strPlayerCount = "Players: " .. tostring(#g_players) .. "/" .. tostring(maxPlayers) .. " (" .. math.floor(usagePercent + 0.5) .. "%)"
	
	-- We need to recalculate the left position, to make it not move when fading.
	local offset = SCOREBOARD_WIDTH - dxGetTextWidth ( strPlayerCount, 1, makeFont() or "default" ) - 4
	left = left + offset
	-- Make sure of that it needs to be rendered now
	
	-- Draw the body.
	-- Update the bounding box.
	left, top, bottom = SCOREBOARD_X, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + 2, SCOREBOARD_Y + g_currentHeight - 2

	-- Pre-calculate how much height will each row have.
	local rowHeight = dxGetFontHeight ( 1, "default-bold" )
	
	-- Draw the headers
	drawRowBounded ( "ID", "Player Name", "Hoursplayed", "Status", "Ping",
					 { SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR },
					 "default-bold", top )
	
				 
	-- Add the offset for a new row
	top = top + rowHeight + 3
	
	-- Draw the separator
	right = clamp ( 0, rowsBoundingBox[4][2] - 5, SCOREBOARD_X + g_currentWidth )
	if top < SCOREBOARD_Y + g_currentHeight then
		dxDrawLine ( SCOREBOARD_X + 5, top, right, top, SCOREBOARD_SEPARATOR_COLOR, 1, SCOREBOARD_POSTGUI )
	end
	top = top + 3
	
	-- Create a function to render a player entry
	local renderEntry = function ( player, seeUsername )
		-- Get the player data
		local playerID = getElementData ( player, "playerid" ) or 0
		playerID = tostring ( playerID )
		local playerUsername = ""
		if exports.integration:isPlayerTrialAdmin(getLocalPlayer()) or exports.integration:isPlayerSupporter(getLocalPlayer()) then
			local uname = getElementData( player, 'account:username' )
			playerUsername = uname and (" ("..uname..")") or ""
		end
		local playerName = exports.global:getPlayerName( player )..playerUsername
		local playerHours = getElementData( player, 'hoursplayed' ) or 0
		local playerStatus = getElementData( player, 'isAFK' ) or "Unknown"
		local playerPing = getPlayerPing ( player )
		playerPing = tostring ( playerPing )
		local r, g, b = getPlayerNametagColor ( player )
		local playerColor = tocolor ( r, g, b, 255 )
		
		-- Create the table of colors
		local colors = { playerColor, playerColor, playerColor, playerColor }
		
		-- Render it!
		drawRowBounded ( playerID, playerName, playerHours, playerStatus, playerPing, colors, "default-bold", top )
	end
	
	-- Calculate how much players can fit in the body window.
	local playersPerPage = math.floor ( ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - top ) / ( rowHeight + SCOREBOARD_ROW_GAP ) )
	
	-- Get the amount of shifted players per page
	local playerShift = math.floor ( playersPerPage / 2 )
	
	-- Get the number of players to skip
	local playersToSkip = playerShift * g_currentPage
	if (#g_players - playersToSkip) < playersPerPage then
		-- Check that they didn't go to an invalid page
		if (#g_players - playersToSkip) < playerShift then
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then g_currentPage = 0 end
		end

		-- Try to always fill pages
		playersToSkip = #g_players - playersPerPage + 1
	end
	
	-- Check for when there are too few players to fill one page.
	if playersToSkip < 0 then
		playersToSkip = 0
	end

	local isStaffOnDuty = exports.global:isStaffOnDuty( localPlayer )

	-- For every player in the cache, render a new entry.
	for k=playersToSkip + 1, #g_players do
		local player = g_players [ k ]
		local hasPerk, perkValue = exports.donators:hasPlayerPerk(player, 12)
		if not (hasPerk and tonumber(perkValue) == 1) or isStaffOnDuty then
			-- Check if it's gonna fit. If it doesn't stop rendering.
			if top < bottom - rowHeight - SCOREBOARD_ROW_GAP then
				renderEntry ( player, isStaffOnDuty )
				-- Update the height for the next entry
				top = top + rowHeight + SCOREBOARD_ROW_GAP
			else break end
		end
	end
	
	-- Draw the scrollbar. The maximum players to skip is #g_players - playersPerPage + 1, so when
	-- the scoreboard is fully scrolled it will become 1, while when it's not scrolled it will be
	-- 0 due to playersToSkip being 0.
	drawScrollBar ( SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + rowHeight + 10, playersToSkip / ( #g_players - playersPerPage + 1 ) )
end

--[[
* isVisible
Returns wherever or not the scoreboard is visible
--]]
function isVisible ( )
	return g_isShowing
end

addCommandHandler("afk",
	function ( player )
		if ( player ) then
			local data = getElementData(player, "isAFK")
			if ( data == false ) then
				setElementData(player, "isAFK", "AFK")
				outputChatBox("Your status now is afk.", player, 255, 255, 255, true)
			else
				outputChatBox("Your status now is online.", player, 255, 255, 255, true)
				setElementData(player, "isAFK", "Online")
			end
		end
	end
)

 

Link to comment
8 hours ago, Abdul KariM said:

@N3xT بالكلينت مافيه بارتمر لاعب

مشكور ع التنبيه, راح عن بالي انه كلينت

عدل

 

--
-- vgScoreboard v1.0
-- Client-side script.
-- By Alberto "ryden" Alonso
--
--[[ Configuration ]]--
local SCOREBOARD_WIDTH				= 460				-- The scoreboard window width
local SCOREBOARD_HEIGHT				= 500				-- The scoreboard window height
local SCOREBOARD_HEADER_HEIGHT		= 30				-- Height for the header in what you can see the server info
local SCOREBOARD_TOGGLE_CONTROL		= "tab"				-- Control/Key to toggle the scoreboard visibility
local SCOREBOARD_PGUP_CONTROL		= "mouse_wheel_up"	-- Control/Key to move one page up
local SCOREBOARD_PGDN_CONTROL		= "mouse_wheel_down"-- Control/Key to move one page down
local SCOREBOARD_DISABLED_CONTROLS	= { "next_weapon",	-- Controls that are disabled when the scoreboard is showing
										"previous_weapon",
										"aim_weapon",
										"radio_next",
										"radio_previous" }
local SCOREBOARD_TOGGLE_TIME		= 200				-- Time in miliseconds to make the scoreboard (dis)appear
local SCOREBOARD_POSTGUI			= true				-- Set to true if it must be drawn over the GUI
local SCOREBOARD_INFO_BACKGROUND	= { 0, 0, 0, 150 }			-- RGBA color for the info header background
local SCOREBOARD_SERVER_NAME_COLOR	= { 255, 255, 255, 255 }		-- RGBA color for the server name text
local SCOREBOARD_PLAYERCOUNT_COLOR	= { 255, 255, 255, 255 }	-- RGBA color for the server player count text
local SCOREBOARD_BACKGROUND			= { 0, 0, 0, 140 }			-- RGBA color for the background
local SCOREBOARD_BACKGROUND_IMAGE	= { 255, 255, 255, 40 }		-- RGBA color for the background image
local SCOREBOARD_HEADERS_COLOR		= { 255, 255, 255, 180 }	-- RGBA color for the headers
local SCOREBOARD_SEPARATOR_COLOR	= { 82, 82, 82, 140 }		-- RGBA color for the separator line between headers and body content
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_BACKGROUND	= { 0, 10, 20, 100 }		-- RGBA color for the scroll background
local SCOREBOARD_SCROLL_FOREGROUND	= { 255, 255, 255, 255 }		-- RGBA color for the scroll foreground
local SCOREBOARD_SCROLL_HEIGHT		= 40						-- Size for the scroll marker
local SCOREBOARD_COLUMNS_WIDTH		= { 0.08, 0.57, 0.2, 0.14, 0.02 }	-- Relative width for each column: id, player name, ping and scroll position
local SCOREBOARD_ROW_GAP			= 1							-- Gap between rows
--[[ Uncomment to test with dummies ]]--
--[[
local _getPlayerName = getPlayerName
local _getPlayerPing = getPlayerPing
local _getPlayerNametagColor = getPlayerNametagColor
function getPlayerName ( player )
	if getElementType ( player ) == "player" then return _getPlayerName ( player ) end
	return getElementData ( player, "name" )
end
function getPlayerPing ( player )
	if getElementType ( player ) == "player" then return _getPlayerPing ( player ) end
	return getElementData ( player, "ping" )
end
function getPlayerNametagColor ( player )
	if getElementType ( player ) == "player" then return _getPlayerNametagColor ( player )
	else return unpack(getElementData(player, "color")) end
end
--]]
--[[ Global variables to this context ]]--
local g_isShowing = false		-- Marks if the scoreboard is showing
local g_currentWidth = 0		-- Current window width. Used for the fade in/out effect.
local g_currentHeight = 0		-- Current window height. Used for the fade in/out effect.
local g_scoreboardDummy			-- Will contain the scoreboard dummy element to gather info from.
local g_windowSize = { guiGetScreenSize () }	-- The window size
local g_localPlayer = getLocalPlayer ()			-- The local player...
local g_currentPage = 0			-- The current scroll page
local g_players					-- We will keep a cache of the conected player list
local g_oldControlStates		-- To save the old control states before disabling them for scrolling
--[[ Pre-calculate some stuff ]]--
-- Scoreboard position
local SCOREBOARD_X = math.floor ( ( g_windowSize[1] - SCOREBOARD_WIDTH ) / 2 )
local SCOREBOARD_Y = math.floor ( ( g_windowSize[2] - SCOREBOARD_HEIGHT ) / 2 )
-- Scoreboard colors
SCOREBOARD_INFO_BACKGROUND = tocolor ( unpack ( SCOREBOARD_INFO_BACKGROUND ) )
SCOREBOARD_SERVER_NAME_COLOR = tocolor ( unpack ( SCOREBOARD_SERVER_NAME_COLOR ) )
SCOREBOARD_PLAYERCOUNT_COLOR = tocolor ( unpack ( SCOREBOARD_PLAYERCOUNT_COLOR ) )
SCOREBOARD_BACKGROUND = tocolor ( unpack ( SCOREBOARD_BACKGROUND ) )
SCOREBOARD_BACKGROUND_IMAGE = tocolor ( unpack ( SCOREBOARD_BACKGROUND_IMAGE ) )
SCOREBOARD_HEADERS_COLOR = tocolor ( unpack ( SCOREBOARD_HEADERS_COLOR ) )
SCOREBOARD_SCROLL_BACKGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_BACKGROUND ) )
SCOREBOARD_SCROLL_FOREGROUND = tocolor ( unpack ( SCOREBOARD_SCROLL_FOREGROUND ) )
SCOREBOARD_SEPARATOR_COLOR = tocolor ( unpack ( SCOREBOARD_SEPARATOR_COLOR ) )
-- Columns width in absolute units
for k=1,#SCOREBOARD_COLUMNS_WIDTH do
	SCOREBOARD_COLUMNS_WIDTH[k] = math.floor ( SCOREBOARD_COLUMNS_WIDTH[k] * SCOREBOARD_WIDTH )
end
-- Pre-calculate each row horizontal bounding box.
local rowsBoundingBox = { { SCOREBOARD_X, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 } }
-- ID
rowsBoundingBox[1][2] = SCOREBOARD_X + SCOREBOARD_COLUMNS_WIDTH[1]
-- Name
rowsBoundingBox[2][1] = rowsBoundingBox[1][2]
rowsBoundingBox[2][2] = rowsBoundingBox[2][1] + SCOREBOARD_COLUMNS_WIDTH[2]
-- Hoursplayed
rowsBoundingBox[3][1] = rowsBoundingBox[2][2]
rowsBoundingBox[3][2] = rowsBoundingBox[3][1] + SCOREBOARD_COLUMNS_WIDTH[3]
-- Ping
rowsBoundingBox[4][1] = rowsBoundingBox[3][2]
rowsBoundingBox[4][2] = rowsBoundingBox[4][1] + SCOREBOARD_COLUMNS_WIDTH[4]
-- Scrollbar
rowsBoundingBox[5][1] = rowsBoundingBox[4][2]
rowsBoundingBox[5][2] = SCOREBOARD_X + SCOREBOARD_WIDTH
--[[ Pre-declare some functions ]]--
local onRender
local fadeScoreboard
local drawBackground
local drawScoreboard
--[[
* clamp
Clamps a value into a range.
--]]
local function clamp ( valueMin, current, valueMax )
	if current < valueMin then
		return valueMin
	elseif current > valueMax then
		return valueMax
	else
		return current
	end
end
--[[
* createPlayerCache
Generates a new player cache.
--]]
local function createPlayerCache ( ignorePlayer )
	-- Optimize the function in case of not having to ignore a player
	if ignorePlayer then
		-- Clear the gloal table
		g_players = {}
		
		-- Get the list of connected players
		local players = getElementsByType ( "player" )
	
		-- Dump them to the global table
		for k, player in ipairs(players) do
			if ignorePlayer ~= player then
				table.insert ( g_players, player )
			end
		end
	else
		g_players = getElementsByType ( "player" )
	end
	
	--[[ Uncomment to test with dummies ]]--
	--[[
	for k,v in ipairs(getElementsByType("playerDummy")) do
		table.insert(g_players, v)
	end
	--]]
	
	-- Sort the player list by their ID, giving priority to the local player
	table.sort ( g_players, function ( a, b )
		local idA = getElementData ( a, "playerid" ) or 0
		local idB = getElementData ( b, "playerid" ) or 0
		-- Perform the checks to always set the local player at the beggining
		if a == g_localPlayer then
			idA = -1
		elseif b == g_localPlayer then
			idB = -1
		end
		
		return tonumber(idA) < tonumber(idB)
	end )
end
--[[
* onClientResourceStart
Handles the resource start event to create the initial player cache
--]]
addEventHandler ( "onClientResourceStart", getResourceRootElement(getThisResource()), function ()
	createPlayerCache ()
end, false )
--[[
* onClientElementDataChange
Handles the element data changes event to update the player cache
if the playerid was changed.
--]]
addEventHandler ( "onClientElementDataChange", root, function ( dataName, dataValue )
	if dataName == "playerid" then
		createPlayerCache ()
	end
end )
--[[
* onClientPlayerQuit
Handles the player quit event to update the player cache.
--]]
addEventHandler ( "onClientPlayerQuit", root, function ()
	createPlayerCache ( source )
end )
--[[
* toggleScoreboard
Toggles the visibility of the scoreboard.
--]]
local function toggleScoreboard ( show )
	if not getControlState( 'aim_weapon' ) then
		-- Force the parameter to be a boolean
		local show = show == true
		
		-- Check if the status has changed
		if show ~= g_isShowing then
			g_isShowing = show
			
			if g_isShowing and g_currentWidth == 0 and g_currentHeight == 0 then
				-- Handle the onClientRender event to start drawing the scoreboard.
				addEventHandler ( "onClientPreRender", root, onRender, false )
			end
			
			-- Little hack to avoid switching weapons while moving through the scoreboard pages.
			if g_isShowing then
				g_oldControlStates = {}
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					g_oldControlStates[k] = isControlEnabled ( control )
					toggleControl ( control, false )
				end
			else
				for k, control in ipairs ( SCOREBOARD_DISABLED_CONTROLS ) do
					toggleControl ( control, g_oldControlStates[k] )
				end
				g_oldControlStates = nil
			end
		end
	end
end
--[[
* onToggleKey
Function to bind to the appropiate key the function to toggle the scoreboard visibility.
--]]
local function onToggleKey ( key, keyState )
	-- Check if the scoreboard element has been created
	if not g_scoreboardDummy then
		local elementTable = getElementsByType ( "scoreboard" )
		if #elementTable > 0 then
			g_scoreboardDummy = elementTable[1]
		else
			return
		end
	end
	
	-- Toggle the scoreboard, and check that it's allowed.
	toggleScoreboard ( keyState == "down" and getElementData ( g_scoreboardDummy, "allow" ) )
end
bindKey ( SCOREBOARD_TOGGLE_CONTROL, "both", onToggleKey )
--[[
* onScrollKey
Function to bind to the appropiate key the function to change the current page.
--]]
local function onScrollKey ( direction )
	if g_isShowing then
		if direction then
			g_currentPage = g_currentPage + 1
		else
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then
				g_currentPage = 0
			end
		end
	end
end
bindKey ( SCOREBOARD_PGUP_CONTROL, "down", function () onScrollKey ( false ) end )
bindKey ( SCOREBOARD_PGDN_CONTROL, "down", function () onScrollKey ( true ) end )
--[[
* onRender
Event handler for onClientPreRender. It will forward the flow to the most appropiate
function: fading-in, fading-out or drawScoreboard.
--]]
onRender = function ( timeshift )
	-- Boolean to check if we must draw the scoreboard.
	local drawIt = false
	
	if g_isShowing then
		-- Check if the scoreboard has been disallowed
		if not getElementData ( g_scoreboardDummy, "allow" ) then
			toggleScoreboard ( false )
		-- If it's showing, check if it got fully faded in. Else, draw it normally.
		elseif g_currentWidth < SCOREBOARD_WIDTH or g_currentHeight < SCOREBOARD_HEIGHT then
			drawIt = fadeScoreboard ( timeshift, 1 )
		else
			-- Allow drawing the full scoreboard
			drawIt = true
		end
	else
		-- If it shouldn't be showing, make another step to fade it out.
		drawIt = fadeScoreboard ( timeshift, -1 )
	end
	
	-- Draw the scoreboard if allowed.
	if drawIt then
		drawScoreboard ()
	end
end
--[[
* fadeScoreboard
Makes a step of the fade effect. Gets a multiplier to make it either fading in or out.
--]]
fadeScoreboard = function ( timeshift, multiplier )
	-- Get the percentage of the final size that it should grow for this step.
	local growth = ( timeshift / SCOREBOARD_TOGGLE_TIME ) * multiplier
	
	-- Apply the growth to the scoreboard size
	g_currentWidth = clamp ( 0, g_currentWidth + ( SCOREBOARD_WIDTH * growth ), SCOREBOARD_WIDTH )
	g_currentHeight = clamp ( 0, g_currentHeight + ( SCOREBOARD_HEIGHT * growth ), SCOREBOARD_HEIGHT )
	
	-- Check if the scoreboard has collapsed. If so, unregister the onClientRender event.
	if g_currentWidth == 0 or g_currentHeight == 0 then
		g_currentWidth = 0
		g_currentHeight = 0
		removeEventHandler ( "onClientPreRender", root, onRender )
		return false
	else
		return true
	end
end
--[[
* drawBackground
Draws the scoreboard background.
--]]
drawBackground = function ()
	dxDrawImage(SCOREBOARD_X, SCOREBOARD_Y, g_currentWidth, g_currentHeight, ":hud/images/hud/box.png")
	
end
--[[
* drawRowBounded
Draws a scoreboard body row with the pre-calculated row bounding boxes.
--]]
local function drawRowBounded ( id, name, hours, ping, colors, font, top )
	-- Precalculate some constants
	local bottom = clamp ( 0, top + dxGetFontHeight ( 1, font ), SCOREBOARD_Y + g_currentHeight )
	local maxWidth = SCOREBOARD_X + g_currentWidth
	
	-- If the row doesn't fit, just avoid any further calculations.
	if bottom < top then return end
	
	-- ID
	local left = rowsBoundingBox[1][1]
	local right = clamp ( 0, rowsBoundingBox[1][2], maxWidth )
	if left < right then
		dxDrawText ( id, left, top, right, bottom,
					 colors[1], 1, font, "right", "top",
					 true, false, SCOREBOARD_POSTGUI )
		
		-- Name
		left = rowsBoundingBox[2][1] + 17 -- Grant some padding to the name column
		right = clamp ( 0, rowsBoundingBox[2][2], maxWidth )
		if left < right then
			dxDrawText ( name, left, top, right, bottom,
						 colors[2], 1, font, "left", "top",
						 true, false, SCOREBOARD_POSTGUI )
			
			-- Hoursplayed
			left = rowsBoundingBox[3][1]
			right = clamp ( 0, rowsBoundingBox[3][2], maxWidth )
			--outputDebugString(left.." vs ".. right)
			if left < right then
				dxDrawText ( hours, left, top, right, bottom,
							 colors[3], 1, font, "left", "top",
							 true, false, SCOREBOARD_POSTGUI )
				-- Ping
				left = rowsBoundingBox[4][1]
				right = clamp ( 0, rowsBoundingBox[4][2], maxWidth )
				--outputDebugString(left.." vs ".. right)
				if left < right then
					dxDrawText ( ping, left, top, right, bottom,
								 colors[3], 1, font, "left", "top",
								 true, false, SCOREBOARD_POSTGUI )
				end
			end
			
		end
	end
end
--[[
* drawScrollBar
Draws the scroll bar. Position ranges from 0 to 1.
--]]
local function drawScrollBar ( top, position )
	-- Get the bounding box
	local left = rowsBoundingBox[5][1]
	local right = clamp ( 0, rowsBoundingBox[5][2], SCOREBOARD_X + g_currentWidth )
	local bottom = clamp ( 0, SCOREBOARD_Y + SCOREBOARD_HEIGHT, SCOREBOARD_Y + g_currentHeight )
	
	-- Make sure that it'd be visible.
	if left < right and top < bottom then
		-- Draw the background
		dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_BACKGROUND, SCOREBOARD_POSTGUI )
		
		-- Get the current Y position for the scroll marker
		local top = top + position * ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - SCOREBOARD_SCROLL_HEIGHT - top )
		bottom = clamp ( 0, top + SCOREBOARD_SCROLL_HEIGHT, SCOREBOARD_Y + g_currentHeight )
		
		-- Make sure that it'd be visible
		if top < bottom then
			dxDrawRectangle ( left, top, right - left, bottom - top, SCOREBOARD_SCROLL_FOREGROUND, SCOREBOARD_POSTGUI )
		end
	end
end
function makeFont()
	if not theFont then
		theFont = dxCreateFont ( ':resources/cartwheel.otf' )
	end
	return theFont
end
--[[
* drawScoreboard
Draws the scoreboard contents.
--]]
drawScoreboard = function ()
	-- Check that we got the list of players
	if not g_players then return end
	-- First draw the background
	drawBackground ()
	
	-- Get the server information
	local serverName = getElementData ( g_scoreboardDummy, "serverName" ) or "MTA server"
	local maxPlayers = getElementData ( root, "server:Slots" ) or 0
	serverName = tostring ( serverName )
	maxPlayers = tonumber ( maxPlayers )
	
	-- Render the header
	-- Calculate the bounding box for the header texts
	local left, top, right, bottom = SCOREBOARD_X + 2, SCOREBOARD_Y + 2, SCOREBOARD_X + g_currentWidth - 2, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT - 2
	
	-- Render the server name
	dxDrawText ( serverName, left, top, right, bottom,
				 SCOREBOARD_SERVER_NAME_COLOR, 1, makeFont() or "default-bold", "center", "center",
				 true, false, SCOREBOARD_POSTGUI )
	-- Render the player count
	local usagePercent = (#g_players / maxPlayers) * 100
	local strPlayerCount = "Players: " .. tostring(#g_players) .. "/" .. tostring(maxPlayers) .. " (" .. math.floor(usagePercent + 0.5) .. "%)"
	
	-- We need to recalculate the left position, to make it not move when fading.
	local offset = SCOREBOARD_WIDTH - dxGetTextWidth ( strPlayerCount, 1, makeFont() or "default" ) - 4
	left = left + offset
	-- Make sure of that it needs to be rendered now
	
	-- Draw the body.
	-- Update the bounding box.
	left, top, bottom = SCOREBOARD_X, SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + 2, SCOREBOARD_Y + g_currentHeight - 2
	-- Pre-calculate how much height will each row have.
	local rowHeight = dxGetFontHeight ( 1, "default-bold" )
	
	-- Draw the headers
	drawRowBounded ( "ID", "Player Name", "Hoursplayed", "Status", "Ping",
					 { SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR, SCOREBOARD_HEADERS_COLOR },
					 "default-bold", top )
	
				 
	-- Add the offset for a new row
	top = top + rowHeight + 3
	
	-- Draw the separator
	right = clamp ( 0, rowsBoundingBox[4][2] - 5, SCOREBOARD_X + g_currentWidth )
	if top < SCOREBOARD_Y + g_currentHeight then
		dxDrawLine ( SCOREBOARD_X + 5, top, right, top, SCOREBOARD_SEPARATOR_COLOR, 1, SCOREBOARD_POSTGUI )
	end
	top = top + 3
	
	-- Create a function to render a player entry
	local renderEntry = function ( player, seeUsername )
		-- Get the player data
		local playerID = getElementData ( player, "playerid" ) or 0
		playerID = tostring ( playerID )
		local playerUsername = ""
		if exports.integration:isPlayerTrialAdmin(getLocalPlayer()) or exports.integration:isPlayerSupporter(getLocalPlayer()) then
			local uname = getElementData( player, 'account:username' )
			playerUsername = uname and (" ("..uname..")") or ""
		end
		local playerName = exports.global:getPlayerName( player )..playerUsername
		local playerHours = getElementData( player, 'hoursplayed' ) or 0
		local playerStatus = getElementData( player, 'isAFK' ) or "Unknown"
		local playerPing = getPlayerPing ( player )
		playerPing = tostring ( playerPing )
		local r, g, b = getPlayerNametagColor ( player )
		local playerColor = tocolor ( r, g, b, 255 )
		
		-- Create the table of colors
		local colors = { playerColor, playerColor, playerColor, playerColor }
		
		-- Render it!
		drawRowBounded ( playerID, playerName, playerHours, playerStatus, playerPing, colors, "default-bold", top )
	end
	
	-- Calculate how much players can fit in the body window.
	local playersPerPage = math.floor ( ( SCOREBOARD_Y + SCOREBOARD_HEIGHT - top ) / ( rowHeight + SCOREBOARD_ROW_GAP ) )
	
	-- Get the amount of shifted players per page
	local playerShift = math.floor ( playersPerPage / 2 )
	
	-- Get the number of players to skip
	local playersToSkip = playerShift * g_currentPage
	if (#g_players - playersToSkip) < playersPerPage then
		-- Check that they didn't go to an invalid page
		if (#g_players - playersToSkip) < playerShift then
			g_currentPage = g_currentPage - 1
			if g_currentPage < 0 then g_currentPage = 0 end
		end
		-- Try to always fill pages
		playersToSkip = #g_players - playersPerPage + 1
	end
	
	-- Check for when there are too few players to fill one page.
	if playersToSkip < 0 then
		playersToSkip = 0
	end
	local isStaffOnDuty = exports.global:isStaffOnDuty( localPlayer )
	-- For every player in the cache, render a new entry.
	for k=playersToSkip + 1, #g_players do
		local player = g_players [ k ]
		local hasPerk, perkValue = exports.donators:hasPlayerPerk(player, 12)
		if not (hasPerk and tonumber(perkValue) == 1) or isStaffOnDuty then
			-- Check if it's gonna fit. If it doesn't stop rendering.
			if top < bottom - rowHeight - SCOREBOARD_ROW_GAP then
				renderEntry ( player, isStaffOnDuty )
				-- Update the height for the next entry
				top = top + rowHeight + SCOREBOARD_ROW_GAP
			else break end
		end
	end
	
	-- Draw the scrollbar. The maximum players to skip is #g_players - playersPerPage + 1, so when
	-- the scoreboard is fully scrolled it will become 1, while when it's not scrolled it will be
	-- 0 due to playersToSkip being 0.
	drawScrollBar ( SCOREBOARD_Y + SCOREBOARD_HEADER_HEIGHT + rowHeight + 10, playersToSkip / ( #g_players - playersPerPage + 1 ) )
end
--[[
* isVisible
Returns wherever or not the scoreboard is visible
--]]
function isVisible ( )
	return g_isShowing
end
addCommandHandler("afk",
	function ( )
		local data = getElementData(localPlayer, "isAFK")
		if ( data == false ) then
			setElementData(localPlayer, "isAFK", "AFK")
			outputChatBox("Your status now is afk.", 255, 255, 255, true)
		else
			outputChatBox("Your status now is online.", 255, 255, 255, true)
			setElementData(localPlayer, "isAFK", "Online")
		end
	end
)

 

Edited by N3xT
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...