-- Глобальная переменная для масштабирования
local scale = 1.0

-- Параметры для контроля изменения размера перекрестия
local minScale = 0.5  -- Минимальный коэффициент масштабирования
local maxScale = 1.5  -- Максимальный коэффициент масштабирования
local distanceInfluence = 2 -- Сила влияния расстояния на размер перекрестия



function vehHaveGun()
	for _, v in ipairs({425, 447, 464, 476, 520}) do
		if isCharInModel(playerPed, v) then 
			return true 
		end
	end
	return false
end

function getRhinoCannonCorner(carHandle)
	local memory = require 'memory'
	local ptr = getCarPointer(carHandle)
	local x = memory.getfloat(ptr + 0x94C, false) * 180.0 / math.pi
	local y = memory.getfloat(ptr + 0x950, false) * 180.0 / math.pi
	return x, y
end



function dxDrawRing(posX, posY, radius, width, startAngle, amount, color, absoluteAmount, anglesPerLine)
    -- Проверка входных данных на правильность типов
    if type(posX) ~= "number" or type(posY) ~= "number" or type(startAngle) ~= "number" or type(amount) ~= "number" then
        print("Error: One of the required parameters (posX, posY, startAngle, amount) is not a number.")
        return false
    end

    -- Установка значений по умолчанию для параметров
    radius = type(radius) == "number" and radius or 50
    width = type(width) == "number" and width or 5
    color = color or 0xFFFFFFFF
    absoluteAmount = type(absoluteAmount) == "boolean" and absoluteAmount or false
    anglesPerLine = type(anglesPerLine) == "number" and anglesPerLine or 1

    -- Вычисление конечного угла
    local stopAngle = absoluteAmount and (amount + startAngle) or ((amount * 360) + startAngle)

    -- Отрисовка кольца путем создания линий
    for angle = startAngle, stopAngle, anglesPerLine do
        local radAngle = math.rad(angle)
        local startX = math.cos(radAngle) * (radius - width)
        local startY = math.sin(radAngle) * (radius - width)
        local endX = math.cos(radAngle) * (radius + width)
        local endY = math.sin(radAngle) * (radius + width)

        -- Отрисовка линии с использованием скорректированных координат
        renderDrawLine(startX + posX, startY + posY, endX + posX, endY + posY, width, color)
    end

    -- Возвращаем количество линий, которое было нарисовано
    return math.floor((stopAngle - startAngle) / anglesPerLine)
end







local ffi = require 'ffi'
--HOOKS
local hook = {hooks = {}}
addEventHandler('onScriptTerminate', function(scr)
    if scr == script.this then
        for i, hook in ipairs(hook.hooks) do
            if hook.status then
                hook.stop()
            end
        end
    end
end)
ffi.cdef [[
    int VirtualProtect(void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect);
]]
function hook.new(cast, callback, hook_addr, size)
    jit.off(callback, true) --off jit compilation
    local size = size or 5
    local new_hook = {}
    local detour_addr = tonumber(ffi.cast('intptr_t', ffi.cast('void*', ffi.cast(cast, callback))))
    local void_addr = ffi.cast('void*', hook_addr)
    local old_prot = ffi.new('unsigned long[1]')
    local org_bytes = ffi.new('uint8_t[?]', size)
    ffi.copy(org_bytes, void_addr, size)
    local hook_bytes = ffi.new('uint8_t[?]', size, 0x90)
    hook_bytes[0] = 0xE9
    ffi.cast('uint32_t*', hook_bytes + 1)[0] = detour_addr - hook_addr - 5
    new_hook.call = ffi.cast(cast, hook_addr)
    new_hook.status = false
    local function set_status(bool)
        new_hook.status = bool
        ffi.C.VirtualProtect(void_addr, size, 0x40, old_prot)
        ffi.copy(void_addr, bool and hook_bytes or org_bytes, size)
        ffi.C.VirtualProtect(void_addr, size, old_prot[0], old_prot)
    end
    new_hook.stop = function() set_status(false) end
    new_hook.start = function() set_status(true) end
    new_hook.start()
    table.insert(hook.hooks, new_hook)
    return setmetatable(new_hook, {
        __call = function(self, ...)
            self.stop()
            local res = self.call(...)
            self.start()
            return res
        end
    })
end
--HOOKS

function main()
    -- Предположительный адрес функции
    local preRenderAddr = 0x6D0E60
    -- Установим хук
    vehiclePreRenderHook = hook.new('void(__thiscall *)(void*)', preRenderHook, preRenderAddr)
end

-- Функция для расчета расстояния между двумя точками
function calculateDistance(x1, y1, z1, x2, y2, z2)
    local dx = x2 - x1
    local dy = y2 - y1
    local dz = z2 - z1
    return math.sqrt(dx * dx + dy * dy + dz * dz)
end

function renderCrosshair(x, y, distance)
    -- Изменение масштаба в зависимости от расстояния
    local dynamicScale = scale * (1 / (1 + (distance / 100) * distanceInfluence))

    -- Ограничиваем масштаб в пределах минимального и максимального значения
    dynamicScale = math.max(minScale, math.min(maxScale, dynamicScale))
    
    -- Центрированное компактное центральное кольцо
    local ringRadius = 8 * dynamicScale
    local ringThickness = 0.95 * dynamicScale
    dxDrawRing(x, y, ringRadius, ringThickness, 0, 1, 0x10FFFFFF, false, 1)

    -- Толщина линии для корректировки центрального выравнивания
    local lineThickness = 1 * dynamicScale
    
    -- Длина линий от центра
    local lineLength = 10 * dynamicScale
    local gapLength = 3 * dynamicScale

    -- Корректировка вертикальных линий
    renderDrawLine(x + lineThickness / 2, y - lineLength, x + lineThickness / 2, y - gapLength, lineThickness, 0xFFFFFFFF) -- Верхняя линия
    renderDrawLine(x + lineThickness / 2, y + gapLength, x + lineThickness / 2, y + lineLength, lineThickness, 0xFFFFFFFF) -- Нижняя линия

    -- Корректировка горизонтальных линий
    renderDrawLine(x - lineLength, y - lineThickness / 2, x - gapLength, y - lineThickness / 2, lineThickness, 0xFFFFFFFF) -- Левая линия
    renderDrawLine(x + gapLength, y - lineThickness / 2, x + lineLength, y - lineThickness / 2, lineThickness, 0xFFFFFFFF) -- Правая линия
end




ffi.cdef('struct CVector2D {float x, y;}')

function TransformRealWorldPointToRadarSpace(x, y)
    local RetVal = ffi.new('struct CVector2D', {0, 0})
    ffi.cast('void (__cdecl*)(struct CVector2D*, struct CVector2D*)', 0x583530)(RetVal, ffi.new('struct CVector2D', {x, y}))
    return RetVal.x, RetVal.y
end

function TransformRadarPointToScreenSpace(x, y)
    local RetVal = ffi.new('struct CVector2D', {0, 0})
    ffi.cast('void (__cdecl*)(struct CVector2D*, struct CVector2D*)', 0x583480)(RetVal, ffi.new('struct CVector2D', {x, y}))
    return RetVal.x, RetVal.y
end

function IsPointInsideRadar(x, y)
    return ffi.cast('bool (__cdecl*)(struct CVector2D*)', 0x584D40)(ffi.new('struct CVector2D', {x, y}))
end









function preRenderHook(this)

    if isCharInAnyCar(playerPed) then
        local car = storeCarCharIsInNoSave(playerPed)
        local cX, cY, cZ = getCarCoordinates(car)
        if vehHaveGun() then
            fX, fY, fZ = getOffsetFromCarInWorldCoords(car, 0, 128, 0)
            local result, tPoint = processLineOfSight(cX, cY, cZ, fX, fY, fZ, true, false, true, true, false, false, false, true)
            if result then fX, fY, fZ = tPoint.pos[1], tPoint.pos[2], tPoint.pos[3] end
            local _, gx, gy, z, _, _ = convert3DCoordsToScreenEx(fX, fY, fZ)
            local distance = calculateDistance(cX, cY, cZ, fX, fY, fZ)
            if z > 1 then renderCrosshair(gx, gy, distance) end
        elseif isCharInModel(playerPed, 432) then
            local oX, oY, oZ = getOffsetFromCarInWorldCoords(car, 0, 0, 1.1)
            if not rail then rail = createObject(1551, oX, oY, oZ) end
            if rail then
                local x, y = getRhinoCannonCorner(car)
                attachObjectToCar(rail, car, 0.0, 0.0, 1.1, y, 0.0, x)
                local x1, y1, z1 = getOffsetFromObjectInWorldCoords(rail, 0.0, 6.5, 0.0)
                local x2, y2, z2 = getOffsetFromObjectInWorldCoords(rail, 0.0, 67.0, .0)
                local result, tPoint = processLineOfSight(x1, y1, z1, x2, y2, z2, true, false, true, true, false, false, false, true)
                if result then x2, y2, z2 = tPoint.pos[1], tPoint.pos[2], tPoint.pos[3] end
                local _, gx, gy, z, _, _ = convert3DCoordsToScreenEx(x2, y2, z2)
                local distance = calculateDistance(x1, y1, z1, x2, y2, z2)
                if z > 1 then renderCrosshair(gx, gy, distance) end
            end
        end
    else
        if rail then deleteObject(rail); rail = nil end
    end
	

    vehiclePreRenderHook(this) -- Вызовем оригинальную функцию после выполнения нашего кода
end

как сделать чтобы если игрок в танке и прицел направлен дальше чем на 60 метров то у него менялся цвет