Привет! В моем коде слишком много разбиения на функции, мне не нужно такое количество функций. мне надо чтобы функций было минимум, они были максимально гибки и универсальны, чтобы код легко расширялся. ну и насчет конфига бы подумать немного - привести к какому-то более общему виду, больше внутри закономерностей, больше настроек, что ли - вроде вложения штук в штуки, может быть,  выравния и все такое. сам код - local IS_ACTIVE_KEY = "z"
local IS_ACTIVE = false

local SAMP = require "samp"
local memory = require "memory"
require "socket"

local FONT_ARIAL = {
    Small = renderCreateFont("Arial", 6.5, 0),
    Medium = renderCreateFont("Arial", 8.125),
    Large = renderCreateFont("Arial", 16.25, 0)
}

local SPEEDOMETER_CONFIG = {
    Position = {X = 1200, Y = 730},
    Width = 200,
    Height = 70,
    SpeedBar = {
        Offset = {X = 20, Y = 10},
        Height = 25
    },
    SpeedTextOffset = {X = 0, Y = 48},
    CurrentSpeedOffset = {X = 0, Y = 25},
    LabelOffset = {X = 0, Y = 62},
    Ticks = {
        Main = {
            Width = 20,
            Start = {X = 20, Y = 35},
            End = {X = 180, Y = 40}
        },
        Secondary = {
            Width = 10,
            Start = {X = 30, Y = 35},
            End = {X = 180, Y = 38}
        }
    },
    BorderWidth = 1.1,
    MaxSpeed = 160,
    SpeedWidth = 160
}

local function initializeFonts()
    for name, font in pairs(FONT_ARIAL) do
        if not font then
            error("Failed to create font " .. name)
        end
    end
end

local function getCarSpeed(car)
    return getHandlingFromCarHandle(car, 0x6C)
end

local function getHandlingFromCarHandle(carHandle, offset)
    local carPointer = getCarPointer(carHandle)
    local handlingPointer = readMemory(carPointer + 0x384, 4, false)
    local value = memory.getfloat(handlingPointer + offset, false)
    return (value / 0.02) * 2
end

local function drawBox(x, y, width, height, color)
    renderDrawBox(x, y, width, height, color)
end

local function drawLine(startX, startY, endX, endY, width, color)
    renderDrawLine(startX, startY, endX, endY, width, color)
end

local function drawText(font, text, x, y, color)
    local length, height = renderGetFontDrawTextSize(font, text, false)
    renderFontDrawText(font, text, x - length / 2, y - height / 2, color)
end

local function drawSpeedometerBackground()
    local position = SPEEDOMETER_CONFIG.Position
    drawBox(position.X, position.Y, SPEEDOMETER_CONFIG.Width, SPEEDOMETER_CONFIG.Height, 0xd9FFFFFF)
end

local function drawSpeedBar(speed)
    local position = SPEEDOMETER_CONFIG.Position
    local offset = SPEEDOMETER_CONFIG.SpeedBar.Offset
    local speedBarHeight = SPEEDOMETER_CONFIG.SpeedBar.Height
    local speedWidth = SPEEDOMETER_CONFIG.SpeedWidth
    local speedStart =
        speed.Value > SPEEDOMETER_CONFIG.MaxSpeed and
        SPEEDOMETER_CONFIG.MaxSpeed * math.floor(speed.Value / SPEEDOMETER_CONFIG.MaxSpeed) or
        0

    local barWidth = math.min((speedWidth / SPEEDOMETER_CONFIG.MaxSpeed) * (speed.Value - speedStart), speedWidth)
    drawBox(position.X + offset.X, position.Y + offset.Y, barWidth, speedBarHeight, 0x800000ff)
end

local function drawTicks(tickConfig)
    local position = SPEEDOMETER_CONFIG.Position
    local start = tickConfig.Start
    local endPos = tickConfig.End
    local width = tickConfig.Width

    for x = start.X, endPos.X, width do
        drawLine(position.X + x, position.Y + start.Y, position.X + x, position.Y + endPos.Y, 1, 0xff000000)
    end
end

local function drawSpeedLabels()
    local position = SPEEDOMETER_CONFIG.Position
    local offset = SPEEDOMETER_CONFIG.SpeedTextOffset
    local font = FONT_ARIAL.Small

    for speed = 0, SPEEDOMETER_CONFIG.MaxSpeed, SPEEDOMETER_CONFIG.Ticks.Main.Width do
        drawText(font, tostring(speed), position.X + speed + offset.X, position.Y + offset.Y, 0xff000000)
    end
end

local function drawCurrentSpeed(speed)
    local position = SPEEDOMETER_CONFIG.Position
    local offset = SPEEDOMETER_CONFIG.CurrentSpeedOffset
    local font = FONT_ARIAL.Large

    drawText(font, tostring(speed.Value), position.X + SPEEDOMETER_CONFIG.Width / 2, position.Y + offset.Y, 0xff000000)
end

local function drawSpeedLabel()
    local position = SPEEDOMETER_CONFIG.Position
    local offset = SPEEDOMETER_CONFIG.LabelOffset
    local font = FONT_ARIAL.Medium

    drawText(font, "Speed(MPH)", position.X + SPEEDOMETER_CONFIG.Width / 2, position.Y + offset.Y, 0xff000000)
end

local function drawBorders()
    local position = SPEEDOMETER_CONFIG.Position
    local offset = SPEEDOMETER_CONFIG.SpeedBar.Offset
    local speedBarHeight = SPEEDOMETER_CONFIG.SpeedBar.Height
    local speedWidth = SPEEDOMETER_CONFIG.SpeedWidth
    local borderWidth = SPEEDOMETER_CONFIG.BorderWidth

    drawLine(
        position.X + offset.X,
        position.Y + offset.Y,
        position.X + offset.X + speedWidth,
        position.Y + offset.Y,
        borderWidth,
        0xff000000
    )
    drawLine(
        position.X + offset.X,
        position.Y + offset.Y + speedBarHeight,
        position.X + offset.X + speedWidth,
        position.Y + offset.Y + speedBarHeight,
        borderWidth,
        0xff000000
    )
    drawLine(
        position.X + offset.X,
        position.Y + offset.Y,
        position.X + offset.X,
        position.Y + offset.Y + speedBarHeight,
        borderWidth,
        0xff000000
    )
    drawLine(
        position.X + offset.X + speedWidth,
        position.Y + offset.Y,
        position.X + offset.X + speedWidth,
        position.Y + offset.Y + speedBarHeight,
        borderWidth,
        0xff000000
    )
end

local function drawSpeedometer(speed)
    drawSpeedometerBackground()
    drawSpeedBar(speed)
    drawTicks(SPEEDOMETER_CONFIG.Ticks.Main)
    drawTicks(SPEEDOMETER_CONFIG.Ticks.Secondary)
    drawSpeedLabels()
    drawCurrentSpeed(speed)
    drawSpeedLabel()
    drawBorders()
end

local function main()
    repeat
        wait(0)
    until SAMP.isAvailable()

    SAMP.registerChatCommand(
        IS_ACTIVE_KEY,
        function(arg)
            IS_ACTIVE = not IS_ACTIVE
        end
    )

    while true do
        wait(0)
        if SAMP.isCharInAnyCar(SAMP.playerPed()) then
            local car = SAMP.storeCarCharIsInNoSave(SAMP.playerPed())
            local speed = {Value = math.floor(getCarSpeed(car) * 2)}
            if IS_ACTIVE then
                drawSpeedometer(speed)
            end
        end
    end
end

initializeFonts()
main()