Guest User

Untitled

a guest
Dec 9th, 2012
60
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- THESE CAN BE CHANGED
  2. triggerKey = "tab" -- default button to open/close scoreboard
  3. settingsKey = "F7" -- default button to open the settings window
  4. drawOverGUI = true -- draw scoreboard over gui?
  5. seperationSpace = 80 -- the space between top/bottom screen and scoreboard top/bottom in pixels
  6.  
  7. -- BUT DON'T TOUCH THESE
  8. scoreboardToggled = false
  9. scoreboardForced = false
  10. scoreboardDrawn = false
  11. forceScoreboardUpdate = false
  12. useAnimation = true
  13. scoreboardIsToggleable = false
  14. showServerInfo = false
  15. showGamemodeInfo = false
  16. showTeams = true
  17. useColors = true
  18. drawSpeed = 1
  19. scoreboardScale = 1
  20. teamHeaderFont = "clear"
  21. contentFont = "default-bold"
  22. columnFont = "default-bold"
  23. serverInfoFont = "default"
  24. rmbFont = "clear"
  25. cBlack = tocolor( 0, 0, 0 )
  26. cWhite = tocolor( 255, 255, 255 )
  27. cSettingsBox = tocolor( 255, 255, 255, 150 )
  28. MAX_PRIRORITY_SLOT = 500
  29.  
  30. scoreboardColumns = {}
  31. resourceColumns = {}
  32. scoreboardDimensions = { ["width"] = 0, ["height"] = 0, ["phase"] = 1, ["lastSeconds"] = 0 }
  33. scoreboardTicks = { ["lastUpdate"] = 0, ["updateInterval"] = 500 }
  34. scoreboardContent = {}
  35. firstVisibleIndex = 1
  36. sortBy = { ["what"] = "__NONE__", ["dir"] = -1 } -- -1 = dec, 1 = asc
  37. sbOutOffset, sbInOffset = 1, 1
  38. sbFont = "clear"
  39. sbFontScale = 0.68
  40. serverInfo = {}
  41. fontScale = { -- To make all fonts be equal in height
  42. ["default"] = 1.0,
  43. ["default-bold"] = 1.0,
  44. ["clear"] = 1.0,
  45. ["arial"] = 1.0,
  46. ["sans"] = 1.0,
  47. ["pricedown"] = 0.5,
  48. ["bankgothic"] = 0.55,
  49. ["diploma"] = 0.5,
  50. ["beckett"] = 0.5
  51. }
  52. selectedRows = {}
  53.  
  54. addEvent( "onClientPlayerScoreboardClick" )
  55.  
  56. addEventHandler( "onClientResourceStart", getResourceRootElement( getThisResource() ),
  57. function ( resource )
  58. cScoreboardBackground = tocolor( defaultSettings.bg_color.r, defaultSettings.bg_color.g, defaultSettings.bg_color.b, defaultSettings.bg_color.a )
  59. cSelection = tocolor( defaultSettings.selection_color.r, defaultSettings.selection_color.g, defaultSettings.selection_color.b, defaultSettings.selection_color.a )
  60. cHighlight = tocolor( defaultSettings.highlight_color.r, defaultSettings.highlight_color.g, defaultSettings.highlight_color.b, defaultSettings.highlight_color.a )
  61. cHeader = tocolor( 255,174,255, defaultSettings.header_color.a )
  62. cTeam = tocolor( defaultSettings.team_color.r, defaultSettings.team_color.g, defaultSettings.team_color.b, defaultSettings.team_color.a )
  63. cBorder = tocolor( defaultSettings.border_color.r, defaultSettings.border_color.g, defaultSettings.border_color.b, defaultSettings.border_color.a )
  64. cServerInfo = tocolor( defaultSettings.serverinfo_color.r, defaultSettings.serverinfo_color.g, defaultSettings.serverinfo_color.b, defaultSettings.serverinfo_color.a )
  65. cContent = tocolor( defaultSettings.content_color.r, defaultSettings.content_color.g, defaultSettings.content_color.b, defaultSettings.content_color.a )
  66.  
  67. bindKey( triggerKey, "down", "Toggle scoreboard", "1" )
  68. bindKey( triggerKey, "up", "Toggle scoreboard", "0" )
  69. bindKey( settingsKey, "down", "Open scoreboard settings", "1" )
  70.  
  71. addEventHandler( "onClientRender", getRootElement(), drawScoreboard )
  72. triggerServerEvent( "onClientDXScoreboardResourceStart", getRootElement() )
  73. readScoreboardSettings()
  74. triggerServerEvent( "requestServerInfo", getRootElement() )
  75.  
  76. colorPicker.constructor()
  77. end
  78. )
  79.  
  80. addEventHandler( "onClientPlayerQuit", getRootElement(),
  81. function()
  82. selectedRows[source] = nil
  83. end
  84. )
  85.  
  86. function sendServerInfo( output )
  87. serverInfo = output
  88. end
  89. addEvent( "sendServerInfo", true )
  90. addEventHandler( "sendServerInfo", getResourceRootElement( getThisResource() ), sendServerInfo )
  91.  
  92. function toggleScoreboard( _, state )
  93. state = iif( state == "1", true, false )
  94. if scoreboardIsToggleable and state then
  95. scoreboardToggled = not scoreboardToggled
  96. elseif not scoreboardIsToggleable then
  97. scoreboardToggled = state
  98. end
  99. end
  100. addCommandHandler( "Toggle scoreboard", toggleScoreboard )
  101.  
  102. function openSettingsWindow()
  103. if scoreboardDrawn then
  104. local sX, sY = guiGetScreenSize()
  105. if not (windowSettings and isElement( windowSettings ) and guiGetVisible( windowSettings )) then
  106. createScoreboardSettingsWindow( sX-323, sY-350 )
  107. showCursor( true )
  108. elseif isElement( windowSettings ) then
  109. destroyScoreboardSettingsWindow()
  110. end
  111. end
  112. end
  113. addCommandHandler( "Open scoreboard settings", openSettingsWindow )
  114.  
  115. addCommandHandler( "scoreboard",
  116. function ()
  117. scoreboardToggled = not scoreboardToggled
  118. end
  119. )
  120.  
  121. function iif( cond, arg1, arg2 )
  122. if cond then
  123. return arg1
  124. end
  125. return arg2
  126. end
  127.  
  128. function drawScoreboard()
  129. local sX, sY = guiGetScreenSize()
  130. if #scoreboardColumns ~= 0 then
  131.  
  132. local currentSeconds = getTickCount() / 1000
  133. local deltaSeconds = currentSeconds - scoreboardDimensions.lastSeconds
  134. scoreboardDimensions.lastSeconds = currentSeconds
  135. deltaSeconds = math.clamp( 0, deltaSeconds, 1/25 )
  136.  
  137. if scoreboardToggled or scoreboardForced then
  138. local phases = {
  139. [1] = {
  140. ["width"] = s(10),
  141. ["height"] = s(5),
  142.  
  143. ["incToWidth"] = s(10),
  144. ["incToHeight"] = s(5),
  145.  
  146. ["decToWidth"] = 0,
  147. ["decToHeight"] = 0
  148. },
  149. [2] = {
  150. ["width"] = s(40),
  151. ["height"] = s(5),
  152.  
  153. ["incToWidth"] = calculateWidth(),
  154. ["incToHeight"] = s(5),
  155.  
  156. ["decToWidth"] = s(10),
  157. ["decToHeight"] = s(5)
  158.  
  159. },
  160. [3] = {
  161. ["width"] = calculateWidth(),
  162. ["height"] = s(30),
  163.  
  164. ["incToWidth"] = calculateWidth(),
  165. ["incToHeight"] = calculateHeight(),
  166.  
  167. ["decToWidth"] = calculateWidth(),
  168. ["decToHeight"] = s(5)
  169. }
  170. }
  171.  
  172. if not useAnimation then
  173. scoreboardDimensions.width = calculateWidth()
  174. scoreboardDimensions.height = calculateHeight()
  175. scoreboardDimensions.phase = #phases
  176. end
  177.  
  178. local maxChange = deltaSeconds * 30*drawSpeed
  179. local maxWidthDiff = math.clamp( -maxChange, phases[scoreboardDimensions.phase].incToWidth - scoreboardDimensions.width, maxChange )
  180. local maxHeightDiff = math.clamp( -maxChange, phases[scoreboardDimensions.phase].incToHeight - scoreboardDimensions.height, maxChange )
  181.  
  182. if scoreboardDimensions.width < phases[scoreboardDimensions.phase].incToWidth then
  183. scoreboardDimensions.width = scoreboardDimensions.width + maxWidthDiff * phases[scoreboardDimensions.phase].width
  184. if scoreboardDimensions.width > phases[scoreboardDimensions.phase].incToWidth then
  185. scoreboardDimensions.width = phases[scoreboardDimensions.phase].incToWidth
  186. end
  187. elseif scoreboardDimensions.width > phases[scoreboardDimensions.phase].incToWidth and not scoreboardDrawn then
  188. scoreboardDimensions.width = scoreboardDimensions.width - maxWidthDiff * phases[scoreboardDimensions.phase].width
  189. if scoreboardDimensions.width < phases[scoreboardDimensions.phase].incToWidth then
  190. scoreboardDimensions.width = phases[scoreboardDimensions.phase].incToWidth
  191. end
  192. end
  193.  
  194. if scoreboardDimensions.height < phases[scoreboardDimensions.phase].incToHeight then
  195. scoreboardDimensions.height = scoreboardDimensions.height + maxHeightDiff * phases[scoreboardDimensions.phase].height
  196. if scoreboardDimensions.height > phases[scoreboardDimensions.phase].incToHeight then
  197. scoreboardDimensions.height = phases[scoreboardDimensions.phase].incToHeight
  198. end
  199. elseif scoreboardDimensions.height > phases[scoreboardDimensions.phase].incToHeight and not scoreboardDrawn then
  200. scoreboardDimensions.height = scoreboardDimensions.height - maxHeightDiff * phases[scoreboardDimensions.phase].height
  201. if scoreboardDimensions.height < phases[scoreboardDimensions.phase].incToHeight then
  202. scoreboardDimensions.height = phases[scoreboardDimensions.phase].incToHeight
  203. end
  204. end
  205.  
  206. if scoreboardDimensions.width == phases[scoreboardDimensions.phase].incToWidth and
  207. scoreboardDimensions.height == phases[scoreboardDimensions.phase].incToHeight then
  208. if phases[scoreboardDimensions.phase + 1] then
  209. scoreboardDimensions.phase = scoreboardDimensions.phase + 1
  210. else
  211. if not scoreboardDrawn then
  212. bindKey( "mouse2", "both", showTheCursor )
  213. bindKey( "mouse_wheel_up", "down", scrollScoreboard, -1 )
  214. bindKey( "mouse_wheel_down", "down", scrollScoreboard, 1 )
  215. addEventHandler( "onClientClick", getRootElement(), scoreboardClickHandler )
  216. if not (windowSettings and isElement( windowSettings )) then
  217. showCursor( false )
  218. end
  219. triggerServerEvent( "requestServerInfo", getRootElement() )
  220. end
  221. scoreboardDrawn = true
  222. end
  223. end
  224. elseif scoreboardDimensions.width ~= 0 and scoreboardDimensions.height ~= 0 then
  225. local phases = {
  226. [1] = {
  227. ["width"] = s(10),
  228. ["height"] = s(5),
  229.  
  230. ["incToWidth"] = s(10),
  231. ["incToHeight"] = s(5),
  232.  
  233. ["decToWidth"] = 0,
  234. ["decToHeight"] = 0
  235. },
  236. [2] = {
  237. ["width"] = s(40),
  238. ["height"] = s(5),
  239.  
  240. ["incToWidth"] = calculateWidth(),
  241. ["incToHeight"] = s(5),
  242.  
  243. ["decToWidth"] = s(10),
  244. ["decToHeight"] = s(5)
  245.  
  246. },
  247. [3] = {
  248. ["width"] = calculateWidth(),
  249. ["height"] = s(30),
  250.  
  251. ["incToWidth"] = calculateWidth(),
  252. ["incToHeight"] = calculateHeight(),
  253.  
  254. ["decToWidth"] = calculateWidth(),
  255. ["decToHeight"] = s(5)
  256. }
  257. }
  258.  
  259. if scoreboardDrawn then
  260. unbindKey( "mouse2", "both", showTheCursor )
  261. unbindKey( "mouse_wheel_up", "down", scrollScoreboard, -1 )
  262. unbindKey( "mouse_wheel_down", "down", scrollScoreboard, 1 )
  263. removeEventHandler( "onClientClick", getRootElement(), scoreboardClickHandler )
  264. if not (windowSettings and isElement( windowSettings )) then
  265. showCursor( false )
  266. end
  267. end
  268. scoreboardDrawn = false
  269.  
  270. if not useAnimation then
  271. scoreboardDimensions.width = 0
  272. scoreboardDimensions.height = 0
  273. scoreboardDimensions.phase = 1
  274. end
  275.  
  276. local maxChange = deltaSeconds * 30*drawSpeed
  277. local maxWidthDiff = math.clamp( -maxChange, scoreboardDimensions.width - phases[scoreboardDimensions.phase].decToWidth, maxChange )
  278. local maxHeightDiff = math.clamp( -maxChange, scoreboardDimensions.height - phases[scoreboardDimensions.phase].decToHeight, maxChange )
  279.  
  280. if scoreboardDimensions.width > phases[scoreboardDimensions.phase].decToWidth then
  281. scoreboardDimensions.width = scoreboardDimensions.width - maxWidthDiff * phases[scoreboardDimensions.phase].width
  282. if scoreboardDimensions.width < phases[scoreboardDimensions.phase].decToWidth then
  283. scoreboardDimensions.width = phases[scoreboardDimensions.phase].decToWidth
  284. end
  285. elseif scoreboardDimensions.width < phases[scoreboardDimensions.phase].decToWidth then
  286. scoreboardDimensions.width = scoreboardDimensions.width - maxWidthDiff * phases[scoreboardDimensions.phase].width
  287. if scoreboardDimensions.width > phases[scoreboardDimensions.phase].decToWidth then
  288. scoreboardDimensions.width = phases[scoreboardDimensions.phase].decToWidth
  289. end
  290. end
  291.  
  292. if scoreboardDimensions.height > phases[scoreboardDimensions.phase].decToHeight then
  293. scoreboardDimensions.height = scoreboardDimensions.height - maxHeightDiff * phases[scoreboardDimensions.phase].height
  294. if scoreboardDimensions.height < phases[scoreboardDimensions.phase].decToHeight then
  295. scoreboardDimensions.height = phases[scoreboardDimensions.phase].decToHeight
  296. end
  297. elseif scoreboardDimensions.height < phases[scoreboardDimensions.phase].decToHeight then
  298. scoreboardDimensions.height = scoreboardDimensions.height - maxHeightDiff * phases[scoreboardDimensions.phase].height
  299. if scoreboardDimensions.height > phases[scoreboardDimensions.phase].decToHeight then
  300. scoreboardDimensions.height = phases[scoreboardDimensions.phase].decToHeight
  301. end
  302. end
  303.  
  304. if scoreboardDimensions.width == phases[scoreboardDimensions.phase].decToWidth and
  305. scoreboardDimensions.height == phases[scoreboardDimensions.phase].decToHeight and
  306. scoreboardDimensions.width ~= 0 and scoreboardDimensions.height ~= 0 then
  307.  
  308. scoreboardDimensions.phase = scoreboardDimensions.phase - 1
  309. if scoreboardDimensions.phase < 1 then scoreboardDimensions.phase = 1 end
  310. end
  311. end
  312.  
  313. if scoreboardDimensions.width ~= 0 and scoreboardDimensions.height ~= 0 then
  314. dxDrawRectangle( (sX/2)-(scoreboardDimensions.width/2), (sY/2)-(scoreboardDimensions.height/2), scoreboardDimensions.width, scoreboardDimensions.height, cScoreboardBackground, drawOverGUI )
  315. end
  316.  
  317. -- Update the scoreboard content
  318. local currentTick = getTickCount()
  319. if (currentTick - scoreboardTicks.lastUpdate > scoreboardTicks.updateInterval and (scoreboardToggled or scoreboardForced)) or forceScoreboardUpdate then
  320. forceScoreboardUpdate = false
  321. scoreboardContent = {}
  322. local index = 1
  323.  
  324. local sortTableIndex = 1
  325. local sortTable = {}
  326.  
  327. local players = getElementsByType( "player" )
  328. for key, player in ipairs( players ) do
  329. if not getPlayerTeam( player ) or not (showTeams or (serverInfo.forceshowteams and not serverInfo.forcehideteams)) or serverInfo.forcehideteams then
  330. sortTable[sortTableIndex] = {}
  331. for key, column in ipairs( scoreboardColumns ) do
  332. local content
  333. if column.name == "name" then
  334. local playerName = getPlayerName( player )
  335. if serverInfo.allowcolorcodes then
  336. if string.find( playerName, "#%x%x%x%x%x%x" ) then
  337. local colorCodes = {}
  338. while( string.find( playerName, "#%x%x%x%x%x%x" ) ) do
  339. local startPos, endPos = string.find( playerName, "#%x%x%x%x%x%x" )
  340. if startPos then
  341. colorCode = string.sub( playerName, startPos, endPos )
  342. table.insert( colorCodes, { { getColorFromString( colorCode ) }, startPos } )
  343. playerName = string.gsub( playerName, "#%x%x%x%x%x%x", "", 1 )
  344. end
  345. end
  346. content = { playerName, colorCodes }
  347. else
  348. content = playerName
  349. end
  350. else
  351. content = playerName
  352. end
  353. elseif column.name == "ping" then
  354. content = getPlayerPing( player )
  355. -- Edit by NeXTreme
  356. elseif column.name == "countryName" then
  357. local countryName = getElementData( player, column.name)
  358. if type(countryName) == "string" then
  359. content = getElementData( player, column.name)
  360. else
  361. content = "N/A"
  362. end
  363.  
  364. elseif column.name == "countryCode" then
  365. local countryCode = getElementData( player, column.name)
  366. if type(countryCode) == "string" then
  367. content = getElementData( player, column.name)
  368. else
  369. content = "N/A"
  370. end
  371. -------------------
  372. -- `flag image` addon by MX_Master
  373. elseif column.name == " flag" then
  374. content = getElementData( player, 'countryFlagImage' )
  375. if type(content) ~= 'string' then content = '' end
  376. --
  377. else
  378. content = getElementData( player, column.name )
  379. end
  380.  
  381. content = iif( content and column.name ~= "name" and type( content ) ~= "table", tostring( content ), content )
  382. if column.textFunction then
  383. if content and column.name == "name" and type( content ) == "table" then
  384. content[1] = column.textFunction( content[1], player )
  385. else
  386. content = column.textFunction( content, player )
  387. end
  388. end
  389. sortTable[sortTableIndex][column.name] = content
  390. sortTable[sortTableIndex]["__SCOREBOARDELEMENT__"] = player
  391. end
  392. sortTableIndex = sortTableIndex + 1
  393. end
  394. end
  395. if sortBy.what ~= "__NONE__" then table.sort( sortTable, scoreboardSortFunction ) end
  396. for key, value in ipairs( sortTable ) do
  397. scoreboardContent[index] = value
  398. index = index + 1
  399. end
  400.  
  401. if (showTeams or (serverInfo.forceshowteams and not serverInfo.forcehideteams)) and not serverInfo.forcehideteams then
  402. -- And then the teams
  403. local teamSortTableIndex = 1
  404. local teamSortTable = {}
  405. sortTableIndex = 1
  406. sortTable = {}
  407. local teams = getElementsByType( "team" )
  408. for key, team in ipairs( teams ) do
  409.  
  410. -- Add teams to sorting table first
  411. teamSortTable[teamSortTableIndex] = {}
  412. for key, column in ipairs( scoreboardColumns ) do
  413. local content
  414. if column.name == "name" then
  415. local teamName = getTeamName( team )
  416. local teamMemberCount = #getPlayersInTeam( team )
  417. teamName = iif( teamName, tostring( teamName ), "-" )
  418. teamMemberCount = iif( teamMemberCount, tostring( teamMemberCount ), "0" )
  419. teamName = teamName --[[.. " (" .. teamMemberCount .. " player" .. iif( teamMemberCount == "1", "", "s" ) .. ")"--]]
  420. if serverInfo.allowcolorcodes then
  421. if string.find( teamName, "#%x%x%x%x%x%x" ) then
  422. local colorCodes = {}
  423. while( string.find( teamName, "#%x%x%x%x%x%x" ) ) do
  424. local startPos, endPos = string.find( teamName, "#%x%x%x%x%x%x" )
  425. if startPos then
  426. colorCode = string.sub( teamName, startPos, endPos )
  427. table.insert( colorCodes, { { getColorFromString( colorCode ) }, startPos } )
  428. teamName = string.gsub( teamName, "#%x%x%x%x%x%x", "", 1 )
  429. end
  430. end
  431. content = { teamName, colorCodes }
  432. else
  433. content = teamName
  434. end
  435. else
  436. content = teamName
  437. end
  438. else
  439. content = getElementData( team, column.name )
  440. end
  441. content = iif( content and column.name ~= "name" and type( content ) ~= "table", tostring( content ), content )
  442. if column.textFunction then
  443. if content and column.name == "name" and type( content ) == "table" then
  444. content[1] = column.textFunction( content[1], team )
  445. else
  446. content = column.textFunction( content, team )
  447. end
  448. end
  449. teamSortTable[teamSortTableIndex][column.name] = content
  450. teamSortTable[teamSortTableIndex]["__SCOREBOARDELEMENT__"] = team
  451. end
  452. teamSortTableIndex = teamSortTableIndex + 1
  453.  
  454. -- and then the players
  455. sortTableIndex = 1
  456. sortTable[team] = {}
  457. local players = getPlayersInTeam( team )
  458. for key, player in ipairs( players ) do
  459. sortTable[team][sortTableIndex] = {}
  460. for key, column in ipairs( scoreboardColumns ) do
  461. local content
  462. if column.name == "name" then
  463. local playerName = getPlayerName( player )
  464. if serverInfo.allowcolorcodes then
  465. if string.find( playerName, "#%x%x%x%x%x%x" ) then
  466. local colorCodes = {}
  467. while( string.find( playerName, "#%x%x%x%x%x%x" ) ) do
  468. local startPos, endPos = string.find( playerName, "#%x%x%x%x%x%x" )
  469. if startPos then
  470. colorCode = string.sub( playerName, startPos, endPos )
  471. table.insert( colorCodes, { { getColorFromString( colorCode ) }, startPos } )
  472. playerName = string.gsub( playerName, "#%x%x%x%x%x%x", "", 1 )
  473. end
  474. end
  475. content = { playerName, colorCodes }
  476. else
  477. content = playerName
  478. end
  479. else
  480. content = playerName
  481. end
  482. elseif column.name == "ping" then
  483. content = getPlayerPing( player )
  484. -- `flag image` addon by MX_Master
  485. elseif column.name == " flag" then
  486. content = getElementData( player, 'countryFlagImage' )
  487. if type(content) ~= 'string' then content = '' end
  488. --
  489. else
  490. content = getElementData( player, column.name )
  491. end
  492. content = iif( content and column.name ~= "name" and type( content ) ~= "table", tostring( content ), content )
  493. if column.textFunction then
  494. if content and column.name == "name" and type( content ) == "table" then
  495. content[1] = column.textFunction( content[1], player )
  496. else
  497. content = column.textFunction( content, player )
  498. end
  499. end
  500. sortTable[team][sortTableIndex][column.name] = content
  501. sortTable[team][sortTableIndex]["__SCOREBOARDELEMENT__"] = player
  502. end
  503. sortTableIndex = sortTableIndex + 1
  504. end
  505. if sortBy.what ~= "__NONE__" then table.sort( sortTable[team], scoreboardSortFunction ) end
  506. end
  507. if sortBy.what ~= "__NONE__" then table.sort( teamSortTable, scoreboardSortFunction ) end
  508. for key, content in ipairs( teamSortTable ) do
  509. local team = content["__SCOREBOARDELEMENT__"]
  510. scoreboardContent[index] = content
  511. index = index + 1
  512.  
  513. for key, value in ipairs( sortTable[team] ) do
  514. scoreboardContent[index] = value
  515. index = index + 1
  516. end
  517. end
  518. end
  519. scoreboardTicks.lastUpdate = currentTick
  520. end
  521.  
  522. if scoreboardDrawn then
  523. scoreboardDimensions.height = calculateHeight()
  524. scoreboardDimensions.width = calculateWidth()
  525.  
  526. local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2)
  527. local index = firstVisibleIndex
  528. local maxPerWindow = getMaxPerWindow()
  529.  
  530. if firstVisibleIndex > #scoreboardContent-maxPerWindow+1 then
  531. firstVisibleIndex = 1
  532. end
  533.  
  534. if firstVisibleIndex > 1 then
  535. dxDrawImage( sX/2-8, topY-15, 17, 11, "arrow.png", 0, 0, 0, cWhite, drawOverGUI )
  536. end
  537. if firstVisibleIndex+maxPerWindow <= #scoreboardContent and #scoreboardContent > maxPerWindow then
  538. dxDrawImage( sX/2-8, topY+scoreboardDimensions.height+4, 17, 11, "arrow.png", 180, 0, 0, cWhite, drawOverGUI )
  539. end
  540.  
  541. local y = topY+s(5)
  542. if serverInfo.server and showServerInfo then
  543. dxDrawText( "Server: " .. serverInfo.server, topX+s(5), y, topX+scoreboardDimensions.width-s(10), y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ), cServerInfo, fontscale(serverInfoFont, s(0.75)), serverInfoFont, "left", "top", false, false, drawOverGUI )
  544. end
  545. if serverInfo.players and showServerInfo then
  546. local players = getElementsByType( "player" )
  547. local text = "Players: " .. tostring( #players ) .. "/" .. serverInfo.players
  548. local textWidth = dxGetTextWidth( text, fontscale(serverInfoFont, s(0.75)), serverInfoFont )
  549. dxDrawText( text, topX+scoreboardDimensions.width-s(5)-textWidth, y, topX+scoreboardDimensions.width-s(5), y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ), cServerInfo, fontscale(serverInfoFont, s(0.75)), serverInfoFont, "left", "top", false, false, drawOverGUI )
  550. end
  551. if (serverInfo.server or serverInfo.players) and showServerInfo then y = y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  552. if serverInfo.gamemode and showGamemodeInfo then
  553. dxDrawText( "Gamemode: " .. serverInfo.gamemode, topX+s(5), y, topX+scoreboardDimensions.width-s(10), y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ), cServerInfo, fontscale(serverInfoFont, s(0.75)), serverInfoFont, "left", "top", false, false, drawOverGUI )
  554. end
  555. if serverInfo.map and showGamemodeInfo then
  556. local text = "Map: " .. serverInfo.map
  557. local textWidth = dxGetTextWidth( text, fontscale(serverInfoFont, s(0.75)), serverInfoFont )
  558. dxDrawText( text, topX+scoreboardDimensions.width-s(5)-textWidth, y, topX+scoreboardDimensions.width-s(5), y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ), cServerInfo, fontscale(serverInfoFont, s(0.75)), serverInfoFont, "left", "top", false, false, drawOverGUI )
  559. end
  560. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then y = y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  561. y = y+s(3)
  562.  
  563. local textLength = dxGetTextWidth( "Hold RMB to enable scrolling/sorting", fontscale(rmbFont, s(0.75)), rmbFont )
  564. local textHeight = dxGetFontHeight( fontscale(rmbFont, s(0.75)), rmbFont )
  565. dxDrawText( "Hold RMB to enable scrolling/sorting", sX/2-(textLength/2), topY+scoreboardDimensions.height-textHeight-s(2), sX/2+(textLength/2), topY+scoreboardDimensions.height-s(2), cWhite, fontscale(serverInfoFont, s(0.75)), rmbFont, "left", "top", false, false, drawOverGUI )
  566.  
  567. local bottomX, bottomY = topX+scoreboardDimensions.width, topY+scoreboardDimensions.height
  568. textLength = dxGetTextWidth( "settings...", fontscale(sbFont, s(sbFontScale)), sbFont )
  569. textHeight = dxGetFontHeight( fontscale(sbFont, s(sbFontScale)), sbFont )
  570. dxDrawText( "settings...", bottomX-s(sbOutOffset+1+sbInOffset)-textLength, bottomY-s(sbOutOffset+1+sbInOffset)-textHeight, bottomX-s(sbOutOffset+1+sbInOffset), bottomY-s(sbOutOffset+1+sbInOffset), cSettingsBox, fontscale(sbFont, s(sbFontScale)), sbFont, "left", "top", false, false, drawOverGUI )
  571. dxDrawLine( bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength, bottomY-s(sbOutOffset+2*sbInOffset+1)-textHeight, bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength, bottomY-s(sbOutOffset+1), cSettingsBox, 1, drawOverGUI )
  572. dxDrawLine( bottomX-s(sbOutOffset+1), bottomY-s(sbOutOffset+2*sbInOffset+1)-textHeight, bottomX-s(sbOutOffset+1), bottomY-s(sbOutOffset+1), cSettingsBox, 1, drawOverGUI )
  573. dxDrawLine( bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength, bottomY-s(sbOutOffset+2*sbInOffset+1)-textHeight, bottomX-s(sbOutOffset+1), bottomY-s(sbOutOffset+2*sbInOffset+1)-textHeight, cSettingsBox, 1, drawOverGUI )
  574. dxDrawLine( bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength, bottomY-s(sbOutOffset+1), bottomX-s(sbOutOffset+1), bottomY-s(sbOutOffset+1), cSettingsBox, 1, drawOverGUI )
  575.  
  576. local x = s(10)
  577. for key, column in ipairs( scoreboardColumns ) do
  578. if x ~= s(10) then
  579. local height = s(5)
  580. if (serverInfo.server or serverInfo.players) and showServerInfo then height = height+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  581. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then height = height+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  582. height = height+s(3)
  583. dxDrawLine( topX+x-s(5), y+s(1), topX+x-s(5), y+scoreboardDimensions.height-height-s(2)-textHeight-s(5), cBorder, s(1), drawOverGUI )
  584. end
  585. if sortBy.what == column.name then
  586. local _, _, _, a = fromcolor( cHeader )
  587. dxDrawText( column.friendlyName or "-", topX+x+s(1+9), y+s(1), topX+x+s(1+column.width), y+s(1)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), tocolor( 0, 0, 0, a ), fontscale(columnFont, s(1)), columnFont, "left", "top", true, false, drawOverGUI )
  588. dxDrawText( column.friendlyName or "-", topX+x+s(9), y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), cHeader, fontscale(columnFont, s(1)), columnFont, "left", "top", true, false, drawOverGUI )
  589. dxDrawRectangle( topX+x, iif( sortBy.dir == 1, y+s(8), y+s(6) ), s(5), s(1), cWhite, drawOverGUI )
  590. dxDrawRectangle( topX+x+s(1), y+s(7), s(3), s(1), cWhite, drawOverGUI )
  591. dxDrawRectangle( topX+x+s(2), iif( sortBy.dir == 1, y+s(6), y+s(8) ), s(1), s(1), cWhite, drawOverGUI )
  592. else
  593. local _, _, _, a = fromcolor( cHeader )
  594. dxDrawText( column.friendlyName or "-", topX+x+s(1), y+s(1), topX+x+s(1+column.width), y+s(1)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), tocolor( 0, 0, 0, a ), fontscale(columnFont, s(1)), columnFont, "left", "top", true, false, drawOverGUI )
  595. dxDrawText( column.friendlyName or "-", topX+x, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), cHeader, fontscale(columnFont, s(1)), columnFont, "left", "top", true, false, drawOverGUI )
  596. end
  597. x = x + s(column.width + 10)
  598. end
  599. dxDrawLine( topX+s(5), y+s(1)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), topX+scoreboardDimensions.width-s(5), y+s(1)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), cBorder, s(1), true )
  600.  
  601. y = y+s(5)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont )
  602. while ( index < firstVisibleIndex+maxPerWindow and scoreboardContent[index] ) do
  603. local x = s(10)
  604. local element = scoreboardContent[index]["__SCOREBOARDELEMENT__"]
  605.  
  606. if element and isElement( element ) and getElementType( element ) == "team" then
  607. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), cTeam, drawOverGUI )
  608. -- Highlight the the row on which the cursor lies on
  609. if isCursorShowing() then
  610. local cX, cY = getCursorPosition()
  611. local sX, sY = guiGetScreenSize()
  612. cX, cY = cX*sX, cY*sY
  613. if cX >= topX+s(5) and cX <= topX+scoreboardDimensions.width-s(5) and cY >= y and cY <= y+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ) then
  614. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), cHighlight, drawOverGUI )
  615. end
  616. end
  617. -- Highlight selected row
  618. if selectedRows[element] then
  619. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), cHighlight, drawOverGUI )
  620. end
  621.  
  622. for key, column in ipairs( scoreboardColumns ) do
  623. local r, g, b, a = fromcolor( cContent )
  624. if not useColors then
  625. r, g, b = 255, 255, 255
  626. end
  627. local theX = x
  628. local content = scoreboardContent[index][column.name]
  629. if content and column.name == "name" then
  630. if useColors then
  631. r, g, b = getTeamColor( element )
  632. end
  633. theX = x - s(3)
  634. end
  635. if content then
  636. if serverInfo.allowcolorcodes and type( content ) == "table" and column.name == "name" then
  637. local playerName = content[1]
  638. local colorCodes = content[2]
  639. local xPos = topX+theX
  640. for k, v in ipairs( colorCodes ) do
  641. local firstCodePos = v[2]
  642. local secondCodePos = colorCodes[k+1] and colorCodes[k+1][2]-1 or #playerName
  643. if firstCodePos ~= 1 and k == 1 then
  644. local secondPos = firstCodePos-1
  645. local firstPos = 1
  646. local partOfName = string.sub( playerName, firstPos, secondPos )
  647. local textLength = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont )
  648. dxDrawText( partOfName, xPos+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  649. dxDrawText( partOfName, xPos, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  650. xPos = xPos + textLength
  651. end
  652. if useColors then
  653. r, g, b = v[1][1], v[1][2], v[1][3]
  654. end
  655. local partOfName = string.sub( playerName, firstCodePos, secondCodePos )
  656. local textLength = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont )
  657. dxDrawText( partOfName, xPos+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  658. dxDrawText( partOfName, xPos, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  659. xPos = xPos + textLength
  660. end
  661. -- `flag image` addon by MX_Master
  662. elseif column.name == ' flag' and type(content) == 'string' and #content > 0 then
  663. dxDrawImage( topX+theX, y+1, 16, 11, content, 0,0,0, cWhite, drawOverGUI )
  664. --
  665. else
  666. dxDrawText( content, topX+theX+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  667. dxDrawText( content, topX+theX, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(teamHeaderFont, s(1)), teamHeaderFont, "left", "top", true, false, drawOverGUI )
  668. end
  669. end
  670. x = x + s(column.width + 10)
  671. end
  672. elseif element and isElement( element ) and getElementType( element ) == "player" then
  673. -- Highlight local player's name
  674. if element == getLocalPlayer() then
  675. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), cSelection, drawOverGUI )
  676. end
  677. -- Highlight the the row on which the cursor lies on
  678. if isCursorShowing() then
  679. local cX, cY = getCursorPosition()
  680. local sX, sY = guiGetScreenSize()
  681. cX, cY = cX*sX, cY*sY
  682. if cX >= topX+s(5) and cX <= topX+scoreboardDimensions.width-s(5) and cY >= y and cY <= y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ) then
  683. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), cHighlight, drawOverGUI )
  684. end
  685. end
  686. -- Highlight selected row
  687. if selectedRows[element] then
  688. dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), cHighlight, drawOverGUI )
  689. end
  690.  
  691. for key, column in ipairs( scoreboardColumns ) do
  692. local r, g, b, a = fromcolor( cContent )
  693. if not useColors then
  694. r, g, b = 255, 255, 255
  695. end
  696. local theX = x
  697. local content = scoreboardContent[index][column.name]
  698. if content and column.name == "name" then
  699. if useColors then
  700. r, g, b = getPlayerNametagColor( element )
  701. end
  702. if getPlayerTeam( element ) and (showTeams or (serverInfo.forceshowteams and not serverInfo.forcehideteams)) and not serverInfo.forcehideteams then theX = x + s(12) end
  703. end
  704. if content then
  705. if serverInfo.allowcolorcodes and type( content ) == "table" and column.name == "name" then
  706. local playerName = content[1]
  707. local colorCodes = content[2]
  708. local xPos = topX+theX
  709. for k, v in ipairs( colorCodes ) do
  710. local firstCodePos = v[2]
  711. local secondCodePos = colorCodes[k+1] and colorCodes[k+1][2]-1 or #playerName
  712. if firstCodePos ~= 1 and k == 1 then
  713. local secondPos = firstCodePos-1
  714. local firstPos = 1
  715. local partOfName = string.sub( playerName, firstPos, secondPos )
  716. local textLength = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont )
  717. dxDrawText( partOfName, xPos+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  718. dxDrawText( partOfName, xPos, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  719. xPos = xPos + textLength
  720. end
  721. if useColors then
  722. r, g, b = v[1][1], v[1][2], v[1][3]
  723. end
  724. local partOfName = string.sub( playerName, firstCodePos, secondCodePos )
  725. local textLength = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont )
  726. dxDrawText( partOfName, xPos+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  727. dxDrawText( partOfName, xPos, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  728. xPos = xPos + textLength
  729. end
  730. -- `flag image` addon by MX_Master
  731. elseif column.name == ' flag' and type(content) == 'string' and #content > 0 then
  732. dxDrawImage( topX+theX, y+1, 16, 11, content, 0,0,0, cWhite, drawOverGUI )
  733. --
  734. -- Edit by NeXTreme
  735. elseif column.name == "countryCode" then
  736. if content ~= "N/A" then
  737. local countryImage = "flags/"..string.lower(content)..".png"
  738. dxDrawImage(topX+theX, y+s(1)-2, 16, 16, countryImage,0,0,0,tocolor( 255,255,255,255 ), true)
  739. end
  740. else
  741. dxDrawText( content, topX+theX+s(1), y+s(1), topX+x+s(1+column.width), y+s(11)+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( 0, 0, 0, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  742. dxDrawText( content, topX+theX, y, topX+x+s(column.width), y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), tocolor( r or 255, g or 255, b or 255, a or 255 ), fontscale(contentFont, s(1)), contentFont, "left", "top", true, false, drawOverGUI )
  743. end
  744. -------
  745. end
  746. x = x + s(column.width + 10)
  747. end
  748. end
  749. local font = iif( element and isElement( element ) and getElementType( element ) == "team", teamHeaderFont, contentFont )
  750. y = y + dxGetFontHeight( fontscale(font, scoreboardScale), font )
  751. index = index + 1
  752. end
  753. index = 1
  754. end
  755. end
  756. end
  757.  
  758. -- FUNCTIONS
  759. -- addColumn
  760. function scoreboardAddColumn( name, width, friendlyName, priority, textFunction, fromResource )
  761. if type( name ) == "string" then
  762. width = width or 70
  763. friendlyName = friendlyName or name
  764. priority = tonumber( priority ) or getNextFreePrioritySlot( scoreboardGetColumnPriority( "name" ) )
  765. fixPrioritySlot( priority )
  766. textFunction = textFunction or nil
  767. fromResource = sourceResource or fromResource or nil
  768.  
  769. if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then
  770. for key, value in ipairs( scoreboardColumns ) do
  771. if name == value.name then
  772. return false
  773. end
  774. end
  775. table.insert( scoreboardColumns, { ["name"] = name, ["width"] = width, ["friendlyName"] = friendlyName, ["priority"] = priority, ["textFunction"] = textFunction } )
  776. table.sort( scoreboardColumns, function ( a, b ) return a.priority < b.priority end )
  777. if fromResource then
  778. if not resourceColumns[fromResource] then resourceColumns[fromResource] = {} end
  779. table.insert ( resourceColumns[fromResource], name )
  780. end
  781. return true
  782. end
  783. end
  784. return false
  785. end
  786.  
  787. addEvent( "doScoreboardAddColumn", true )
  788. addEventHandler( "doScoreboardAddColumn", getResourceRootElement(),
  789. function ( name, width, friendlyName, priority, fromResource )
  790. scoreboardAddColumn( name, width, friendlyName, priority, nil, fromResource )
  791. end
  792. )
  793.  
  794. -- removeColumn
  795. function scoreboardRemoveColumn( name )
  796. if type( name ) == "string" then
  797. for key, value in ipairs( scoreboardColumns ) do
  798. if name == value.name then
  799. table.remove( scoreboardColumns, key )
  800. for resource, content in pairs( resourceColumns ) do
  801. table.removevalue( content, name )
  802. end
  803. return true
  804. end
  805. end
  806. end
  807. return false
  808. end
  809.  
  810. addEvent( "doScoreboardRemoveColumn", true )
  811. addEventHandler( "doScoreboardRemoveColumn", getResourceRootElement(),
  812. function ( name )
  813. scoreboardRemoveColumn( name )
  814. end
  815. )
  816.  
  817. -- clearColumns
  818. function scoreboardClearColumns()
  819. while ( scoreboardColumns[1] ) do
  820. table.remove( scoreboardColumns, 1 )
  821. resourceColumns = {}
  822. end
  823. return true
  824. end
  825.  
  826. addEvent( "doScoreboardClearColumns", true )
  827. addEventHandler( "doScoreboardClearColumns", getResourceRootElement(),
  828. function ()
  829. scoreboardClearColumns()
  830. end
  831. )
  832.  
  833. -- resetColumns
  834. function scoreboardResetColumns( fromServer )
  835. while ( scoreboardColumns[1] ) do
  836. table.remove( scoreboardColumns, 1 )
  837. resourceColumns = {}
  838. end
  839. if not fromServer then
  840. scoreboardAddColumn( "name", 200, "Name" )
  841. scoreboardAddColumn( "ping", 40, "Ping" )
  842. end
  843. return true
  844. end
  845.  
  846. addEvent( "doScoreboardResetColumns", true )
  847. addEventHandler( "doScoreboardResetColumns", getResourceRootElement(),
  848. function ( fromServer )
  849. scoreboardResetColumns( iif( fromServer == nil, true, fromServer ) )
  850. end
  851. )
  852.  
  853. -- setForced
  854. function scoreboardSetForced( forced )
  855. scoreboardForced = forced
  856. end
  857.  
  858. addEvent( "doScoreboardSetForced", true )
  859. addEventHandler( "doScoreboardSetForced", getResourceRootElement(),
  860. function ( forced )
  861. scoreboardSetForced( forced )
  862. end
  863. )
  864.  
  865. --Compability
  866. setScoreboardForced = scoreboardSetForced
  867.  
  868. --setSortBy
  869. function scoreboardSetSortBy( name, desc )
  870. if name then
  871. if type( name ) == "string" then
  872. local exists = false
  873. for key, value in ipairs( scoreboardColumns ) do
  874. if name == value.name then
  875. exists = true
  876. end
  877. end
  878. if exists then
  879. desc = iif( type( desc ) == "boolean" and not desc, 1, -1 )
  880. sortBy.what = name
  881. sortBy.dir = desc
  882. end
  883. end
  884. return false
  885. else
  886. sortBy.what = "__NONE__"
  887. sortBy.dir = -1
  888. return true
  889. end
  890. end
  891.  
  892. addEvent( "doScoreboardSetSortBy", true )
  893. addEventHandler( "doScoreboardSetSortBy", getResourceRootElement(),
  894. function ( name, desc )
  895. scoreboardSetSortBy( name, desc )
  896. end
  897. )
  898.  
  899. --getColumnPriority
  900. function scoreboardGetColumnPriority( name )
  901. if type( name ) == "string" then
  902. for key, value in ipairs( scoreboardColumns ) do
  903. if name == value.name then
  904. return value.priority
  905. end
  906. end
  907. end
  908. return false
  909. end
  910.  
  911. --setColumnPriority
  912. function scoreboardSetColumnPriority( name, priority )
  913. if type( name ) == "string" and type( priority ) == "number" then
  914. if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then
  915. local columnIndex = false
  916. for key, value in ipairs( scoreboardColumns ) do
  917. if name == value.name then
  918. columnIndex = key
  919. end
  920. end
  921. if columnIndex then
  922. scoreboardColumns[columnIndex].priority = -1 -- To empty out the current priority
  923. fixPrioritySlot( priority )
  924. scoreboardColumns[columnIndex].priority = priority
  925. table.sort( scoreboardColumns, function ( a, b ) return a.priority < b.priority end )
  926. return true
  927. end
  928. end
  929. end
  930. return false
  931. end
  932.  
  933. addEvent( "doScoreboardSetColumnPriority", true )
  934. addEventHandler( "doScoreboardSetColumnPriority", getResourceRootElement(),
  935. function ( name, priority )
  936. scoreboardSetColumnPriority( name, priority )
  937. end
  938. )
  939.  
  940. --getColumnCount
  941. function scoreboardGetColumnCount()
  942. return #scoreboardColumns
  943. end
  944.  
  945. --setColumnTextFunction
  946. function scoreboardSetColumnTextFunction( name, func )
  947. if type( name ) == "string" then
  948. for key, value in ipairs( scoreboardColumns ) do
  949. if name == value.name then
  950. scoreboardColumns[key].textFunction = func
  951. return true
  952. end
  953. end
  954. end
  955. return false
  956. end
  957.  
  958. function scoreboardGetTopCornerPosition()
  959. if scoreboardDrawn then
  960. local sX, sY = guiGetScreenSize()
  961. local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2)
  962. return topX, topY
  963. end
  964. return false
  965. end
  966.  
  967. function scoreboardGetSize()
  968. if scoreboardDrawn then
  969. local width, height = calculateWidth(), calculateHeight()
  970. return width, height
  971. end
  972. return false
  973. end
  974.  
  975. function scoreboardGetSelectedRows()
  976. local rows = {}
  977. for k, v in pairs( selectedRows ) do
  978. table.insert( rows, k )
  979. end
  980. return rows
  981. end
  982.  
  983. -- Other
  984. function calculateWidth()
  985. local width = 0
  986. for key, value in ipairs( scoreboardColumns ) do
  987. width = width + s(value.width + 10)
  988. end
  989. return width + s(10)
  990. end
  991.  
  992. function calculateHeight()
  993. local sX, sY = guiGetScreenSize()
  994. local maxPerWindow = getMaxPerWindow()
  995. local index = firstVisibleIndex
  996. local height = s(5)
  997. if (serverInfo.server or serverInfo.players) and showServerInfo then height = height+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  998. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then height = height+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  999. height = height+s(3)
  1000. height = height+s(5)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont )
  1001. height = height+s(5)+dxGetFontHeight( fontscale(rmbFont, s(0.75)), rmbFont )
  1002. height = height+s(2)
  1003. while ( index < firstVisibleIndex+maxPerWindow and scoreboardContent[index] ) do
  1004. local element = scoreboardContent[index]["__SCOREBOARDELEMENT__"]
  1005. if element and isElement( element ) and getElementType( element ) == "team" then
  1006. height = height + dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont )
  1007. else
  1008. height = height + dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont )
  1009. end
  1010. index = index + 1
  1011. end
  1012. return height
  1013. end
  1014.  
  1015. function showTheCursor( _, state )
  1016. if state == "down" then
  1017. showCursor( true )
  1018. else
  1019. if not (windowSettings and isElement( windowSettings )) then
  1020. showCursor( false )
  1021. end
  1022. end
  1023. end
  1024.  
  1025. function scrollScoreboard( _, _, upOrDown )
  1026. if isCursorShowing() then
  1027. local index = firstVisibleIndex
  1028. local maxPerWindow = getMaxPerWindow()
  1029. index = index + upOrDown
  1030. if index < 1 or (index+maxPerWindow-1 > #scoreboardContent) then
  1031. -- Do nothing
  1032. else
  1033. firstVisibleIndex = index
  1034. end
  1035. end
  1036. end
  1037.  
  1038. function math.clamp( low, value, high )
  1039. return math.max( low, math.min( value, high ) )
  1040. end
  1041.  
  1042. function fromcolor( color )
  1043. -- Propably not the most efficient way, but only way it works
  1044. local colorCode = string.format( "%x", color )
  1045. local a = string.sub( colorCode, 1, 2 ) or "FF"
  1046. local r = string.sub( colorCode, 3, 4 ) or "FF"
  1047. local g = string.sub( colorCode, 5, 6 ) or "FF"
  1048. local b = string.sub( colorCode, 7, 8 ) or "FF"
  1049. a = tonumber( "0x" .. a )
  1050. r = tonumber( "0x" .. r )
  1051. g = tonumber( "0x" .. g )
  1052. b = tonumber( "0x" .. b )
  1053. return r, g, b, a
  1054. end
  1055.  
  1056. function scale( value )
  1057. return value*scoreboardScale
  1058. end
  1059. s = scale
  1060.  
  1061. function fontscale( font, value )
  1062. return value*fontScale[font]
  1063. end
  1064.  
  1065. function scoreboardSortFunction( a, b )
  1066. local firstContent, secondContent
  1067. local sortByA
  1068. if a[sortBy.what] and type( a[sortBy.what] ) == "table" and sortBy.what == "name" then
  1069. sortByA = a[sortBy.what][1]
  1070. else
  1071. sortByA = a[sortBy.what]
  1072. end
  1073. local sortByB
  1074. if b[sortBy.what] and type( b[sortBy.what] ) == "table" and sortBy.what == "name" then
  1075. sortByB = b[sortBy.what][1]
  1076. else
  1077. sortByB = b[sortBy.what]
  1078. end
  1079. if tonumber( sortByA ) then
  1080. firstContent = tonumber( sortByA )
  1081. else
  1082. if sortByA then
  1083. firstContent = string.lower( tostring( sortByA ) )
  1084. else
  1085. firstContent = ""
  1086. end
  1087. end
  1088. if tonumber( sortByB ) then
  1089. secondContent = tonumber( sortByB )
  1090. else
  1091. if sortByB then
  1092. secondContent = string.lower( tostring( sortByB ) )
  1093. else
  1094. secondContent = ""
  1095. end
  1096. end
  1097. if type( sortBy.dir ) == "number" then
  1098. if type( firstContent ) == type( secondContent ) then
  1099. else
  1100. firstContent = string.lower( tostring( firstContent ) )
  1101. secondContent = string.lower( tostring( secondContent ) )
  1102. end
  1103. return iif( sortBy.dir == 1, firstContent > secondContent, firstContent < secondContent )
  1104. end
  1105. return false
  1106. end
  1107.  
  1108. function getMaxPerWindow()
  1109. local sX, sY = guiGetScreenSize()
  1110. local availableHeight = sY-(seperationSpace*2)-s(5)
  1111. if (serverInfo.server or serverInfo.players) and showServerInfo then availableHeight = availableHeight-dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1112. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then availableHeight = availableHeight-dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1113. availableHeight = availableHeight-s(3)
  1114. availableHeight = availableHeight-s(5)-dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont )
  1115. availableHeight = availableHeight-s(5)-dxGetFontHeight( fontscale(rmbFont, s(0.75)), rmbFont )
  1116. availableHeight = availableHeight-s(2)
  1117.  
  1118. local index = firstVisibleIndex
  1119. local count = 0
  1120. local height = 0
  1121. while ( scoreboardContent[index] ) do
  1122. local element = scoreboardContent[index]["__SCOREBOARDELEMENT__"]
  1123. if element and isElement( element ) and getElementType( element ) == "team" then
  1124. height = height + dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont )
  1125. else
  1126. height = height + dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont )
  1127. end
  1128. if height >= availableHeight then
  1129. return count
  1130. end
  1131. index = index + 1
  1132. count = count + 1
  1133. end
  1134. return count
  1135. end
  1136.  
  1137. function scoreboardClickHandler( button, state, cX, cY )
  1138. if scoreboardDrawn and button == "left" and state == "down" then
  1139. local sX, sY = guiGetScreenSize()
  1140. local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2)
  1141. local xMin, xMax, yMin, yMax = topX, topX+calculateWidth(), topY, topY+calculateHeight()
  1142. local maxPerWindow = getMaxPerWindow()
  1143. if cX >= xMin and cX <= xMax and cY >= yMin and cY <= yMax then
  1144. local clickedOnColumn = false
  1145. local x = s(10)
  1146. local y = s(5)+s(3)
  1147. if (serverInfo.server or serverInfo.players) and showServerInfo then y = y + dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1148. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then y = y + dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1149. for key, column in ipairs( scoreboardColumns ) do
  1150. if cX >= topX+x and cX <= topX+x+s(column.width) and cY >= topY+y and cY <= topY+y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ) then
  1151. clickedOnColumn = column.name
  1152. end
  1153. x = x + s(column.width + 10)
  1154. end
  1155. if clickedOnColumn then
  1156. if sortBy.what == clickedOnColumn then -- last click was this column
  1157. sortBy.dir = sortBy.dir + 2
  1158. if sortBy.dir > 1 then
  1159. sortBy.what = "__NONE__"
  1160. sortBy.dir = -1
  1161. end
  1162. else
  1163. sortBy.what = clickedOnColumn
  1164. sortBy.dir = -1
  1165. end
  1166. forceScoreboardUpdate = true
  1167. end
  1168.  
  1169. -- Settings button
  1170. local bottomX, bottomY = topX+calculateWidth(), topY+calculateHeight()
  1171. textLength = dxGetTextWidth( "settings...", fontscale(sbFont, s(sbFontScale)), sbFont )
  1172. textHeight = dxGetFontHeight( fontscale(sbFont, s(sbFontScale)), sbFont )
  1173. if cX >= bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength and cX <= bottomX-s(sbOutOffset+1) and cY >= bottomY-s(sbOutOffset+2*sbInOffset+1)-textHeight and cY <= bottomY-s(sbOutOffset+1) then
  1174. if not (windowSettings and isElement( windowSettings ) and guiGetVisible( windowSettings )) then
  1175. createScoreboardSettingsWindow( sX-323, sY-350 )
  1176. elseif isElement( windowSettings ) then
  1177. destroyScoreboardSettingsWindow()
  1178. end
  1179. end
  1180. end
  1181.  
  1182. -- Scroll buttons
  1183. if firstVisibleIndex > 1 then
  1184. if cX >= sX/2-8 and cX <= sX/2-8+17 and cY >= topY-15 and cY <= topY-15+11 then
  1185. scrollScoreboard( nil, nil, -1 )
  1186. end
  1187. end
  1188. if firstVisibleIndex+maxPerWindow <= #scoreboardContent and #scoreboardContent > maxPerWindow then
  1189. if cX >= sX/2-8 and cX <= sX/2-8+17 and cY >= topY+calculateHeight()+4 and cY <= topY+calculateHeight()+4+11 then
  1190. scrollScoreboard( nil, nil, 1 )
  1191. end
  1192. end
  1193.  
  1194. -- Player/team click
  1195. local y = topY+s(5)
  1196. if (serverInfo.server or serverInfo.players) and showServerInfo then y = y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1197. if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then y = y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end
  1198. y = y+s(3)
  1199. y = y+s(5)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont )
  1200. if cY >= y and cX then
  1201. local index = firstVisibleIndex
  1202. local maxPerWindow = getMaxPerWindow()
  1203. local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2)
  1204. local width = calculateWidth()
  1205. while ( index < firstVisibleIndex+maxPerWindow and scoreboardContent[index] ) do
  1206. local element = scoreboardContent[index]["__SCOREBOARDELEMENT__"]
  1207. local font = iif( element and isElement( element ) and getElementType( element ) == "team", teamHeaderFont, contentFont )
  1208. if cX >= topX+s(5) and cX <= topX+width-s(5) and cY >= y and cY <= y+dxGetFontHeight( fontscale(font, scoreboardScale), font ) then
  1209. local selected = (not selectedRows[element]) == true
  1210. local triggered = triggerEvent( "onClientPlayerScoreboardClick", element, selected, cX, cY )
  1211. if triggered then
  1212. selectedRows[element] = not selectedRows[element]
  1213. end
  1214. end
  1215. y = y + dxGetFontHeight( fontscale(font, scoreboardScale), font )
  1216. index = index + 1
  1217. end
  1218. end
  1219. end
  1220. end
  1221.  
  1222. function removeResourceScoreboardColumns( resource )
  1223. if resourceColumns[resource] then
  1224. while resourceColumns[resource][1] do
  1225. local success = scoreboardRemoveColumn( resourceColumns[resource][1] )
  1226. if not success then break end
  1227. end
  1228. resourceColumns[resource] = nil
  1229. end
  1230. end
  1231. addEventHandler( "onClientResourceStop", getRootElement(), removeResourceScoreboardColumns )
RAW Paste Data