local isActive = true

local memory = require 'memory'
require "socket"
require"lib.sampfuncs"


local colors = {

	-- светлая тема
	tmpTheme1 = {
	background = 0xD9FFFFFF, -- белый цвет с 85% прозрачностью
	text = 0xff000000, -- черный цвет с 100% прозрачностью
	border = 0xff000000, -- черный цвет с 100% прозрачностью
	
	speed1 = 0x800000FF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF00FF, -- фиолетовый цвет с 50% прозрачностью
	},
	
	-- темная тема
	tmpTheme2 = {
	background = 0xD9000000, -- черный цвет с 85% прозрачностью
	text = 0xFFFFFFFF, -- белый цвет
	border = 0xFFFFFFFF, -- белый цвет
	
	speed1 = 0x80505FFF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF50FF, -- фиолетовый цвет с 50% прозрачностью
	},
	
	-- полупрозрачная темная тема
	tmpTheme3 = {
	background = 0x1A000000, -- черный цвет с 10% прозрачностью
	text = 0xFFFFFFFF, -- белый цвет
	border = 0xFFFFFFFF, -- белый цвет
	
	speed1 = 0x80505FFF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF50FF, -- фиолетовый цвет с 50% прозрачностью
	}
	
}

local fonts = {
    small = renderCreateFont('Arial', 6.5, 0),
    medium = renderCreateFont('Arial', 8.125),
    large = renderCreateFont('Arial', 16.25, 0)
}

local speedometer = {
    maxSpeed 	= 160,
    width 		= 200,
    height 		= 70,
    posX 		= 1200,
    posY 		= 730,
    borderWidth = 1.1
}

local speedBar = {
	allign 		= 'center', 
	padding 	= 20,
--  width 		= 160,
    height 		= 25,
    offsetX 	= speedometer.width/2,
    offsetY 	= 10
}

local ticks = {
    main = {
		milesPerTick  = 20,
		milesOffset   = 0,
		allign        = 'end',
		height        = 5,
		width         = 1,
		text          = true,
		textOffset	  = 8
    } ,
    secondary = {
		milesPerTick  = 20,
		milesOffset   = 10,
		allign        = 'end',
		height        = 3,
		width         = 1,
		text          = false,
		textOffset	  = false
    }
}

local labels = {
    labelOffsetY = 62
}

function main()
    repeat wait(0) until isSampAvailable()

	local theme = colors.tmpTheme1

    while true do wait(0)
        if isCharInAnyCar(playerPed) then
            local car = storeCarCharIsInNoSave(playerPed)
            local speedUnits = math.floor(getCarSpeed(car) * 2)
            local speedStart = speedUnits > speedometer.maxSpeed and speedometer.maxSpeed * math.floor(speedUnits / speedometer.maxSpeed) or 0
			renderSetRenderState(161 --[[D3DRS_MULTISAMPLEANTIALIAS]], 1)

			
            -- отрисовка фона спидометра
            renderDrawBox(speedometer.posX, speedometer.posY, speedometer.width, speedometer.height, theme.background)
			
			
			-- отрисовка спидбара
			local width = speedometer.width - (speedBar.padding * 2)
			local offsetX = (speedBar.allign == 'start' and speedBar.offsetX) or 
							(speedBar.allign == 'center' and speedBar.offsetX - width/2) or 
							(speedBar.allign == 'end' and speedBar.offsetX - width)
			local speed = (speedUnits - speedStart) / speedometer.maxSpeed * width
			renderDrawBox(speedometer.posX + offsetX, speedometer.posY + speedBar.offsetY,speed, speedBar.height, theme.speed1)
			
			
			-- отрисовка делений и чисел под ними
			for _, tick in pairs(ticks) do
				local startX = speedometer.posX + speedBar.padding
				local startY = ((tick.allign == 'start' and 0) or 
							   (tick.allign == 'center' and speedBar.height / 2) or 
							   (tick.allign == 'end' and speedBar.height)) + speedometer.posY + speedBar.offsetY
				local endY = startY + tick.height
				local speedBarWidth = (speedometer.width - (speedBar.padding * 2))
				local pixelsPerMile = speedBarWidth / (speedometer.maxSpeed) -- деление ширины спидбара на максимальную на нем скорость
				local pixelsOffset = tick.milesOffset * pixelsPerMile -- смещение от начала в пикселях
				local ticksSpacing = tick.milesPerTick * pixelsPerMile -- расстояние между делениями
				local numTicks = math.floor((speedBarWidth-pixelsOffset) / ticksSpacing) -- деление ширины спидбара на ширину тика
				if tick.milesPerTick then
					for i = 0, numTicks  do
						local x = startX + ticksSpacing * i + pixelsOffset
						renderDrawLine(x, startY, x, endY, tick.width, theme.text)
						if tick.text then -- отрисовка текста под(над) черточкой скорости
							local speed = tick.milesPerTick * i + tick.milesOffset + speedStart
							local textY = endY + tick.textOffset
							
							renderFontDrawTextEx(fonts.small, tostring(speed), x, textY, theme.text, _, 'center', 'center') -- !! НАПИСАТЬЬ ВЫРАВНИЕ ПО ЦЕНТРУ ПО ОБЕИМ(?) ОСЯМ ЧЕРЕЗ КАСТОМНУЮ ФУНКЦИЮ РЕНДЕРА !!
						end
					end
				end
			end
					
					
            -- отрисовка текущей скорости			
			renderFontDrawTextEx(				fonts.large,				tostring(speedUnits),				speedometer.posX + speedBar.offsetX,				speedometer.posY + ((speedBar.height / 2)+speedBar.offsetY),				theme.text,				_, 'center', 'center'
			)


			-- отрисовка надписи "Speed(MPH)"
			renderFontDrawTextEx(				fonts.medium,				'Speed(MPH)',				speedometer.posX + speedometer.width / 2,				speedometer.posY + labels.labelOffsetY,				theme.text,				_, 'center', 'center')


			-- отрисовка границ спидбара
			renderDrawLine(speedometer.posX + offsetX, speedometer.posY + speedBar.offsetY, speedometer.posX + offsetX + width, speedometer.posY + speedBar.offsetY, speedometer.borderWidth, theme.border)
			renderDrawLine(speedometer.posX + offsetX, speedometer.posY + speedBar.offsetY + speedBar.height, speedometer.posX + offsetX + width, speedometer.posY + speedBar.offsetY + speedBar.height, speedometer.borderWidth, theme.border)
			renderDrawLine(speedometer.posX + offsetX, speedometer.posY + speedBar.offsetY, speedometer.posX + offsetX, speedometer.posY + speedBar.offsetY + speedBar.height, speedometer.borderWidth, theme.border)
			renderDrawLine(speedometer.posX + offsetX + width, speedometer.posY + speedBar.offsetY, speedometer.posX + offsetX + width, speedometer.posY + speedBar.offsetY + speedBar.height, speedometer.borderWidth, theme.border)
		end
	end
end

--      'start'      'center'      'end'

-- 1 значение - одинаковый отступ со всех сторон
-- 2 значения - первое для верха и низа, второе для левой и правой сторон
-- 3 значения - первое для верха, второе для правой и левой, третье для низа
-- 4 значения - отступы по часовой стрелке: верх, правая, низ, левая

function renderFontDrawTextEx(font, text, posX, posY, color, ignoreColorTags, allignX, allignY)
    local length = renderGetFontDrawTextLength(font, text)
    local height = renderGetFontDrawHeight(font)

    if allignX == "center" then
        posX = posX - length / 2
    elseif allignX == "end" then
        posX = posX - length
    end

    if allignY == "center" then
        posY = posY - height / 2
    elseif allignY == "end" then
        posY = posY - height
    end

    return renderFontDrawText(font, text, posX, posY, color, ignoreColorTags)
end


-- примеры вызова drawStar:
-- drawStar(100, 100, 100, 5, 0xFFDD0000, 0xFFFFFFFF, 55)
-- drawStar(50, 230, 45, 7, 0xFFDD0000, 0xFFFFFFFF, 65)
-- drawStar(230, 200, 100, 4, 0xFFCC0000, 0xAAFF00FF, 65)






перепиши этот код под такую структуру:

local speedometer = {
    maxSpeed 	= 160,
    width 		= 200,
    height 		= 70,
    posX 		= 1200,
    posY 		= 730,
    borderWidth = 1.1
	bars		= {
		speedBar = {
			allign 		= 'center', 
			padding 	= 20,
			width 		= 160,
			height 		= 25,
			offsetX 	= speedometer.width/2,
			offsetY 	= 10
			ticks 		= {
				main = {
					milesPerTick  = 20,
					milesOffset   = 0,
					allign        = 'end',
					height        = 5,
					width         = 1,
					text          = true,
					textFont	  = text.small
					textOffset	  = 8
					
				} ,
				secondary = {
					milesPerTick  = 20,
					milesOffset   = 10,
					allign        = 'end',
					height        = 3,
					width         = 1,
					text          = false,
					textOffset	  = false
				}
			}
		}
	}
	labels		= {
		allign 		= 'center', 
		padding 	= 20
	}
}