Advertisement
NaroxEG

Nametags Updated

Jun 21st, 2025 (edited)
429
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.22 KB | None | 0 0
  1. -- Custom Car Tags for Assetto Corsa Server
  2. -- Parallelogram-style player tags with name, input type, country flag, and ping bars
  3.  
  4. local driverData = {}
  5. local nametagCanvas = {}
  6. local numberOfCars = 0
  7. local globaldt = 0.016
  8.  
  9. -- Initialize data for all cars
  10. for i = 0, 1000 do
  11.     if not ac.getCar(i) then
  12.         break
  13.     end
  14.     numberOfCars = numberOfCars + 1
  15.     driverData[i] = {
  16.         nationCode = ""  -- Initialize nation code
  17.     }
  18.     nametagCanvas[i] = {
  19.         canvas = ui.ExtraCanvas(vec2(480, 120), 1, render.AntialiasingMode.ExtraSharpCMAA),
  20.         fadeCurrent = 0,
  21.         fadeTarget = 0,
  22.         lastUpdate = 0
  23.     }
  24. end
  25.  
  26. local tagsDistance = 150
  27. local updateInterval = 0.1
  28.  
  29. -- Function to get input type (returns type identifier)
  30. function getInputType(carIndex)
  31.     local car = ac.getCar(carIndex)
  32.     if not car then return "gamepad" end
  33.    
  34.     -- Get current input values
  35.     local steer = car.steer
  36.     local gas = car.gas
  37.     local brake = car.brake
  38.    
  39.     -- Enhanced detection logic
  40.     local steerAbs = math.abs(steer)
  41.    
  42.     -- Check for digital inputs (keyboard) - very precise on/off values
  43.     if (steerAbs > 0.98 or steerAbs == 0) and (gas > 0.95 or gas == 0) and (brake > 0.95 or brake == 0) then
  44.         return "keyboard"
  45.     end
  46.    
  47.     -- Check for wheel - smooth analog steering with fine control
  48.     if steerAbs > 0.02 and steerAbs < 0.98 then
  49.         return "wheel"
  50.     end
  51.    
  52.     -- Default to gamepad/controller
  53.     return "gamepad"
  54. end
  55.  
  56. -- Function to draw country flag
  57. function drawCountryFlag(carIndex, x, y, alpha)
  58.     -- Get nation code from driver data (this is how AC stores it)
  59.     local nationCode = ""
  60.    
  61.     -- Try to get nation code from the driver data
  62.     if driverData[carIndex] and driverData[carIndex].nationCode then
  63.         nationCode = driverData[carIndex].nationCode
  64.     end
  65.    
  66.     if nationCode ~= "" then
  67.         -- Use local AC flag images
  68.         local flagPath = "/content/gui/NationFlags/" .. nationCode .. ".png"
  69.         local flagWidth = 24
  70.         local flagHeight = 18
  71.        
  72.         local success = pcall(function()
  73.             ui.drawImage(
  74.                 flagPath,
  75.                 vec2(x, y),
  76.                 vec2(x + flagWidth, y + flagHeight),
  77.                 rgbm(1, 1, 1, alpha)
  78.             )
  79.         end)
  80.        
  81.         -- Fallback if flag image doesn't exist - show nation code
  82.         if not success and nationCode then
  83.             ui.drawText(nationCode, vec2(x, y), rgbm(0.8, 0.8, 1.0, alpha))
  84.         end
  85.     else
  86.         -- No country data available - show globe emoji
  87.         ui.drawText("🌍", vec2(x, y), rgbm(0.6, 0.6, 0.6, alpha))
  88.     end
  89. end
  90.  
  91. -- Function to draw input icon (text or image)
  92. function drawInputIcon(inputType, x, y, alpha)
  93.     if inputType == "wheel" then
  94.         -- Draw steering wheel image
  95.         local wheelURL = "https://i.ibb.co/ds8PPhzj/steering-wheel-1.png"
  96.         local iconSize = 28  -- Size to match text icons
  97.        
  98.         local success = pcall(function()
  99.             ui.drawImage(
  100.                 wheelURL,
  101.                 vec2(x, y),
  102.                 vec2(x + iconSize, y + iconSize),
  103.                 rgbm(1, 1, 1, alpha)
  104.             )
  105.         end)
  106.        
  107.         -- Fallback if URL loading fails
  108.         if not success then
  109.             ui.drawText("🚗", vec2(x, y), rgbm(1, 0.8, 0.2, alpha))
  110.         end
  111.     else
  112.         -- Draw text icons for keyboard and gamepad
  113.         local icon = "🎮"  -- Default gamepad
  114.         if inputType == "keyboard" then
  115.             icon = "⌨️"
  116.         end
  117.         ui.drawText(icon, vec2(x, y), rgbm(1, 0.8, 0.2, alpha))
  118.     end
  119. end
  120.  
  121. -- Function to draw ping bars
  122. function drawPingBars(x, y, ping)
  123.     local barWidth = 6
  124.     local barHeight = 16
  125.     local barSpacing = 3
  126.     local maxBars = 4
  127.    
  128.     local bars = 4
  129.     local barColor = rgb(0, 1, 0)
  130.    
  131.     if ping > 200 then
  132.         bars = 1
  133.         barColor = rgb(1, 0, 0)
  134.     elseif ping > 150 then
  135.         bars = 2
  136.         barColor = rgb(1, 0.5, 0)
  137.     elseif ping > 100 then
  138.         bars = 3
  139.         barColor = rgb(1, 1, 0)
  140.     end
  141.    
  142.     for i = 1, maxBars do
  143.         local barX = x + (i - 1) * (barWidth + barSpacing)
  144.         local currentBarHeight = barHeight * (i / maxBars)
  145.         local currentY = y + barHeight - currentBarHeight
  146.        
  147.         local alpha = (i <= bars) and 1.0 or 0.3
  148.         local color = rgbm(barColor.r, barColor.g, barColor.b, alpha)
  149.        
  150.         ui.drawRectFilled(
  151.             vec2(barX, currentY),
  152.             vec2(barX + barWidth, y + barHeight),
  153.             color
  154.         )
  155.     end
  156. end
  157.  
  158. -- Function to draw parallelogram background
  159. function drawParallelogram(x, y, width, height, color)
  160.     local skew = 20
  161.    
  162.     local topLeft = vec2(x + skew, y)
  163.     local topRight = vec2(x + width + skew, y)
  164.     local bottomRight = vec2(x + width, y + height)
  165.     local bottomLeft = vec2(x, y + height)
  166.    
  167.     ui.drawTriangleFilled(topLeft, topRight, bottomRight, color)
  168.     ui.drawTriangleFilled(topLeft, bottomRight, bottomLeft, color)
  169.    
  170.     local borderColor = rgbm(0.4, 0.4, 0.4, 0.9)
  171.     ui.drawLine(topLeft, topRight, borderColor, 2)
  172.     ui.drawLine(topRight, bottomRight, borderColor, 2)
  173.     ui.drawLine(bottomRight, bottomLeft, borderColor, 2)
  174.     ui.drawLine(bottomLeft, topLeft, borderColor, 2)
  175. end
  176.  
  177. -- Function to draw main area parallelogram (without right border)
  178. function drawMainAreaParallelogram(x, y, width, height, color)
  179.     local skew = 20
  180.    
  181.     local topLeft = vec2(x + skew, y)
  182.     local topRight = vec2(x + width + skew, y)
  183.     local bottomRight = vec2(x + width, y + height)
  184.     local bottomLeft = vec2(x, y + height)
  185.    
  186.     ui.drawTriangleFilled(topLeft, topRight, bottomRight, color)
  187.     ui.drawTriangleFilled(topLeft, bottomRight, bottomLeft, color)
  188.    
  189.     -- Only draw top, bottom, and left borders - no right border
  190.     local borderColor = rgbm(0.4, 0.4, 0.4, 0.9)
  191.     ui.drawLine(topLeft, topRight, borderColor, 2)
  192.     ui.drawLine(bottomRight, bottomLeft, borderColor, 2)
  193.     ui.drawLine(bottomLeft, topLeft, borderColor, 2)
  194. end
  195.  
  196. -- Function to draw ping area background (darker section)
  197. function drawPingAreaBackground(x, y, width, height)
  198.     local skew = 20
  199.    
  200.     local topLeft = vec2(x + skew, y)
  201.     local topRight = vec2(x + width + skew, y)
  202.     local bottomRight = vec2(x + width, y + height)
  203.     local bottomLeft = vec2(x, y + height)
  204.    
  205.     -- Draw darker background for ping area
  206.     local pingBgColor = rgbm(0.01, 0.01, 0.01, 0.95)  -- Even darker, higher opacity
  207.     ui.drawTriangleFilled(topLeft, topRight, bottomRight, pingBgColor)
  208.     ui.drawTriangleFilled(topLeft, bottomRight, bottomLeft, pingBgColor)
  209.    
  210.     -- Draw angled separator line - positioned just to the left of ping bars
  211.     local separatorX = x + 2  -- Move separator 2px to the right from ping area start
  212.     local separatorTopLeft = vec2(separatorX + skew, y)
  213.     local separatorBottomLeft = vec2(separatorX, y + height)
  214.     local separatorColor = rgbm(0.5, 0.5, 0.5, 0.8)
  215.     ui.drawLine(separatorTopLeft, separatorBottomLeft, separatorColor, 2)
  216. end
  217.  
  218. -- Function to render the custom nametag
  219. function renderCustomNametag(carData)
  220.     local canvas = nametagCanvas[carData.index].canvas
  221.     local carIndex = carData.index  -- Store the car index for consistency
  222.    
  223.     canvas:clear()
  224.    
  225.     -- Get all data for the specific car being processed
  226.     local driverName = ac.getDriverName(carIndex)
  227.     local ping = driverData[carIndex].ping or 50
  228.     local inputType = getInputType(carIndex)  -- Use the correct car index
  229.    
  230.     if string.len(driverName) > 15 then
  231.         driverName = string.sub(driverName, 1, 15) .. "..."
  232.     end
  233.    
  234.     -- Define layout
  235.     local tagWidth = 440
  236.     local tagHeight = 80
  237.     local tagX = 20
  238.     local tagY = 20
  239.     local centerY = tagY + (tagHeight / 2)  -- 60
  240.    
  241.     -- Define ping area dimensions
  242.     local pingAreaWidth = 135  -- Increased width to accommodate moved separator
  243.     local pingAreaX = tagX + tagWidth - pingAreaWidth  -- Position at right side
  244.    
  245.     -- Draw main parallelogram with more opacity (no right border)
  246.     drawMainAreaParallelogram(tagX, tagY, tagWidth - pingAreaWidth, tagHeight, rgbm(0.05, 0.05, 0.05, 0.7))
  247.    
  248.     -- Draw darker ping area background
  249.     drawPingAreaBackground(pingAreaX, tagY, pingAreaWidth, tagHeight)
  250.    
  251.     -- Move ping elements left to fit better in parallelogram
  252.     local pingBarsX = 350  -- Moved left from 385
  253.     local pingBarsY = centerY - 8
  254.     drawPingBars(pingBarsX, pingBarsY, ping)
  255.    
  256.     -- Using ui.drawText for text elements
  257.     ui.pushFont(ui.Font.Main)
  258.    
  259.     -- Input icon - use new function that handles both text and image
  260.     drawInputIcon(inputType, 60, centerY - 14, 1.0)  -- Adjusted Y to center image better
  261.    
  262.     -- Country flag - positioned between input icon and name, use correct car index
  263.     drawCountryFlag(carIndex, 130, centerY - 9, 1.0)  -- Use carIndex instead of carData.index
  264.    
  265.     -- Player name - positioned with small gap from flag
  266.     ui.drawText(driverName, vec2(170, centerY - 10), rgb(1, 1, 1))  -- Moved left to accommodate flag
  267.    
  268.     -- Ping text - positioned relative to ping bars
  269.     ui.drawText(ping .. "ms", vec2(395, centerY - 8), rgb(0.9, 0.9, 0.9))
  270.    
  271.     ui.popFont()
  272. end
  273.  
  274. -- Main nametag rendering function
  275. function renderDriverNameTag(carData)
  276.     CurrentlyProcessedCar = carData
  277.    
  278.     -- Update driver data BEFORE rendering
  279.     driverData[carData.index].racePosition = carData.racePosition
  280.     driverData[carData.index].driverName = ac.getDriverName(carData.index)
  281.     driverData[carData.index].ping = carData.ping or math.random(30, 120) -- Fallback for testing
  282.     driverData[carData.index].distanceToCamera = carData.distanceToCamera
  283.    
  284.     -- Try to get nation code from available sources
  285.     if not driverData[carData.index].nationCode or driverData[carData.index].nationCode == "" then
  286.         -- Try different methods to get nation code
  287.         local nationCode = ""
  288.        
  289.         -- Method 1: Try ac.getDriverInfo if it exists
  290.         local success, driverInfo = pcall(function()
  291.             return ac.getDriverInfo(carData.index)
  292.         end)
  293.         if success and driverInfo and driverInfo.nation then
  294.             nationCode = driverInfo.nation
  295.         end
  296.        
  297.         -- Method 2: Try alternative AC functions for nation code
  298.         if nationCode == "" then
  299.             local success2, nation = pcall(function()
  300.                 return ac.getDriverNation(carData.index)
  301.             end)
  302.             if success2 and nation then
  303.                 nationCode = nation
  304.             end
  305.         end
  306.        
  307.         -- Store the nation code (empty string if not found)
  308.         driverData[carData.index].nationCode = nationCode
  309.     end
  310.    
  311.     local currentTime = os.clock()
  312.     if not driverData[carData.index].lastUpdate then
  313.         driverData[carData.index].lastUpdate = currentTime
  314.     end
  315.    
  316.     local shouldUpdate = (currentTime - driverData[carData.index].lastUpdate) > updateInterval
  317.    
  318.     if shouldUpdate and driverData[carData.index].distanceToCamera < tagsDistance then
  319.         nametagCanvas[carData.index].canvas:update(function()
  320.            renderCustomNametag(carData)
  321.         end)
  322.  
  323.         driverData[carData.index].lastUpdate = currentTime
  324.     end
  325.    
  326.     if driverData[carData.index].distanceToCamera < tagsDistance then
  327.         local distance = driverData[carData.index].distanceToCamera
  328.         local sizeScale = math.clamp(((tagsDistance - distance) / tagsDistance)^0.5, 0.6, 1.4)
  329.        
  330.         nametagCanvas[carData.index].fadeTarget = math.clamp((tagsDistance - distance) / (tagsDistance * 0.2), 0, 1)
  331.        
  332.         local fadeSpeed = globaldt * 4
  333.         if nametagCanvas[carData.index].fadeTarget > nametagCanvas[carData.index].fadeCurrent then
  334.             nametagCanvas[carData.index].fadeCurrent = math.min(
  335.                 nametagCanvas[carData.index].fadeCurrent + fadeSpeed,
  336.                 nametagCanvas[carData.index].fadeTarget
  337.             )
  338.         else
  339.             nametagCanvas[carData.index].fadeCurrent = math.max(
  340.                 nametagCanvas[carData.index].fadeCurrent - fadeSpeed,
  341.                 nametagCanvas[carData.index].fadeTarget
  342.             )
  343.         end
  344.        
  345.         if nametagCanvas[carData.index].fadeCurrent > 0.01 then
  346.             local canvasWidth = 480 * sizeScale
  347.             local canvasHeight = 120 * sizeScale
  348.             local canvasX = (600 - canvasWidth) / 2
  349.             local canvasY = (250 - canvasHeight) / 2
  350.            
  351.             ui.drawImage(
  352.                 nametagCanvas[carData.index].canvas,
  353.                 vec2(canvasX, canvasY),
  354.                 vec2(canvasWidth, canvasHeight),
  355.                 rgbm(1, 1, 1, nametagCanvas[carData.index].fadeCurrent)
  356.             )
  357.         end
  358.     else
  359.         nametagCanvas[carData.index].fadeTarget = 0
  360.         nametagCanvas[carData.index].fadeCurrent = 0
  361.     end
  362. end
  363.  
  364. function script.update(dt)
  365.     globaldt = dt
  366. end
  367.  
  368. ui.onDriverNameTag(
  369.     true,
  370.     rgbm(1, 1, 1, 0),
  371.     renderDriverNameTag,
  372.     {
  373.         mainSize = 1.2,
  374.         mirrorSize = 4,
  375.         distanceMultiplier = 3,
  376.         tagSize = vec2(600, 250)
  377.     }
  378. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement