AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 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 طبق اللي قلت عليه .. ترا مجربه الحين ذذ Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 1 minute ago, Killer Project said: طبق اللي قلت عليه .. ترا مجربه الحين ذذ اعمل /afk ولا اسيبو فترة |؟ Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 9 hours ago, Jack Tom said: اعمل /afk ولا اسيبو فترة |؟ بص اعمل ملف meta.xml واعمل ملف server.lua ضيف ملف السيرفر داخل الميتا طبيعي وضيف الكود اللي ارسلته لك في ملف سيرفر واكتب في اف 8 afk او AFK اذا كنت افك مارح تكون افك واذا ما كنت افك رح تكون افك Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 Just now, Killer Project said: بص اعمل ملف meta.xml واعمل ملف server.lua ضيف ملف السيرفر داخل الميتا طبيعي وضيف الكود اللي ارسلته لك في ملف سيرفر واكتب في اف 8 afk او AFK اذا كنت افك مارح تكون افك واذا ما كنت افك رح تكون افك بس برضو ما بيظهر في تاب Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 9 hours ago, Jack Tom said: بس برضو ما بيظهر في تاب اطرح ملف الميتا ذذ Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 Just now, Killer Project said: اطرح ملف الميتا ذذ <meta> <info author="TEst" name="AFK Script" version="1.0.0" type="script"/> <script src="server.lua" type="server" /> </meta> اهوز Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 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
Master_MTA Posted April 13, 2017 Share Posted April 13, 2017 2 minutes ago, Jack Tom said: <meta> <info author="TEst" name="AFK Script" version="1.0.0" type="script"/> <script src="server.lua" type="server" /> </meta> اهوز انت حياه واقعيه اطرح سكوربورد حقك Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 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
Master_MTA Posted April 13, 2017 Share Posted April 13, 2017 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
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 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
Master_MTA Posted April 13, 2017 Share Posted April 13, 2017 (edited) 2 minutes ago, Jack Tom said: ممكن تحط المود كلو في رابط و ترفعو لو سمحت @Killer Project ? الميتا اطرحها كامله Edited April 13, 2017 by Master_MTA Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 Just now, Master_MTA said: ? الميتا اطرحها <meta> <info author="Alberto 'ryden' Alonso" type="script" version="1.0" /> <script src="c_tab.lua" type="client" /> <script src="s_tab.lua" type="server" /> <file src="icon.png"/> <export function="isVisible" type="client" /> </meta> meta Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 9 hours ago, Jack Tom said: ممكن تحط المود كلو في رابط و ترفعو لو سمحت @Killer Project ركز في كلام الاخ ماستر شوية وعموماً اهو الرابطhttps://up.top4top.net/downloadf-4683crkq1-zip.html Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 8 minutes ago, Killer Project said: ركز في كلام الاخ ماستر شوية وعموماً اهو الرابطhttps://up.top4top.net/downloadf-4683crkq1-zip.html برضو ما اشتغل Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 9 hours ago, Jack Tom said: برضو ما اشتغل انت عندك مود السكور بورد اسمه اي بالضبط ؟ اللي انت مشغله يعني Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 Just now, Killer Project said: انت عندك مود السكور بورد اسمه اي بالضبط ؟ اللي انت مشغله يعني scoreboard Link to comment
AHMED MOSTAFA Posted April 13, 2017 Share Posted April 13, 2017 9 hours ago, Jack Tom said: scoreboard مدري صراحة .. سوي اشارة لأحد الاشخاص وخله يجرب الكود اللي ارسلته لك اذا نفس المشكلة اذن المشكلة عندي واذا لا وهذا الشي المتوقع فالمشكلة بتكون عندك لأني مجرب الكود قبل ما ارسله لك Link to comment
mohamed hussein Posted April 13, 2017 Author Share Posted April 13, 2017 17 minutes ago, Killer Project said: مدري صراحة .. سوي اشارة لأحد الاشخاص وخله يجرب الكود اللي ارسلته لك اذا نفس المشكلة اذن المشكلة عندي واذا لا وهذا الشي المتوقع فالمشكلة بتكون عندك لأني مجرب الكود قبل ما ارسله لك خلاص اخي مشكور لا تاكل هم Link to comment
Master_MTA Posted April 13, 2017 Share Posted April 13, 2017 1 hour ago, Jack Tom said: خلاص اخي مشكور لا تاكل هم سكوربورد الخاص فيك مافيه فنكشن متسويله اكسبورت لاضافة كولمن يبيلك تعدل عليه والله اعلم Link to comment
N3xT Posted April 13, 2017 Share Posted April 13, 2017 جرب استبدل الكلنت حق السكوربورد حقك بذا وأمر الافك 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
Abdul KariM Posted April 14, 2017 Share Posted April 14, 2017 @N3xT بالكلينت مافيه بارتمر لاعب Link to comment
N3xT Posted April 14, 2017 Share Posted April 14, 2017 (edited) 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 April 14, 2017 by N3xT Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now