Speed Trap with Leaderboard

What this script does (see video):
Tracks the velocity of any vehicle seat that passes through with a player driving. Then converts that velocity to mph (using 1 stud = 28cm). Then using that data it populates a leaderboard showing the 3 top speeds, only allowing one entry per player. Internally speeds are tracked to 3 digits after the decimal. Does not use datastore, or save. Leaderboard is fresh on each new server.

How to use:

Simply download this model, then position the red part so where a player can drive through it & make it transparent.

Credits required:
I only ask that you leave my username, “br_cks”, within the starting leaderboard list as a credit.

3 Likes

Source:

local debugMode = true

local topModel = script.Parent
local speedTrap = topModel:WaitForChild("SpeedTrap")

local debounceDict = {}
local leaderboard = {
	{driver = "br_cks", speed = 60},
	{driver = "vGenede", speed = 55},
	{driver = "Hydralodon", speed = 50}
}

local lbPart = topModel:WaitForChild("Leaderboard")
local lbSurfaceGui = lbPart:WaitForChild("SurfaceGui")
local lbMain = lbSurfaceGui:WaitForChild("Main")
local lbBackground = lbMain:WaitForChild("Background")

local lbFirst, lbSecond, lbThird = lbBackground:WaitForChild("1"), lbBackground:WaitForChild("2"), lbBackground:WaitForChild("3")
local lbFirstName, lbFirstSpeed = lbFirst:WaitForChild("Username"), lbFirst:WaitForChild("Speed")
local lbSecondName, lbSecondSpeed = lbSecond:WaitForChild("Username"), lbSecond:WaitForChild("Speed")
local lbThirdName, lbThirdSpeed = lbThird:WaitForChild("Username"), lbThird:WaitForChild("Speed")

speedTrap.Touched:Connect(function(hit)
	if not hit:IsA("VehicleSeat") or not hit.Occupant or not hit.Occupant.Name or hit.Occupant.Name ~= "Humanoid" then
		return
	end

	local driver = hit.Occupant.Parent.Name
	local currentTime = tick()

	if not debounceDict[driver] or (currentTime - debounceDict[driver]) >= 3 then
		local vel = hit.AssemblyLinearVelocity
		local mphConversion = 0.6263
		local rawSpeed = vel.Magnitude * mphConversion
		local formattedSpeed = string.format("%.3f", rawSpeed) -- Format to show only the first three digits after the decimal point
		local speed = math.floor(rawSpeed)

		if debugMode then print(driver .. " is going: " .. formattedSpeed .. " MPH (actual) - " .. speed .. " MPH (rounded)") end

		debounceDict[driver] = currentTime

		local playerIndex = nil

		for i, entry in ipairs(leaderboard) do
			if entry.driver == driver then
				playerIndex = i
				break
			end
		end

		if playerIndex then
			if rawSpeed > leaderboard[playerIndex].speed then
				leaderboard[playerIndex].speed = rawSpeed
			end
		else
			table.insert(leaderboard, {driver = driver, speed = rawSpeed})
		end

		table.sort(leaderboard, function(a, b)
			return a.speed > b.speed or (a.speed == b.speed and a.driver < b.driver)
		end)

		while #leaderboard > 3 do
			table.remove(leaderboard)
		end

		local updateLeaderboard = false

		if lbFirstName.Text ~= leaderboard[1].driver or lbFirstSpeed.Text ~= math.floor(leaderboard[1].speed) .. " MPH" or
			lbSecondName.Text ~= leaderboard[2].driver or lbSecondSpeed.Text ~= math.floor(leaderboard[2].speed) .. " MPH" or
			lbThirdName.Text ~= leaderboard[3].driver or lbThirdSpeed.Text ~= math.floor(leaderboard[3].speed) .. " MPH" then
			updateLeaderboard = true
		end

		if updateLeaderboard then
			lbFirstName.Text, lbFirstSpeed.Text = leaderboard[1].driver, math.floor(leaderboard[1].speed) .. " MPH"
			lbSecondName.Text, lbSecondSpeed.Text = leaderboard[2].driver, math.floor(leaderboard[2].speed) .. " MPH"
			lbThirdName.Text, lbThirdSpeed.Text = leaderboard[3].driver, math.floor(leaderboard[3].speed) .. " MPH"
			if debugMode then 
				print("Leaderboard:")
				for i, entry in ipairs(leaderboard) do
					print(i .. ". " .. entry.driver .. ": " .. string.format("%.3f", entry.speed) .. " MPH")
				end
			end
		end
	end
end)

2 Likes