diff --git a/[gameplay]/scoreboard/dxscoreboard_client.lua b/[gameplay]/scoreboard/dxscoreboard_client.lua index 08837b973..c64058656 100644 --- a/[gameplay]/scoreboard/dxscoreboard_client.lua +++ b/[gameplay]/scoreboard/dxscoreboard_client.lua @@ -1,14 +1,44 @@ -- THESE CAN BE CHANGED -triggerKey = "tab" -- default button to open/close scoreboard -settingsKey = "F7" -- default button to open the settings window + +local triggerKey = "tab" -- default button to open/close scoreboard +local settingsKey = "F7" -- default button to open the settings window +local seperationSpace = 80 -- the space between top/bottom screen and scoreboard top/bottom in pixels + drawOverGUI = true -- draw scoreboard over gui? -seperationSpace = 80 -- the space between top/bottom screen and scoreboard top/bottom in pixels -- BUT DON'T TOUCH THESE -scoreboardToggled = false -scoreboardForced = false + +local resourceColumns = {} +local selectedRows = {} +local serverInfo = {} +local scoreboardContent = {} +local scoreboardDimensions = { ["width"] = 0, ["height"] = 0, ["phase"] = 1, ["lastSeconds"] = 0 } +local scoreboardTicks = { ["lastUpdate"] = 0, ["updateInterval"] = 500 } +local sortBy = { ["what"] = "__NONE__", ["dir"] = -1 } -- -1 = dec, 1 = asc + +local scoreboardToggled = false +local scoreboardForced = false +local forceScoreboardUpdate = false +local firstVisibleIndex = 1 +local sbOutOffset, sbInOffset = 1, 1 +local sbFont = "clear" +local sbFontScale = 0.68 +local cSettingsBox = tocolor(255, 255, 255, 150) + +scoreboardColumns = {} +fontScale = { -- To make all fonts be equal in height + ["default"] = 1.0, + ["default-bold"] = 1.0, + ["clear"] = 1.0, + ["arial"] = 1.0, + ["sans"] = 1.0, + ["pricedown"] = 0.5, + ["bankgothic"] = 0.5, + ["diploma"] = 0.5, + ["beckett"] = 0.5 +} + scoreboardDrawn = false -forceScoreboardUpdate = false useAnimation = true scoreboardIsToggleable = false showServerInfo = false @@ -22,34 +52,8 @@ contentFont = "default-bold" columnFont = "default-bold" serverInfoFont = "default" rmbFont = "clear" -cBlack = tocolor( 0, 0, 0 ) -cWhite = tocolor( 255, 255, 255 ) -cSettingsBox = tocolor( 255, 255, 255, 150 ) -MAX_PRIRORITY_SLOT = 500 - -scoreboardColumns = {} -resourceColumns = {} -scoreboardDimensions = { ["width"] = 0, ["height"] = 0, ["phase"] = 1, ["lastSeconds"] = 0 } -scoreboardTicks = { ["lastUpdate"] = 0, ["updateInterval"] = 500 } -scoreboardContent = {} -firstVisibleIndex = 1 -sortBy = { ["what"] = "__NONE__", ["dir"] = -1 } -- -1 = dec, 1 = asc -sbOutOffset, sbInOffset = 1, 1 -sbFont = "clear" -sbFontScale = 0.68 -serverInfo = {} -fontScale = { -- To make all fonts be equal in height - ["default"] = 1.0, - ["default-bold"] = 1.0, - ["clear"] = 1.0, - ["arial"] = 1.0, - ["sans"] = 1.0, - ["pricedown"] = 0.5, - ["bankgothic"] = 0.5, - ["diploma"] = 0.5, - ["beckett"] = 0.5 -} -selectedRows = {} +cWhite = tocolor(255, 255, 255) +SCREEN_X, SCREEN_Y = guiGetScreenSize() addEvent( "onClientPlayerScoreboardClick" ) @@ -100,7 +104,7 @@ addCommandHandler( "Toggle scoreboard", toggleScoreboard ) function openSettingsWindow() if scoreboardDrawn then - local sX, sY = guiGetScreenSize() + local sX, sY = SCREEN_X, SCREEN_Y if not (windowSettings and isElement( windowSettings ) and guiGetVisible( windowSettings )) then createScoreboardSettingsWindow( sX-323, sY-350 ) showCursor( true ) @@ -334,13 +338,18 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) local sortTableIndex = 1 local sortTable = {} + local players = getElementsByType("player") + + for key = 1, #players do + local player = players[key] - local players = getElementsByType( "player" ) - for key, player in ipairs( players ) do if not getPlayerTeam( player ) or not (showTeams or (serverInfo.forceshowteams and not serverInfo.forcehideteams)) or serverInfo.forcehideteams then sortTable[sortTableIndex] = {} - for key2, column in ipairs( scoreboardColumns ) do + + for key2 = 1, #scoreboardColumns do + local column = scoreboardColumns[key2] local content + if column.name == "name" then local playerName = getPlayerName( player ) if serverInfo.allowcolorcodes then @@ -380,8 +389,12 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) sortTableIndex = sortTableIndex + 1 end end + if sortBy.what ~= "__NONE__" then table.sort( sortTable, scoreboardSortFunction ) end - for key, value in ipairs( sortTable ) do + + for key = 1, #sortTable do + local value = sortTable[key] + scoreboardContent[index] = value index = index + 1 end @@ -390,14 +403,21 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) -- And then the teams local teamSortTableIndex = 1 local teamSortTable = {} + local teams = getElementsByType("team") + sortTable = {} - local teams = getElementsByType( "team" ) - for key, team in ipairs( teams ) do + + for key = 1, #teams do + local team = teams[key] -- Add teams to sorting table first + teamSortTable[teamSortTableIndex] = {} - for key2, column in ipairs( scoreboardColumns ) do + + for key2 = 1, #scoreboardColumns do + local column = scoreboardColumns[key2] local content + if column.name == "name" then local teamName = getTeamName( team ) local teamMemberCount = #getPlayersInTeam( team ) @@ -439,12 +459,21 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) teamSortTableIndex = teamSortTableIndex + 1 -- and then the players + + local playersInTeam = getPlayersInTeam(team) + sortTableIndex = 1 sortTable[team] = {} - for key2, player in ipairs( getPlayersInTeam( team ) ) do + + for key2 = 1, #playersInTeam do + local player = playersInTeam[key2] + sortTable[team][sortTableIndex] = {} - for key3, column in ipairs( scoreboardColumns ) do + + for key3 = 1, #scoreboardColumns do + local column = scoreboardColumns[key3] local content + if column.name == "name" then local playerName = getPlayerName( player ) if serverInfo.allowcolorcodes then @@ -485,18 +514,26 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) end if sortBy.what ~= "__NONE__" then table.sort( sortTable[team], scoreboardSortFunction ) end end + if sortBy.what ~= "__NONE__" then table.sort( teamSortTable, scoreboardSortFunction ) end - for key, content in ipairs( teamSortTable ) do + + for key = 1, #teamSortTable do + local content = teamSortTable[key] local team = content["__SCOREBOARDELEMENT__"] + local sortTableTeam = sortTable[team] + scoreboardContent[index] = content index = index + 1 - for key2, value in ipairs( sortTable[team] ) do + for key2 = 1, #sortTableTeam do + local value = sortTableTeam[key2] + scoreboardContent[index] = value index = index + 1 end end end + scoreboardTicks.lastUpdate = currentTick end @@ -527,9 +564,10 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) 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 ) end if serverInfo.players and showServerInfo then - local players = getElementsByType( "player" ) - local text = "Players: " .. tostring( #players ) .. "/" .. serverInfo.players + local players = getElementsByType("player") + local text = "Players: "..#players.."/"..serverInfo.players local textWidth = dxGetTextWidth( text, fontscale(serverInfoFont, s(0.75)), serverInfoFont ) + 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 ) end if (serverInfo.server or serverInfo.players) and showServerInfo then y = y+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end @@ -558,7 +596,10 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) dxDrawLine( bottomX-s(sbOutOffset+2*sbInOffset+2)-textLength, bottomY-s(sbOutOffset+1), bottomX-s(sbOutOffset+1), bottomY-s(sbOutOffset+1), cSettingsBox, 1, drawOverGUI ) local x1 = s(10) - for key, column in ipairs( scoreboardColumns ) do + + for key = 1, #scoreboardColumns do + local column = scoreboardColumns[key] + if x1 ~= s(10) then local height = s(5) if (serverInfo.server or serverInfo.players) and showServerInfo then height = height+dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end @@ -566,6 +607,7 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) height = height+s(3) dxDrawLine( topX + x1 - s(5), y + s(1), topX + x1 - s(5), y + scoreboardDimensions.height-height-s(2)-textHeight-s(5), cBorder, s(1), drawOverGUI ) end + if sortBy.what == column.name then local _, _, _, a = fromcolor( cHeader ) dxDrawText( column.friendlyName or "-", topX+x1+s(1+9), y+s(1), topX+x1+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 ) @@ -578,8 +620,10 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) dxDrawText( column.friendlyName or "-", topX+x1+s(1), y+s(1), topX+x1+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 ) dxDrawText( column.friendlyName or "-", topX+x1, y, topX+x1+s(column.width), y+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ), cHeader, fontscale(columnFont, s(1)), columnFont, "left", "top", true, false, drawOverGUI ) end + x1 = x1 + s(column.width + 10) end + 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), drawOverGUI ) y = y+s(5)+dxGetFontHeight( fontscale(columnFont, scoreboardScale), columnFont ) @@ -599,27 +643,37 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(teamHeaderFont, scoreboardScale), teamHeaderFont ), cHighlight, drawOverGUI ) end - for key, column in ipairs( scoreboardColumns ) do - local r, g, b, a = fromcolor( cContent ) + for key = 1, #scoreboardColumns do + local column = scoreboardColumns[key] + local r, g, b, a = fromcolor(cContent) + if not useColors then r, g, b = 255, 255, 255 end + local theX = x local content = scoreboardContent[index][column.name] + if content and column.name == "name" then + if useColors then r, g, b = getTeamColor( element ) end + theX = x - s(3) end + if content then if serverInfo.allowcolorcodes and type( content ) == "table" and column.name == "name" then local playerName = content[1] local colorCodes = content[2] - local xPos = topX+theX - for k, v in ipairs( colorCodes ) do + local xPos = topX + theX + + for k = 1, #colorCodes do + local v = colorCodes[k] local firstCodePos = v[2] local secondCodePos = colorCodes[k+1] and colorCodes[k+1][2]-1 or #playerName + if firstCodePos ~= 1 and k == 1 then local secondPos = firstCodePos-1 local firstPos = 1 @@ -629,11 +683,14 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) 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 ) xPos = xPos + textLength5 end + if useColors then r, g, b = v[1][1], v[1][2], v[1][3] end + local partOfName = string.sub( playerName, firstCodePos, secondCodePos ) local textLength4 = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont ) + 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 ) 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 ) xPos = xPos + textLength4 @@ -673,45 +730,60 @@ function doDrawScoreboard( rtPass, onlyAnim, sX, sY ) dxDrawRectangle( topX+s(5), y, scoreboardDimensions.width-s(10), dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ), cHighlight, drawOverGUI ) end - for key, column in ipairs( scoreboardColumns ) do - local r, g, b, a = fromcolor( cContent ) + for key = 1, #scoreboardColumns do + local column = scoreboardColumns[key] + local r, g, b, a = fromcolor(cContent) + if not useColors then r, g, b = 255, 255, 255 end + local theX = x local content = scoreboardContent[index][column.name] + if content and column.name == "name" then + if useColors then r, g, b = getPlayerNametagColor( element ) end + if getPlayerTeam( element ) and (showTeams or (serverInfo.forceshowteams and not serverInfo.forcehideteams)) and not serverInfo.forcehideteams then theX = x + s(12) end end + if content then if serverInfo.allowcolorcodes and type( content ) == "table" and column.name == "name" then local playerName = content[1] local colorCodes = content[2] - local xPos = topX+theX - for k, v in ipairs( colorCodes ) do + local xPos = topX + theX + + for k = 1, #colorCodes do + local v = colorCodes[k] local firstCodePos = v[2] local secondCodePos = colorCodes[k+1] and colorCodes[k+1][2]-1 or #playerName + if firstCodePos ~= 1 and k == 1 then local secondPos = firstCodePos-1 local firstPos = 1 local partOfName = string.sub( playerName, firstPos, secondPos ) local textLength3 = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont ) + 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 ) 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 ) xPos = xPos + textLength3 end + if useColors then r, g, b = v[1][1], v[1][2], v[1][3] end + local partOfName = string.sub( playerName, firstCodePos, secondCodePos ) local textLength2 = dxGetTextWidth( partOfName, fontscale(contentFont, s(1)), contentFont ) + 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 ) 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 ) xPos = xPos + textLength2 end + elseif column.isImage then if type(content)=="table" then if fileExists (content[1]) then @@ -761,30 +833,39 @@ end -- FUNCTIONS -- addColumn -function scoreboardAddColumn( name, width, friendlyName, priority, textFunction, fromResource, isImage, imageW, imageH ) - if type( name ) == "string" then - width = width or 70 - friendlyName = friendlyName or name - priority = tonumber( priority ) or getNextFreePrioritySlot( scoreboardGetColumnPriority( "name" ) ) - fixPrioritySlot( priority ) - textFunction = textFunction or nil - fromResource = sourceResource or fromResource or nil - if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - return false - end - end - table.insert( scoreboardColumns, { ["name"] = name, ["width"] = width, ["friendlyName"] = friendlyName, ["priority"] = priority, ["textFunction"] = textFunction, ["isImage"] = isImage, ["imageW"] = imageW, ["imageH"] = imageH } ) - table.sort( scoreboardColumns, function ( a, b ) return a.priority < b.priority end ) +function scoreboardAddColumn(name, width, friendlyName, priority, textFunction, fromResource, isImage, imageW, imageH) + if type(name) ~= "string" then + return false + end - if fromResource then - if not resourceColumns[fromResource] then resourceColumns[fromResource] = {} end - table.insert ( resourceColumns[fromResource], name ) + width = width or 70 + friendlyName = friendlyName or name + priority = tonumber( priority ) or getNextFreePrioritySlot( scoreboardGetColumnPriority( "name" ) ) + fixPrioritySlot( priority ) + textFunction = textFunction or nil + fromResource = sourceResource or fromResource or nil + + if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + return false end - return true end + + table.insert( scoreboardColumns, { ["name"] = name, ["width"] = width, ["friendlyName"] = friendlyName, ["priority"] = priority, ["textFunction"] = textFunction, ["isImage"] = isImage, ["imageW"] = imageW, ["imageH"] = imageH } ) + table.sort( scoreboardColumns, function ( a, b ) return a.priority < b.priority end ) + + if fromResource then + if not resourceColumns[fromResource] then resourceColumns[fromResource] = {} end + table.insert ( resourceColumns[fromResource], name ) + end + + return true end + return false end @@ -797,18 +878,25 @@ addEventHandler( "doScoreboardAddColumn", root, ) -- removeColumn -function scoreboardRemoveColumn( name ) - if type( name ) == "string" then - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - table.remove( scoreboardColumns, key ) - for resource, content in pairs( resourceColumns ) do - table.removevalue( content, name ) - end - return true +function scoreboardRemoveColumn(name) + if type(name) ~= "string" then + return false + end + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + table.remove(scoreboardColumns, key) + + for resource, content in pairs(resourceColumns) do + table.removevalue(content, name) end + + return true end end + return false end @@ -867,31 +955,37 @@ addEventHandler( "doScoreboardSetForced", resourceRoot, end ) ---Compability +--Compatibility setScoreboardForced = scoreboardSetForced --setSortBy -function scoreboardSetSortBy( name, desc ) - if name then - if type( name ) == "string" then - local exists = false - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - exists = true - end - end - if exists then - desc = iif( type( desc ) == "boolean" and not desc, 1, -1 ) - sortBy.what = name - sortBy.dir = desc - end - end - return false - else +function scoreboardSetSortBy(name, desc) + if not name then sortBy.what = "__NONE__" sortBy.dir = -1 + return true end + + if type(name) ~= "string" then + return false + end + + local exists = false + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + exists = true + end + end + + if exists then + desc = iif(type(desc) == "boolean" and not desc, 1, -1) + sortBy.what = name + sortBy.dir = desc + end end addEvent( "doScoreboardSetSortBy", true ) @@ -902,36 +996,49 @@ addEventHandler( "doScoreboardSetSortBy", resourceRoot, ) --getColumnPriority -function scoreboardGetColumnPriority( name ) - if type( name ) == "string" then - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - return value.priority - end +function scoreboardGetColumnPriority(name) + if type(name) ~= "string" then + return false + end + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + return value.priority end end + return false end --setColumnPriority -function scoreboardSetColumnPriority( name, priority ) - if type( name ) == "string" and type( priority ) == "number" then - if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then - local columnIndex = false - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - columnIndex = key - end - end - if columnIndex then - scoreboardColumns[columnIndex].priority = -1 -- To empty out the current priority - fixPrioritySlot( priority ) - scoreboardColumns[columnIndex].priority = priority - table.sort( scoreboardColumns, function ( a, b ) return a.priority < b.priority end ) - return true +function scoreboardSetColumnPriority(name, priority) + if type(name) ~= "string" or type(priority) ~= "number" then + return false + end + + if not (priority > MAX_PRIRORITY_SLOT or priority < 1) then + local columnIndex = false + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + columnIndex = key end end + + if columnIndex then + scoreboardColumns[columnIndex].priority = -1 -- To empty out the current priority + fixPrioritySlot(priority) + scoreboardColumns[columnIndex].priority = priority + table.sort(scoreboardColumns, function(a, b) return a.priority < b.priority end) + + return true + end end + return false end @@ -948,34 +1055,45 @@ function scoreboardGetColumnCount() end --setColumnTextFunction -function scoreboardSetColumnTextFunction( name, func ) - if type( name ) == "string" then - for key, value in ipairs( scoreboardColumns ) do - if name == value.name then - scoreboardColumns[key].textFunction = func - return true - end +function scoreboardSetColumnTextFunction(name, func) + if type(name) ~= "string" then + return false + end + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + + if name == value.name then + scoreboardColumns[key].textFunction = func + + return true end end + return false end function scoreboardGetTopCornerPosition() - if scoreboardDrawn then - local sX, sY = guiGetScreenSize() - local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2) - topY = topY - 15 -- Extra 15 pixels for the scroll up button - return math.floor(topX), math.floor(topY+1) + if not scoreboardDrawn then + return false end - return false + + local sX, sY = SCREEN_X, SCREEN_Y + local topX, topY = (sX/2) - (calculateWidth()/2), (sY/2) - (calculateHeight()/2) + + topY = topY - 15 -- Extra 15 pixels for the scroll up button + + return math.floor(topX), math.floor(topY + 1) end function scoreboardGetSize() - if scoreboardDrawn then - local width, height = calculateWidth(), calculateHeight() - return width, height + if not scoreboardDrawn then + return false end - return false + + local width, height = calculateWidth(), calculateHeight() + + return width, height end function scoreboardGetSelectedRows() @@ -989,14 +1107,18 @@ end -- Other function calculateWidth() local width = 0 - for key, value in ipairs( scoreboardColumns ) do + + for key = 1, #scoreboardColumns do + local value = scoreboardColumns[key] + width = width + s(value.width + 10) end + return width + s(10) end function calculateHeight() - local sX, sY = guiGetScreenSize() + local sX, sY = SCREEN_X, SCREEN_Y local maxPerWindow = getMaxPerWindow() local index = firstVisibleIndex local height = s(5) @@ -1113,7 +1235,7 @@ function scoreboardSortFunction( a, b ) end function getMaxPerWindow() - local sX, sY = guiGetScreenSize() + local sX, sY = SCREEN_X, SCREEN_Y local availableHeight = sY-(seperationSpace*2)-s(5) if (serverInfo.server or serverInfo.players) and showServerInfo then availableHeight = availableHeight-dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then availableHeight = availableHeight-dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end @@ -1143,7 +1265,7 @@ end function scoreboardClickHandler( button, state, cX, cY ) if scoreboardDrawn and button == "left" and state == "down" then - local sX, sY = guiGetScreenSize() + local sX, sY = SCREEN_X, SCREEN_Y local topX, topY = (sX/2)-(calculateWidth()/2), (sY/2)-(calculateHeight()/2) local xMin, xMax, yMin, yMax = topX, topX+calculateWidth(), topY, topY+calculateHeight() local maxPerWindow = getMaxPerWindow() @@ -1154,13 +1276,17 @@ function scoreboardClickHandler( button, state, cX, cY ) local y = s(5)+s(3) if (serverInfo.server or serverInfo.players) and showServerInfo then y = y + dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end if (serverInfo.gamemode or serverInfo.map) and showGamemodeInfo then y = y + dxGetFontHeight( fontscale(serverInfoFont, scoreboardScale), serverInfoFont ) end - for key, column in ipairs( scoreboardColumns ) do + for key = 1, #scoreboardColumns do + local column = scoreboardColumns[key] + if cX >= topX+x and cX <= topX+x+s(column.width) then clickedColumn = column.name + if cY >= topY+y and cY <= topY+y+dxGetFontHeight( fontscale(contentFont, scoreboardScale), contentFont ) then clickedOnColumnHeader = column.name end end + x = x + s(column.width + 10) end if clickedOnColumnHeader then @@ -1244,4 +1370,4 @@ addEventHandler( "onClientResourceStop", root, removeResourceScoreboardColumns ) function scoreboardForceUpdate () bForceUpdate = true return true -end +end \ No newline at end of file diff --git a/[gameplay]/scoreboard/dxscoreboard_exports.lua b/[gameplay]/scoreboard/dxscoreboard_exports.lua index 93d4eb622..aac1c932c 100644 --- a/[gameplay]/scoreboard/dxscoreboard_exports.lua +++ b/[gameplay]/scoreboard/dxscoreboard_exports.lua @@ -1,5 +1,3 @@ -MAX_PRIRORITY_SLOT = 500 - scoreboardColumns = { { ["name"] = "name", ["width"] = 200, ["friendlyName"] = "Name", ["priority"] = 1 }, { ["name"] = "ping", ["width"] = 40, ["friendlyName"] = "Ping", ["priority"] = MAX_PRIRORITY_SLOT }, diff --git a/[gameplay]/scoreboard/dxscoreboard_rt.lua b/[gameplay]/scoreboard/dxscoreboard_rt.lua index 2d3891ac5..bfc0b2e70 100644 --- a/[gameplay]/scoreboard/dxscoreboard_rt.lua +++ b/[gameplay]/scoreboard/dxscoreboard_rt.lua @@ -6,24 +6,43 @@ local rt local lastUpdateTime = 0 +local savedRowsNext = {} +local savedRows = {} +-- Adjust cursor position if using rt + +local function getCursorScoreboardPosition(rtPass) + local cX, cY = getCursorPosition() + local sX, sY = SCREEN_X, SCREEN_Y + + cX, cY = cX * sX, cY * sY + + if rtPass then + local x, y = scoreboardGetTopCornerPosition() + + cX, cY = cX - x, cY - y + end + + return cX, cY +end -- drawScoreboard --- Do things depending on things +-- Do things depending on things + function drawScoreboard() - cursorCache = {} if #savedRowsNext > 0 then savedRows = savedRowsNext savedRowsNext = {} end if not scoreboardDrawn then - doDrawScoreboard ( false--[[rtPass]], true--[[onlyAnim]], guiGetScreenSize() ) + doDrawScoreboard ( false--[[rtPass]], true--[[onlyAnim]], SCREEN_X, SCREEN_Y ) bForceUpdate = true return end -- Update once every 1000ms + local bUpdate = false if getTickCount() - lastUpdateTime > 1000 or bForceUpdate then bUpdate = true @@ -32,6 +51,7 @@ function drawScoreboard() end -- Determine if new rt is needed + local sX, sY = getRequiredRtSize() if rt then local rX, rY = dxGetMaterialSize( rt ) @@ -42,244 +62,246 @@ function drawScoreboard() end -- Try to create rt if needed + if not rt then rt = dxCreateRenderTarget( sX, sY, true ) bUpdate = true end -- No rt then use standard drawing (hold num_9 to test) + if not rt or getKeyState("num_9") then - doDrawScoreboard ( false --[[rtPass]], false --[[onlyAnim]], guiGetScreenSize() ) + doDrawScoreboard ( false --[[rtPass]], false --[[onlyAnim]], SCREEN_X, SCREEN_Y ) return end -- See if highlighted row will change + local newRowIdx = getCursorOverRow(true) if newRowIdx ~= lastRowIdx then - -- Force rt update if highlighted row will change lastRowIdx = newRowIdx - bUpdate = true + bUpdate = true -- -- Force rt update if highlighted row will change end -- Draw background to screen - doDrawScoreboard ( true --[[rtPass]], true --[[onlyAnim]], guiGetScreenSize() ) + + doDrawScoreboard ( true --[[rtPass]], true --[[onlyAnim]], SCREEN_X, SCREEN_Y ) -- Update to rt + if bUpdate then dxSetRenderTarget ( rt, true ) -- Save drawOverGUI settings + local drawOverGUISaved = drawOverGUI drawOverGUI = false -- Draw all text to rt + dxSetBlendMode( "modulate_add" ) - doDrawScoreboard ( true --[[rtPass]], false --[[onlyAnim]], getRequiredRtSize() ) - dxSetBlendMode( "blend" ) + doDrawScoreboard ( true --[[rtPass]], false --[[onlyAnim]], sX, sY ) + dxSetBlendMode( "blend" ) -- Restore drawOverGUI settings + drawOverGUI = drawOverGUISaved dxSetRenderTarget () end - -- If no text drawn then we are done + -- If no text drawn then we are done + if not scoreboardDrawn then return end -- Draw rt to the screen + local x, y = scoreboardGetTopCornerPosition() dxSetBlendMode( "add" ) - dxDrawImage( x, y, sX, sY, rt, 0, 0, 0, tocolor(255,255,255), drawOverGUI ) + dxDrawImage( x, y, sX, sY, rt, 0, 0, 0, cWhite, drawOverGUI ) dxSetBlendMode( "blend" ) end - -- Calc required render target size --- Includes extra 15 pixels top and bottom for the scroll buttons +-- Includes extra 15 pixels top and bottom for the scroll buttons + function getRequiredRtSize() local sX, sY = calculateWidth(), calculateHeight() + if not sX then - sX, sY = guiGetScreenSize() + sX, sY = SCREEN_X, SCREEN_Y else sY = sY + 30 end + return math.floor(sX), math.floor(sY) end +-- Return true is cursor is inside bounds +-- Also saves row data to check if highlighted row is changing between rt updates --- Adjust cursor position if using rt -cursorCache = {} -function getCursorScoreboardPosition(rtPass) - if #cursorCache == 0 then - local cX, cY = getCursorPosition() - local sX, sY = guiGetScreenSize() - cX, cY = cX*sX, cY*sY - if rtPass then - local x, y = scoreboardGetTopCornerPosition() - cX, cY = cX-x, cY-y - end - cursorCache = { cX, cY } +function checkCursorOverRow(rtPass, xl,xh,yl,yh) + if not isCursorShowing() then + return false end - return unpack(cursorCache) -end + local cX, cY = getCursorScoreboardPosition(rtPass) + local cursorOverRow = cX >= xl and cX <= xh and cY >= yl and cY <= yh -savedRowsNext = {} -savedRows = {} --- Return true is cursor is inside bounds --- Also saves row data to check if highlighted row is changing between rt updates -function checkCursorOverRow( rtPass, xl,xh,yl,yh ) - if isCursorShowing() then - savedRowsNext[#savedRowsNext + 1] = { xl,xh,yl,yh } - local cX, cY = getCursorScoreboardPosition( rtPass ) - if cX >= xl and cX <= xh and cY >= yl and cY <= yh then - return true - end - end - return false + savedRowsNext[#savedRowsNext + 1] = {xl, xh, yl, yh} + + return cursorOverRow end -- Return index of the row the cursor is hovering over + function getCursorOverRow(rtPass) - if isCursorShowing() then - local cX, cY = getCursorScoreboardPosition( rtPass ) - for idx,row in ipairs(savedRows) do - if cX >= row[1] and cX <= row[2] and cY >= row[3] and cY <= row[4] then - return idx - end + if not isCursorShowing() then + return false + end + + local cX, cY = getCursorScoreboardPosition(rtPass) + + for idx = 1, #savedRows do + local row = savedRows[idx] + + if cX >= row[1] and cX <= row[2] and cY >= row[3] and cY <= row[4] then + return idx end end + return false end - -------------------------------------------------------------------- -- -- Fake player data for debugging scoreboard --- Set bAddFakePlayers to true to create some test data +-- Set bAddFakePlayers to true to create some test data -- -------------------------------------------------------------------- -local bAddFakePlayers = false -if bAddFakePlayers then +local bAddFakePlayers = false - local numberOfTeams = 4 - local numberOfPlayersPerTeam = 6 +if not bAddFakePlayers then + return false +end - _getElementsByType = getElementsByType - function getElementsByType(type) - local results = _getElementsByType( type ) - if ( type == "player" ) then - results = {} - for t=1,numberOfTeams do - for p=1,numberOfPlayersPerTeam do - results[#results + 1] = string.format( "player %d %d", t, p ) - end - end - elseif ( type == "team" ) then - results = {} - for t=1,numberOfTeams do - results[#results + 1] = string.format( "team %d", t ) +local numberOfTeams = 4 +local numberOfPlayersPerTeam = 6 + +_getElementsByType = getElementsByType +function getElementsByType(type) + local results = _getElementsByType( type ) + if ( type == "player" ) then + results = {} + for t=1,numberOfTeams do + for p=1,numberOfPlayersPerTeam do + results[#results + 1] = string.format( "player %d %d", t, p ) end end - return results + elseif ( type == "team" ) then + results = {} + for t=1,numberOfTeams do + results[#results + 1] = string.format( "team %d", t ) + end end + return results +end - _getLocalPlayer = getLocalPlayer - function getLocalPlayer(type) - return nil - end +_getLocalPlayer = getLocalPlayer +function getLocalPlayer(type) + return nil +end - _getPlayerTeam = getPlayerTeam - function getPlayerTeam(player) - return nil - end +_getPlayerTeam = getPlayerTeam +function getPlayerTeam(player) + return nil +end - _getPlayerName = getPlayerName - function getPlayerName(player) - return tostring(player) - end +_getPlayerName = getPlayerName +function getPlayerName(player) + return tostring(player) +end - _getPlayerPing = getPlayerPing - function getPlayerPing(player) - return math.random(10,100) - end +_getPlayerPing = getPlayerPing +function getPlayerPing(player) + return math.random(10,100) +end - _getElementData = getElementData - function getElementData(player, name) - return _getElementData(localPlayer, name) - end +_getElementData = getElementData +function getElementData(player, name) + return _getElementData(localPlayer, name) +end - _isElement = isElement - function isElement(elem) - return _isElement(elem) or type(elem) == "string" - end +_isElement = isElement +function isElement(elem) + return _isElement(elem) or type(elem) == "string" +end - _getElementType = getElementType - function getElementType(elem) - if ( type(elem) == "string" ) then - local parts = split( elem, string.byte(' ') ) - if parts[1] == "player" then - return "player" - elseif parts[1] == "team" then - return "team" - end +_getElementType = getElementType +function getElementType(elem) + if ( type(elem) == "string" ) then + local parts = split( elem, string.byte(' ') ) + if parts[1] == "player" then + return "player" + elseif parts[1] == "team" then + return "team" end - return _getElementType(elem) end + return _getElementType(elem) +end - _getPlayerNametagColor = getPlayerNametagColor - function getPlayerNametagColor(plr) - if ( type(plr) == "string" ) then - local parts = split( plr, string.byte(' ') ) - if parts[2] == "1" then - return 255,0,0,255 - elseif parts[2] == "2" then - return 0,255,0,255 - elseif parts[2] == "3" then - return 0,0,255,255 - else - return 255,0,255,255 - end +_getPlayerNametagColor = getPlayerNametagColor +function getPlayerNametagColor(plr) + if ( type(plr) == "string" ) then + local parts = split( plr, string.byte(' ') ) + if parts[2] == "1" then + return 255,0,0,255 + elseif parts[2] == "2" then + return 0,255,0,255 + elseif parts[2] == "3" then + return 0,0,255,255 + else + return 255,0,255,255 end - return _getPlayerNametagColor(plr) end + return _getPlayerNametagColor(plr) +end - _getTeamColor = getTeamColor - function getTeamColor(team) - if ( type(team) == "string" ) then - local parts = split( team, string.byte(' ') ) - if parts[2] == "1" then - return 255,90,90,255 - elseif parts[2] == "2" then - return 90,255,90,255 - elseif parts[2] == "3" then - return 90,90,255,255 - else - return 255,90,255,255 - end +_getTeamColor = getTeamColor +function getTeamColor(team) + if ( type(team) == "string" ) then + local parts = split( team, string.byte(' ') ) + if parts[2] == "1" then + return 255,90,90,255 + elseif parts[2] == "2" then + return 90,255,90,255 + elseif parts[2] == "3" then + return 90,90,255,255 + else + return 255,90,255,255 end - return _getTeamColor(team) end + return _getTeamColor(team) +end - _getTeamName = getTeamName - function getTeamName(team) - return tostring(team) - end +_getTeamName = getTeamName +function getTeamName(team) + return tostring(team) +end - _getPlayersInTeam = getPlayersInTeam - function getPlayersInTeam(team) - if ( type(team) == "string" ) then - local parts = split( team, string.byte(' ') ) - results = {} - local t=tonumber(parts[2]) - for p=1,numberOfPlayersPerTeam do - results[#results + 1] = string.format( "player %d %d", t, p ) - end - return results - end - return _getPlayersInTeam(team) +_getPlayersInTeam = getPlayersInTeam +function getPlayersInTeam(team) + if ( type(team) == "string" ) then + local parts = split( team, string.byte(' ') ) + results = {} + local t=tonumber(parts[2]) + for p=1,numberOfPlayersPerTeam do + results[#results + 1] = string.format( "player %d %d", t, p ) + end + return results end -end + return _getPlayersInTeam(team) +end \ No newline at end of file