local cars = {}
local peds = {}
local link = {}
local lnkl = {}
local navi = {}

for i = 0, 63 do
  cars["segment" .. i] = require("nodes.cars.segment" .. i)
  peds["segment" .. i] = require("nodes.peds.segment" .. i)
  link["segment" .. i] = require("nodes.link.segment" .. i)
  lnkl["segment" .. i] = require("nodes.lnkl.segment" .. i)
  navi["segment" .. i] = require("nodes.navi.segment" .. i)
end

Monocraft12b = renderCreateFont('Monocraft', 12, 1)
Monocraft12d = renderCreateFont('Monocraft', 12, 0)
Monocraft8d = renderCreateFont('Monocraft', 10, 0)

local resX, resY = getScreenResolution()


function main()
	if not isSampfuncsLoaded() or not isSampLoaded() then return end
	while not isSampAvailable() do wait(0) end

	sampfuncsRegisterConsoleCommand("frf", function(arg)
		--local segment = cars.segment3[1]
		--setCharCoordinates(PLAYER_PED, segment[1], segment[2], segment[3])
		sampAddChatMessage(arg,-1)
	end)

	renderSetRenderState(161 --[[D3DRS_MULTISAMPLEANTIALIAS]], 1)


	while true do wait(0)
		-- получение сегмента(и координат) игрока
		local playerX, playerY = getCharCoordinates(PLAYER_PED)
		local tileID, tileX, tileY = getTileFromCoordinates(playerX, playerY)
		local segment = 'segment' .. tileID - 1
		local nodes = cars[segment]
		local links = link[segment]

		-- рендер красивого текста под чатом
		local debugText = string.format("XY: {FB7000}%d, %d {ffffff}area {FB7000}%d {ffffff}(%d, %d)",
			math.floor(playerX), math.floor(playerY), tileID, tileX, tileY)
		local debugTextShadow = string.format("XY: %d, %d area %d (%d, %d)",
			math.floor(playerX), math.floor(playerY), tileID, tileX, tileY)
			
		renderFontDrawText(Monocraft12b, debugTextShadow, 14, 876.5, 0xFF000000)
		renderFontDrawText(Monocraft12d, debugText, 13, 875, 0xFFFFFFFF)
		
		for i, node in ipairs(nodes) do
			local nodeX, nodeY, nodeZ = unpack(node)
			local linkID = node[4]
			local linkedID1 = links[linkID + 1][2] + 1
			local linkedCount = get_first_four_bits(node[8])
			
			local linkedIDs = {} -- { linkedID, linkedSegment }
			for i = linkID, linkID + (linkedCount-1) do
				local linkedID = links[i + 1][2] + 1
				local linkedSeg = links[i + 1][1] + 1
				linkedIDs[#linkedIDs+1] = { linkedID, linkedSeg }
				--sampAddChatMessage( linkedID ,-1)
			end

			local camX, camY, camZ = getActiveCameraCoordinates()

			if isPointOnScreen(nodeX, nodeY, nodeZ, 3) then
				local losClear = isLineOfSightClear(camX, camY, camZ, nodeX, nodeY, nodeZ + 1.5, true, true, true, true, false)
				if losClear then
					local boxX, boxY = convert3DCoordsToScreen(nodeX, nodeY, nodeZ)
					local distance = getDistanceBetweenCoords3d(nodeX, nodeY, nodeZ, camX, camY, camZ)
					local boxSize = 50 / (1 + distance * 0.1)

					renderDrawBoxWithBorder(boxX, boxY, boxSize, boxSize, 0xFFFF0000, boxSize * 0.1, 0xFF000000)

					if distance < 100 then
						local font = Monocraft8d
						local opacity = string.format("%x", (1 - (distance / 100)) * 255)
						local color1 = '0x' .. opacity .. '000000'
						local color2 = '0x' .. opacity .. 'FFFFFF'
						
						local shadowOffsetX = 5
						local shadowOffsetY = 2
						local columnHeight = 12

						renderFontDrawText(font, 'nodeID: ' .. i, boxX + shadowOffsetX, boxY + shadowOffsetY, tonumber(color1))
						renderFontDrawText(font, 'nodeID: ' .. i, boxX + shadowOffsetY, boxY, tonumber(color2))
						renderFontDrawText(font, 'linkID: ' .. linkID, boxX + shadowOffsetX, boxY + shadowOffsetY + columnHeight*1, tonumber(color1))
						renderFontDrawText(font, 'linkID: ' .. linkID, boxX + 3, boxY + columnHeight*1, tonumber(color2))
							renderFontDrawText(font, 'linkedID: ' .. linkedID1, boxX + shadowOffsetX, boxY + shadowOffsetY + columnHeight*2, tonumber(color1))
						renderFontDrawText(font, 'linkedID: ' .. linkedID1, boxX + 3, boxY + columnHeight*2, tonumber(color2))
						renderFontDrawText(font, 'links: ' .. linkedCount, boxX + shadowOffsetX, boxY + shadowOffsetY + columnHeight*3, tonumber(color1))
						renderFontDrawText(font, 'links: ' .. linkedCount, boxX + 3, boxY + columnHeight*3, tonumber(color2))
					end
				end
			end 
			
			for i, val in ipairs(linkedIDs) do
				local linkedID = val[1]
				local linkedSeg	= val[2]
				local linkedNode = cars['segment' .. linkedSeg-1][linkedID]
				local linkX, linkY, linkZ = unpack(linkedNode)
				
				if isPointOnScreen(linkX, linkY, linkZ, 0) then
					local losClear = isLineOfSightClear(camX, camY, camZ, linkX, linkY, linkZ + 1.5, true, true, true, true, false)
					
					if losClear then
						local boxX, boxY = convert3DCoordsToScreen(nodeX, nodeY, nodeZ)
						local linkedX, linkedY = convert3DCoordsToScreen(linkX, linkY, linkZ)
						if i == 1 then 
							 color = 0xFFFF0000
						elseif i == 2 then
							 color = 0xFF00FF00
						elseif i == 3 then
							 color = 0xFF0000FF
						elseif i == 4 then
							 color = 0xFFFFFF00 
						end
						renderDrawLine(boxX, boxY, linkedX, linkedY, 1, color)
					end
				end
			
			end

		end
		
	end
end

function getTileFromCoordinates(x, y)
  local TILE_SIZE = 6000 / 8
  local MAP_OFFSET = 3000
  
  local tileX = math.floor((x + MAP_OFFSET) / TILE_SIZE) + 1
  local tileY = math.floor((y + MAP_OFFSET) / TILE_SIZE) + 1
  local tileID = (tileY - 1) * 8 + tileX
  
  return tileID, tileX, tileY
end

function math.round(n, deci) deci = 10^(deci or 0) return math.floor(n*deci+.5)/deci end

function get_first_four_bits(num)
    -- Получаем десятичное значение первых 4 битов
    local first_four_bits = num % 16
    return first_four_bits
end	


почисть, отрефактокри, оптимизируй, исправь ошибки начинающих в коде