local isActive = true

local memory = require 'memory'
require "socket"

local Arial_8px = renderCreateFont('Arial', 6.5, 0)
local Arial_20px = renderCreateFont('Arial', 16.25, 0)
local Arial_10px = renderCreateFont('Arial', 8.125)

-- Константы
local SPEED_END = 160                                     -- максимальная скорость, отображаемая на спидометре
local SPEED_WIDTH = 160                                   -- ширина полосы скорости

local POS_X = 1200                                        -- позиция спидометра по X
local POS_Y = 730                                         -- позиция спидометра по Y

local MAIN_TICK_WIDTH = 20                                -- 
local SECONDARY_TICK_WIDTH = 10                           -- 

local BORDER_WIDTH = 1.1                                  -- 

local SPEEDOMETER_WIDTH = 200                             -- 
local SPEEDOMETER_HEIGHT = 70                             -- 

local SPEED_BAR_HEIGHT = 25                               -- 
local SPEED_BAR_OFFSET_X = 20                             -- 
local SPEED_BAR_OFFSET_Y = 10        
                     -- 
local SPEED_TEXT_OFFSET_Y = 48                            -- 

local CURRENT_SPEED_OFFSET_Y = 10 + SPEED_BAR_HEIGHT / 2  -- 

local LABEL_OFFSET_Y = 62                                 -- 
local MAIN_TICK_START_X = 20                              -- 
local MAIN_TICK_END_X = 180                               -- 
local MAIN_TICK_START_Y = 35                              -- 
local MAIN_TICK_END_Y = 40                                -- 
local SECONDARY_TICK_START_X = 30                         -- 
local SECONDARY_TICK_END_X = 180                          -- 
local SECONDARY_TICK_START_Y = 35                         -- 
local SECONDARY_TICK_END_Y = 38                           -- 



function main()
	repeat wait(0) until isSampAvailable()
	
	sampRegisterChatCommand("z", function(arg) 
		isActive = not isActive
	end)
	
	while true do wait(0)
				
		if isCharInAnyCar(playerPed) then
		
			local car = storeCarCharIsInNoSave(playerPed)
			local speedUnits = math.floor(getCarSpeed(car) * 2)
			local speedStart = speedUnits > SPEED_END and SPEED_END * math.floor(speedUnits / SPEED_END) or 0

			-- Отрисовка фона спидометра
			renderDrawBox(POS_X, POS_Y, SPEEDOMETER_WIDTH, SPEEDOMETER_HEIGHT, 0xd9FFFFFF)

			-- Отрисовка полосы скорости
			renderDrawBox(POS_X + SPEED_BAR_OFFSET_X, POS_Y + SPEED_BAR_OFFSET_Y, math.min((SPEED_WIDTH / SPEED_END) * (speedUnits - speedStart), SPEED_WIDTH), SPEED_BAR_HEIGHT, 0x800000ff)
			
			-- Отрисовка основных делений
			for x = MAIN_TICK_START_X, MAIN_TICK_END_X, MAIN_TICK_WIDTH do
				renderDrawLine(POS_X + x, POS_Y + MAIN_TICK_START_Y, POS_X + x, POS_Y + MAIN_TICK_END_Y, 1, 0xff000000)
			end
		
			-- Отрисовка промежуточных делений
			for x = SECONDARY_TICK_START_X, SECONDARY_TICK_END_X, MAIN_TICK_WIDTH do
				renderDrawLine(POS_X + x, POS_Y + SECONDARY_TICK_START_Y, POS_X + x, POS_Y + SECONDARY_TICK_END_Y, 1, 0xff000000)
			end

			-- Отрисовка чисел скорости
			for speed = 0, SPEED_END, MAIN_TICK_WIDTH do
				local length = renderGetFontDrawTextLength(Arial_8px, tostring(speed))
				local height = renderGetFontDrawHeight(Arial_8px)
				renderFontDrawText(Arial_8px, tostring(speed), POS_X + speed + SPEED_BAR_OFFSET_X - (length / 2), POS_Y + SPEED_TEXT_OFFSET_Y - (height / 2), 0xff000000)
			end

			-- Отрисовка текущей скорости
			local length2 = renderGetFontDrawTextLength(Arial_20px, tostring(speedUnits))
			local height2 = renderGetFontDrawHeight(Arial_20px)
			renderFontDrawText(Arial_20px, tostring(speedUnits), POS_X + SPEEDOMETER_WIDTH / 2 - (length2 / 2), POS_Y + CURRENT_SPEED_OFFSET_Y - (height2 / 2), 0xff000000)

			-- Отрисовка надписи "Speed(MPH)"
			local length3 = renderGetFontDrawTextLength(Arial_10px, 'Speed(MPH)')
			local height3 = renderGetFontDrawHeight(Arial_10px)
			renderFontDrawText(Arial_10px, 'Speed(MPH)', POS_X + SPEEDOMETER_WIDTH / 2 - (length3 / 2), POS_Y + LABEL_OFFSET_Y - (height3 / 2), 0xff000000)


		
			-- Отрисовка границ спидометра
			renderDrawLine(POS_X + SPEED_BAR_OFFSET_X, POS_Y + SPEED_BAR_OFFSET_Y, POS_X + SPEED_BAR_OFFSET_X + SPEED_WIDTH, POS_Y + SPEED_BAR_OFFSET_Y, BORDER_WIDTH, 0xff000000)
			renderDrawLine(POS_X + SPEED_BAR_OFFSET_X, POS_Y + SPEED_BAR_OFFSET_Y + SPEED_BAR_HEIGHT, POS_X + SPEED_BAR_OFFSET_X + SPEED_WIDTH, POS_Y + SPEED_BAR_OFFSET_Y + SPEED_BAR_HEIGHT, BORDER_WIDTH, 0xff000000)
			renderDrawLine(POS_X + SPEED_BAR_OFFSET_X, POS_Y + SPEED_BAR_OFFSET_Y, POS_X + SPEED_BAR_OFFSET_X, POS_Y + SPEED_BAR_OFFSET_Y + SPEED_BAR_HEIGHT, BORDER_WIDTH, 0xff000000)
			renderDrawLine(POS_X + SPEED_BAR_OFFSET_X + SPEED_WIDTH, POS_Y + SPEED_BAR_OFFSET_Y, POS_X + SPEED_BAR_OFFSET_X + SPEED_WIDTH, POS_Y + SPEED_BAR_OFFSET_Y + SPEED_BAR_HEIGHT, BORDER_WIDTH, 0xff000000)
		end
	end
end

function getHandlingFromCarHandle(carHandle, offset)
	CCar = getCarPointer(carHandle) -- указатель на структуру автомобиля
	CHandling = readMemory(CCar + 0x384, 4, false) -- указатель на структуру хендлинга автомобиля
	res = memory.getfloat(CHandling + offset, false)
	return (res/0.02)*2
end

function getVehicleRPM(vehicle)
    local vehicleRPM = 0
    if (vehicle) then  
        if (isCarEngineOn(vehicle) == true) then
            if getCarCurrentGear(vehicle) > 0 then             
                vehicleRPM = math.floor(((getCarSpeed(vehicle) / getCarCurrentGear(vehicle)) * 160) + 0.5) 
            else
                vehicleRPM = math.floor((getCarSpeed(vehicle) * 160) + 0.5)
            end
            if (vehicleRPM < 650) then
                vehicleRPM = math.random(650, 750) -- Когда машина стоит, обороты будут колебаться от 650 до 750, их можно менять
            elseif (vehicleRPM >= 9000) then
                vehicleRPM = math.random(9000, 9900) -- Максимальное количество оборотов
            end
        else
            vehicleRPM = 0
        end

        return tonumber(vehicleRPM)
    else
        return 0
    end
end

function roundToTenths(num)
    return math.floor(num * 10 + 0.5) / 10
end

окончательно убери из этого кода 'магические числа', измени использование переменных - а т.е. сделай названия более понятными, сгруппируй по таблицам значения