Полезные сниппеты и функции

Gorskin

♥ Love Lua ♥
Проверенный
1,332
1,169
Описание: Отключает покачивание кузова таких авто как tahoma, premier и т.д.
Теперь не нужно менять handling.cfg :))
Lua:
 writeMemory(0x6AC0F0, 2, 0x9090, true)
 

Musaigen

abobusnik
Проверенный
1,607
1,365
Описание: ещё один оператор switch, но наделенный небольшими сверхспособностями.
Код:
Lua:
local function switch(value)
  -- Утилита для вызова функции, или возврата значения, что функцией не является.
  local function call_or_return(var, ...)
    if type(var) == "function" then
      return var(...)
    else
      return var
    end
  end
 
  -- Возвращаем "под-функцию" для красоты.
  return function(cases)
    if cases[value] then -- Если есть готовый обработчик, не "хелпер" (называйте, как хотите), дергаем его. 
      return call_or_return(cases[value], value)
    else -- Иначе дергаем все "хелперы"
      for key, fun in pairs(cases) do
        if type(key) == "function" and key(value) then
          return call_or_return(fun, value)
        end
      end
    end
    
    -- Не один из возможных случаев не был вызван, так что если есть default-case, дергаем его.
    local default = cases["default"]
    if default then
      return call_or_return(default)
    end
  end
end
Пример:
Lua:
local function switch(value)
  -- Утилита для вызова функции, или возврата значения, что функцией не является.
  local function call_or_return(var, ...)
    if type(var) == "function" then
      return var(...)
    else
      return var
    end
  end
 
  -- Возвращаем "под-функцию" для красоты.
  return function(cases)
    if cases[value] then -- Если есть готовый обработчик, не "хелпер" (называйте, как хотите), дергаем его. 
      return call_or_return(cases[value], value)
    else -- Иначе дергаем все "хелперы"
      for key, fun in pairs(cases) do
        if type(key) == "function" and key(value) then
          return call_or_return(fun, value)
        end
      end
    end
    
    -- Не один из возможных случаев не был вызван, так что если есть default-case, дергаем его.
    local default = cases["default"]
    if default then
      return call_or_return(default)
    end
  end
end

local function typeof(_type)
  return function(value)
    return type(value) == _type
  end
end

local function range(min, max)
  return function(value)
    return (type(value) == "number") and (value >= min) and (value <= max)
  end
end

local function search_for(list, key)
  return function(value)
    return value == list[key]
  end
end

local function any_of(...)
  local list = {...}
  return function(value)
    for key, variant in pairs(list) do
      if variant == value then
        return true
      end
    end
    return false
  end
end

-- Думаю, и так ясно, что можно дописать свои хелперы и в йух не дуть.
print(switch("wtf") {
  [1] = 1, -- Если нужно вернуть nil, стоит написать именно функцию, иначе switch не воспримет это как возвращаемое значение.
  [2] = function() -- Простой обработчик, в случае передачи 2.
    print(2)
  end,
  [range(4, 10)] = function(val) -- "Умный"-кейс, так скажем, все значения от 4 до 10 попадут сюда.
    -- val передается для случаев, когда в switch вы сразу будете передавать результат другой функции...
    -- т.е switch(some_fun(...)) { ... }
    print(val, "ranged")
  end,
  [search_for({bebra = 228}, "bebra")] = function() -- Поиск значения в таблице по определенному ключу. Если будет передано 228, выведется "beeebra"
    print("beeebra")
  end,
  [any_of("test", "baby", "wtf")] = function(val)
    print("any_of", val)
  end,
  -- Стоит учитывать, что всегда будет вызываться только 1 обработчик и он рандомный (из-за особенности функции pairs)
  -- Так что в этом примере, у вас может вызваться или этот или верхний обработчик
  [typeof("string")] = function() -- Любая переданная строка вызовет этот кейс
    print("THIS IS A STRING, YEAH BABY")
  end,
  ["default"] = function() -- Если ни один из обработчиков не будет вызван, выведется "NO CASES"
    print("NO CASES")
  end
})
 

Corenale

луашер типа
Проверенный
167
320
Описание: representIntAsFloat и representFloatAsInt без взаимодействия с памятью игры
ну и разбивка float на компоненты (знак, экспонента, мантисса)
lua:
-- warning! it is a mathematical IEEE-754 Floating Point Converter! use ffi for maximum precise!
-- было накидано за сегодня, прошу не ебать за код

local F_MANTISSA_BITS = 23
local F_EXPONENT_BITS = 8
local F_MANTISSA_VALUES = 2^23
local F_EXPONENT_HALF = (2^7)-1

function float2bits(val)
    if val == 1/0 then
        return 0, 255, 0
    elseif val == -1/0 then
        return 1, 255, 0
    elseif val ~= val then
        return 0, 255, 4194304
    end

    local signbit = tostring(val) == tostring(math.abs(val)) and 0 or 1
    val = math.abs(val)
    local exp
    for i = 127, -126, -1 do
        if 2^i <= val then
            exp = i
            break
        end
    end
    local expbits = exp and exp+127 or 0
    exp = exp or -126
    local mantissabits = (((val - 2^exp)/2^exp)*F_MANTISSA_VALUES)+6e15-6e15
    if val < 2^-126 then
        mantissabits = ((val/2^exp)*F_MANTISSA_VALUES)-((val/2^exp)*F_MANTISSA_VALUES)%1
    end
    return signbit, expbits, mantissabits
end

function bits2float(signbit, expbits, mantissabits)
    if expbits == 255 and mantissabits > 0 then
        return 0/0
    elseif expbits == 255 then
        return signbit == 0 and (1/0) or -(1/0)
    end

    local val = expbits == 0 and 0 or 2^(expbits-F_EXPONENT_HALF)
    local temp = expbits == 0 and 2^-126 or 2^(expbits-F_EXPONENT_HALF)
    local val = val+(temp/F_MANTISSA_VALUES)*mantissabits
    return signbit == 0 and val or -val
end

function float2hex(val, isString)
    local signbit, expbits, mantissabits = float2bits(val)
    local signbit = bit.lshift(signbit, 31)
    local expbits = bit.lshift(expbits, 23)
    local result = (signbit+expbits+mantissabits)
    return isString and ("0x"..string.sub(string.format("%08x", result), -8, -1)) or result
end

function hex2float(val)
    local signbit = bit.rshift(bit.band(val, 0x80000000), 31)
    local expbits = bit.rshift(bit.band(val, 0x7F800000), 23)
    local mantissabits = bit.band(val, 0x7FFFFF)
    return bits2float(signbit, expbits, mantissabits)
end
Пример:
lua2:
print(float2hex(3.1415927410126))
print(hex2float(0x40490fdb))
print(float2bits(3.1415927410126))
print(bits2float(0, 128, 4788187))
Для тех, кто смотря на код такой "чзх?":
 
Последнее редактирование:

Corenale

луашер типа
Проверенный
167
320
Описание: Конвертирует 3d корды (высота не нужна окда) в координаты карты в меню игры
c1:
function convert2DCoordsToMenuMapScreenCoords(x, y)
    local fMapZoom = ffi.cast("float*", 0xBA6748+0x64)[0]
    local fMapBaseX = ffi.cast("float*", 0xBA6748+0x68)[0]
    local fMapBaseY = ffi.cast("float*", 0xBA6748+0x6C)[0]

    if isKeyDown(0x5A) then
        return convertGameScreenCoordsToWindowScreenCoords(320+(x/3000)*140, 206-(y/3000)*140)
    else
        return convertGameScreenCoordsToWindowScreenCoords(fMapBaseX+(x/3000)*fMapZoom, fMapBaseY-(y/3000)*fMapZoom)
    end
end
Пример использования:
c2:
if ffi.cast("uint8_t*", 0xBA6748 + 0x15D)[0] == 5 then -- типа только когда меню карты активно окда?
    local charPos = {getCharCoordinates(1)}
    local coords = {convert2DCoordsToMenuMapScreenCoords(unpack(charPos))}
    imgui.GetBackgroundDrawList():AddCircle(ImVec2(coords[1], coords[2]), 5, -1, 45, 5)
end
1722349724642.png
 
Последнее редактирование:

Gorskin

♥ Love Lua ♥
Проверенный
1,332
1,169
Описание: Рисует полукруглый слайдер похожий на спидометр. (mimgui)

Lua:
local imgui = require 'mimgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8

local new = imgui.new
local renderWindow = new.bool(false)

imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
end)

local slider_value = new.float(80.0)  -- Начальное значение слайдера

local newFrame = imgui.OnFrame(
    function() return renderWindow[0] end,
    function(player)
        local resX, resY = getScreenResolution()
        local sizeX, sizeY = 300, 300
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(sizeX, sizeY), imgui.Cond.FirstUseEver)
        imgui.Begin('Main Window', renderWindow)
        imgui.SetCursorPos(imgui.ImVec2(30,50))
        -- Пример использования слайдера с произвольными минимальными и максимальными значениями
        imgui.CustomSemiCircleSlider("SemiCircleSlider", slider_value, 0.0, 300.0, "%d")
        imgui.End()
    end
)

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('mimgui', function()
        renderWindow[0] = not renderWindow[0]
    end)
    while true do
        wait(0)
    end
end

function imgui.CustomSemiCircleSlider(str_id, value, min, max, sformat)
    local radius = 100
    local segments = 50
    local start_angle = math.pi
    local end_angle = 2 * math.pi
    local p = imgui.GetCursorScreenPos()

    -- Невидимая кнопка для захвата мышиных событий
    imgui.InvisibleButton(str_id, imgui.ImVec2(radius * 2 + 15, radius + 20))
    local isActive = imgui.IsItemActive()

    local DL = imgui.GetWindowDrawList()
    local centerX = p.x + radius
    local centerY = p.y + radius

    -- Отрисовка полукруга
    DL:PathArcTo(imgui.ImVec2(centerX, centerY), radius, start_angle, end_angle, segments)
    DL:PathStroke(imgui.GetColorU32(imgui.Col.Button), false, 5.0)

    -- Отрисовка полосок и чисел (делений спидометра)
    local tick_count = 20  -- Общее количество делений (увеличено)
    local show_numbers_every = 4  -- Показывать число через каждые 4 деления
    for i = 0, tick_count do
        local angle = start_angle + (i / tick_count) * (end_angle - start_angle)
        local tick_length = (i % show_numbers_every == 0) and 10 or 5  -- Длинные деления только для чисел
        local tick_inner_x = centerX + math.cos(angle) * (radius - tick_length)
        local tick_inner_y = centerY + math.sin(angle) * (radius - tick_length)
        local tick_outer_x = centerX + math.cos(angle) * radius
        local tick_outer_y = centerY + math.sin(angle) * radius

        DL:AddLine(imgui.ImVec2(tick_inner_x, tick_inner_y), imgui.ImVec2(tick_outer_x, tick_outer_y), imgui.GetColorU32(imgui.Col.Text), 2.0)

        -- Отрисовка чисел только для некоторых делений
        if i % show_numbers_every == 0 then
            local value_at_tick = min + (i / tick_count) * (max - min)
            local text_value = string.format(sformat, value_at_tick)
            local text_size = imgui.CalcTextSize(text_value)
            local text_pos_x = centerX + math.cos(angle) * (radius - tick_length - 17) - text_size.x / 2
            local text_pos_y = centerY + math.sin(angle) * (radius - tick_length - 17) - text_size.y / 2

            DL:AddText(imgui.ImVec2(text_pos_x, text_pos_y), imgui.GetColorU32(imgui.Col.Text), text_value)
        end
    end

    -- Преобразование значения из диапазона [min, max] в [0, 1]
    local norm_value = (value[0] - min) / (max - min)
    
    -- Определение угла по значению слайдера
    local angle = start_angle + norm_value * (end_angle - start_angle)

    -- Определение позиции конца стрелки
    local arrow_length = radius - 20  -- Уменьшенная длина стрелки для отображения значения
    local arrow_x = centerX + math.cos(angle) * arrow_length
    local arrow_y = centerY + math.sin(angle) * arrow_length

    -- Отрисовка стрелки
    DL:AddLine(imgui.ImVec2(centerX, centerY), imgui.ImVec2(arrow_x, arrow_y), imgui.GetColorU32(imgui.Col.Text), 2.0)

    -- Определение координат треугольника на конце стрелки
    local arrow_size = 10  -- Размер стрелки
    local left_arrow_x = arrow_x + math.cos(angle + math.pi / 2) * (arrow_size / 2)
    local left_arrow_y = arrow_y + math.sin(angle + math.pi / 2) * (arrow_size / 2)
    local right_arrow_x = arrow_x + math.cos(angle - math.pi / 2) * (arrow_size / 2)
    local right_arrow_y = arrow_y + math.sin(angle - math.pi / 2) * (arrow_size / 2)
    local tip_arrow_x = arrow_x + math.cos(angle) * arrow_size
    local tip_arrow_y = arrow_y + math.sin(angle) * arrow_size

    -- Отрисовка треугольника на конце стрелки
    DL:AddTriangleFilled(
        imgui.ImVec2(left_arrow_x, left_arrow_y),
        imgui.ImVec2(right_arrow_x, right_arrow_y),
        imgui.ImVec2(tip_arrow_x, tip_arrow_y),
        imgui.GetColorU32(imgui.Col.Text)
    )

    -- Отрисовка значения под стрелкой (фиксированное положение)
    local text_value = string.format(sformat, value[0])
    local text_size = imgui.CalcTextSize(text_value)
    local text_pos_x = centerX - text_size.x / 2
    local text_pos_y = centerY + (radius / 10) -- Фиксированная позиция под полукругом

    -- Добавление фона для текста
    local padding = 4  -- Отступы вокруг текста
    local rect_min = imgui.ImVec2(text_pos_x - padding, text_pos_y - padding)
    local rect_max = imgui.ImVec2(text_pos_x + text_size.x + padding, text_pos_y + text_size.y + padding)
    DL:AddRectFilled(rect_min, rect_max, imgui.GetColorU32(imgui.Col.FrameBg), 0.0)  -- Добавление прямоугольника с закругленными углами

    -- Отображение значения на фоне
    DL:AddText(imgui.ImVec2(text_pos_x, text_pos_y), imgui.GetColorU32(imgui.Col.Text), text_value)

    -- Проверка взаимодействия с ползунком
    if isActive and imgui.IsMouseDown(0) then
        local mouse_pos = imgui.GetMousePos()
        local dx = mouse_pos.x - centerX
        local dy = mouse_pos.y - centerY
        local mouse_angle = math.atan2(dy, dx)

        -- Нормализация угла в диапазоне [0, pi]
        if mouse_angle < start_angle then
            mouse_angle = mouse_angle + 2 * math.pi
        end
        if mouse_angle >= start_angle and mouse_angle <= end_angle then
            -- Преобразование угла обратно в значение слайдера в диапазоне [min, max]
            norm_value = (mouse_angle - start_angle) / (end_angle - start_angle)
            value[0] = min + norm_value * (max - min)
        end
    end
end
Фото:
Screenshot_1.png
 

Gorskin

♥ Love Lua ♥
Проверенный
1,332
1,169
Описание: Рисует элемент регулировки громкости (как на музыкальных колонках)
Работает как закругленный ползунок.

Код:
Lua:
function imgui.Volume(str_id, value, min, max, format)
    imgui.SetCursorPos(imgui.ImVec2(imgui.GetCursorPosX()+5, imgui.GetCursorPosY()))
    local radius_outer = 40
    local radius_inner = 20
    local num_ticks = 10  -- Количество насечек по кругу
    local tick_length = 8  -- Длина насечек
    local tick_thickness = 1  -- Толщина насечек
    local p = imgui.GetCursorScreenPos()

    -- Невидимая кнопка для захвата мышиных событий
    imgui.InvisibleButton(str_id, imgui.ImVec2(radius_outer * 2, radius_outer * 2))
    local isActive = imgui.IsItemActive()

    local DL = imgui.GetWindowDrawList()
    local centerX = p.x + radius_outer
    local centerY = p.y + radius_outer

    -- Отрисовка полного круга для визуализации
    DL:AddCircleFilled(imgui.ImVec2(centerX, centerY), radius_outer, imgui.GetColorU32(imgui.Col.FrameBg), 100)
    DL:AddCircleFilled(imgui.ImVec2(centerX, centerY), radius_inner, imgui.GetColorU32(imgui.Col.WindowBg), 100)
    
    -- Отрисовка границ
    DL:AddCircle(imgui.ImVec2(centerX, centerY), radius_outer, imgui.GetColorU32(imgui.Col.Text), 100, 2.0)
    DL:AddCircle(imgui.ImVec2(centerX, centerY), radius_inner, imgui.GetColorU32(imgui.Col.Text), 100, 2.0)

    -- Отрисовка насечек
    for i = 0, num_ticks - 1 do
        local angle = (i / num_ticks) * 2 * math.pi
        local tick_start_x = centerX + math.cos(angle - math.pi / 2) * (radius_outer - tick_length)
        local tick_start_y = centerY + math.sin(angle - math.pi / 2) * (radius_outer - tick_length)
        local tick_end_x = centerX + math.cos(angle - math.pi / 2) * radius_outer
        local tick_end_y = centerY + math.sin(angle - math.pi / 2) * radius_outer
        DL:AddLine(imgui.ImVec2(tick_start_x, tick_start_y), imgui.ImVec2(tick_end_x, tick_end_y), imgui.GetColorU32(imgui.Col.Text), tick_thickness)
    end

    -- Преобразование значения в угол (ограничение полукругом)
    local norm_value = math.max(0, math.min(1, (value[0] - min) / (max - min)))
    local angle = norm_value * 2 * math.pi  -- Полный круг (от 0 до 2π)

    -- Отрисовка индикатора громкости
    local indicator_length = radius_outer - 10
    local indicator_x = centerX + math.cos(angle - math.pi / 2) * indicator_length
    local indicator_y = centerY + math.sin(angle - math.pi / 2) * indicator_length
    DL:AddLine(imgui.ImVec2(centerX, centerY), imgui.ImVec2(indicator_x, indicator_y), imgui.GetColorU32(imgui.Col.Text), 3.0)

    -- Отрисовка маленького кружка в начале стрелки (в центре внешнего круга)
    local small_circle_radius = 4
    DL:AddCircleFilled(imgui.ImVec2(centerX, centerY), small_circle_radius, imgui.GetColorU32(imgui.Col.Text), 100)

    -- Отображение значения внизу круга
    local text_value = string.format(format, value[0])
    local text_size = imgui.CalcTextSize(text_value)
    
    -- Позиция для текста внизу круга
    local text_pos_x = centerX - text_size.x / 2
    local text_pos_y = p.y + radius_outer * 2 + 10  -- Положение текста немного ниже круга

    -- Добавление фона для текста
    local padding = 4  -- Отступы вокруг текста
    local rect_min = imgui.ImVec2(text_pos_x - padding, text_pos_y - padding)
    local rect_max = imgui.ImVec2(text_pos_x + text_size.x + padding, text_pos_y + text_size.y + padding)
    DL:AddRectFilled(rect_min, rect_max, imgui.GetColorU32(imgui.Col.FrameBg), 0.0)  -- Добавление прямоугольника с закругленными углами

    -- Отображение значения на фоне
    DL:AddText(imgui.ImVec2(text_pos_x, text_pos_y), imgui.GetColorU32(imgui.Col.Text), text_value)

    -- Проверка взаимодействия с ползунком
    if isActive and imgui.IsMouseDown(0) then
        local mouse_pos = imgui.GetMousePos()
        local dx = mouse_pos.x - centerX
        local dy = mouse_pos.y - centerY
        local mouse_angle = math.atan2(dy, dx) + (math.pi / 2)

        -- Ограничение угла в пределах полного круга (от 0 до 2π)
        if mouse_angle < 0 then
            mouse_angle = mouse_angle + (2 * math.pi)
        end
        if mouse_angle > 2 * math.pi then
            mouse_angle = 2 * math.pi
        end

        -- Преобразование угла в значение
        local new_value = (mouse_angle / (2 * math.pi))
        


        -- Преобразование нормализованного значения в диапазон [min, max]
        value[0] = min + new_value * (max - min)
    end
end

Фото: (Громкость)
Screenshot_2.png
 

chromiusj

R&B-baby-queen
Модератор
5,584
3,887
Описание: Рисуем кнопку с анимированным градиентом(2 цвета)
Код:
Lua:
--- @param label string Текст кнопки
--- @param size ImVec2 Размер кнопки (ImVec2)
--- @param color1 table Первый цвет градиента (table, содержащая r, g, b)
--- @param color2 table Второй цвет градиента (table, содержащая r, g, b)
--- @param speed number Скорость анимации (тип number), от 0 до бесконечности, в адекватном виде - от 0 до 5-7
--- @return boolean  возвращаем true, если кнопка была нажата
function imgui.gradientButton(label, size, color1, color2, speed)
    local dl = imgui.GetWindowDrawList()
    local cursorPos = imgui.GetCursorPos()
    local buttonMin = imgui.GetCursorScreenPos()
    local buttonMax = imgui.ImVec2(buttonMin.x + size.x, buttonMin.y + size.y)
    local buttonID = label .. tostring(cursorPos.x) .. tostring(cursorPos.y)
    if ui_button_anim == nil then ui_button_anim = {} end

    if ui_button_anim[buttonID] == nil then
        ui_button_anim[buttonID] = { isPressed = false, startTime = 0, scale = 1.0 }
    end
    local animationDuration = 0.2
    local currentTime = os.clock()
    local function animate(from, to, start_time, duration)
        local timer = currentTime - start_time
        if timer <= duration then
            local t = timer / duration
            return from + t * (to - from), true
        end
        return to, false
    end
    if imgui.IsMouseHoveringRect(buttonMin, buttonMax) and imgui.IsMouseClicked(0) then
        ui_button_anim[buttonID].isPressed = true
        ui_button_anim[buttonID].startTime = currentTime
    end
    if ui_button_anim[buttonID].isPressed then
        ui_button_anim[buttonID].scale, in_progress = animate(1.0, 0.8, ui_button_anim[buttonID].startTime, animationDuration)
        if not in_progress then
            ui_button_anim[buttonID].isPressed = false
            ui_button_anim[buttonID].startTime = currentTime
        end
    else
        ui_button_anim[buttonID].scale, _ = animate(0.8, 1.0, ui_button_anim[buttonID].startTime, animationDuration)
    end
    local scale = ui_button_anim[buttonID].scale
    local centerX, centerY = (buttonMin.x + buttonMax.x) / 2, (buttonMin.y + buttonMax.y) / 2
    buttonMin, buttonMax = imgui.ImVec2(centerX - size.x / 2 * scale, centerY - size.y / 2 * scale), imgui.ImVec2(centerX + size.x / 2 * scale, centerY + size.y / 2 * scale)
    local clock = os.clock() * speed
    local function blendColor(t)
        return {
            r = math.floor(color1.r * (1 - t) + color2.r * t),
            g = math.floor(color1.g * (1 - t) + color2.g * t),
            b = math.floor(color1.b * (1 - t) + color2.b * t)
        }
    end
    local colorA, colorB = blendColor((math.sin(clock) + 1) / 2), blendColor((math.sin(clock + 2) + 1) / 2)
    local vtxStartIdx = dl.VtxBuffer.Size
    dl:AddRectFilled(buttonMin, buttonMax, 0xFFFFFFFF, 8, 15)
    local gradientExtent = imgui.ImVec2(buttonMax.x - buttonMin.x, buttonMax.y - buttonMin.y)
    local gradientInvLength2 = 1.0 / (gradientExtent.x * gradientExtent.x + gradientExtent.y * gradientExtent.y)
    local vtxEndIdx = dl.VtxBuffer.Size
    for i = vtxStartIdx, vtxEndIdx - 1 do
        local vert = dl.VtxBuffer.Data[i]
        local d = (vert.pos.x - buttonMin.x) * gradientExtent.x + (vert.pos.y - buttonMin.y) * gradientExtent.y
        local t = math.max(0.0, math.min(1.0, d * gradientInvLength2))
        vert.col = bit.bor(
            bit.lshift(colorA.r + (colorB.r - colorA.r) * t, 16),
            bit.lshift(colorA.g + (colorB.g - colorA.g) * t, 8),
            colorA.b + (colorB.b - colorA.b) * t,
            bit.band(vert.col, 0xFF000000)
        )
    end
    local textSize = imgui.CalcTextSize(label)
    local scaledTextSize = imgui.ImVec2(textSize.x * scale, textSize.y * scale)
    local textPos = imgui.ImVec2(
        buttonMin.x + (buttonMax.x - buttonMin.x - scaledTextSize.x) * 0.5,
        buttonMin.y + (buttonMax.y - buttonMin.y - scaledTextSize.y) * 0.5
    )
    imgui.SetCursorScreenPos(textPos)
    imgui.SetWindowFontScale(scale)
    imgui.Text(label)
    imgui.SetWindowFontScale(1.0)
    imgui.SetCursorPos(cursorPos)
    imgui.SetCursorPosY(cursorPos.y + size.y + 10)
    return imgui.IsMouseHoveringRect(buttonMin, buttonMax) and imgui.IsMouseClicked(0)
end
Применение:
Lua:
imgui.OnFrame(
    function() return renderWindow[0] and not isGamePaused() end,
    function(self)
        self.HideCursor = not cursorVisible[0]
        local resX, resY = getScreenResolution()
        local menuWidth = 200
        local menuHeight = resY * 0.55
       
        imgui.SetNextWindowPos(imgui.ImVec2(menuPosition, resY / 2), imgui.Cond.Always, imgui.ImVec2(0.0, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(menuWidth, menuHeight), imgui.Cond.Always)
        if imgui.Begin('Menu', renderWindow, imgui.WindowFlags.NoMove + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoTitleBar) then
            local button_size = imgui.ImVec2(100, 50)
       
            if imgui.gradientButton(u8"Навалить говна", button_size,{r = 255, g = 0, b = 0},{r = 0, g = 0, b = 255},3) then
                sampAddChatMessage('Ты навалил говна', -1)
            end
            if imgui.gradientButton(u8"Съесть говна", button_size,{r = 255, g = 255, b = 0},{r = 0, g = 0, b = 255},5) then
                sampAddChatMessage('Ты съел говна', -1)
            end
            imgui.End()
        end
    end
)
Как выглядит:

ezgif-4-1097b1a6b6.gif
 

Tectrex

Известный
128
136
local function call_or_return(var, ...) if type(var) == "function" then return var(...) else return var end end
Брат, желаю тебе только хорошего, не забывай про "тернарные" операторы, ну в луа нам такого добра не завезли, поэтому просто логические операторы.
вместо такой неудобной конструкции if else просто юзай and и or. return type(var) == "function" and var(...) or var.

Так же в следующем твоем случае, приятель, смотри внимательно, я это объясняю не от доеба, и не от злой души, а лишь тебе в добро!
return function(cases) if cases[value] then -- Если есть готовый обработчик, не "хелпер" (называйте, как хотите), дергаем его. return call_or_return(cases[value], value) else -- Иначе дергаем все "хелперы" for key, fun in pairs(cases) do if type(key) == "function" and key(value) then return call_or_return(fun, value) end end end
Заместо if return else, ебашь if return end, затем так же цикл for key, fun in pairs(cases) do, и после выхода из цикла return call_or_return(cases["default"]) и все, в конце эту if default then убираешь вообще, вуаля твой код ну ебейший, просто легендарнейший.
1724927885388.png


Добра и процветания тебе!
 
  • Ха-ха
  • Нравится
Реакции: VanoKLR и Musaigen

ARMOR

Модератор по раксампу
Модератор
4,936
6,738
Проверяем является ли игрок пасажиром, или водителем:

Lua:
local ffi = require("ffi")

function isCharPassenger(vehicleHandle, playerHandle)
    local pVehicle = ffi.cast("void*", getCarPointer(vehicleHandle))
    local pPed = ffi.cast("void*", getCharPointer(playerHandle))
    local CVehicle__IsPassenger = ffi.cast("bool(__thiscall*)(void*, void*)", 0x6D1BD0)
    return CVehicle__IsPassenger(pVehicle, pPed)
end

function isCharDriver(vehicleHandle, playerHandle)
    local pVehicle = ffi.cast("void*", getCarPointer(vehicleHandle))
    local pPed = ffi.cast("void*", getCharPointer(playerHandle))
    local CVehicle__IsDriver = ffi.cast("bool(__thiscall*)(void*, void*)", 0x6D1C40)
    return CVehicle__IsDriver(pVehicle, pPed)
end
 

Corenale

луашер типа
Проверенный
167
320
Описание: Получает размер модуля по хендлу
Код:
c1:
function getModuleSizeByModuleHandle(e_magic)
    return ffi.cast("uint32_t*", e_magic + ffi.cast("uint32_t*", e_magic)[0xF])[0x14]
end
Пример:
c2:
local ffi = require("ffi") -- типа если нету то нада окда
function getModuleSizeByModuleHandle(e_magic)
    return ffi.cast("uint32_t*", e_magic + ffi.cast("uint32_t*", e_magic)[0xF])[0x14]
end

print(getModuleSizeByHandle(getModuleHandle("samp.dll")))
 
Последнее редактирование:

Gorskin

♥ Love Lua ♥
Проверенный
1,332
1,169
Описание: Рисуем такой слайдер.
Screenshot_3.png

Код:
Lua:
-- Функция для отрисовки полукруглого слайдера
function imgui.SemiCircularSlider(str_id, value, min, max, radius)
    local angleMin, angleMax = math.pi * 0.75, math.pi * 2.25 -- начальный и конечный углы
    imgui.SetCursorPos(imgui.ImVec2(imgui.GetCursorPos().x + 10, imgui.GetCursorPos().y + 5))
    -- Получаем текущую позицию курсора для отрисовки
    local p = imgui.GetCursorScreenPos()

    -- Невидимая кнопка для обработки взаимодействий
    imgui.InvisibleButton(str_id, imgui.ImVec2(radius * 2, radius * 2))
    local isActive = imgui.IsItemActive()

    local centerX = p.x + radius
    local centerY = p.y + radius
    local draw_list = imgui.GetWindowDrawList()

    -- Рисуем фон (незаполненная часть слайдера)
    local segments = 256
    local bg_color = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.2, 0.2, 0.2, 1.0)) -- Цвет фона (тёмная дуга)
    for i = 0, segments - 1 do
        local t = i / (segments - 1)
        local currentAngle = angleMin + t * (angleMax - angleMin)
        local x = centerX + radius * math.cos(currentAngle)
        local y = centerY + radius * math.sin(currentAngle)
        local nextAngle = angleMin + (i + 1) / (segments - 1) * (angleMax - angleMin)
        local x_next = centerX + radius * math.cos(nextAngle)
        local y_next = centerY + radius * math.sin(nextAngle)
        draw_list:AddLine(imgui.ImVec2(x, y), imgui.ImVec2(x_next, y_next), bg_color, 8) -- Толщина дуги
    end

    -- Рисуем заполненную часть слайдера с градиентом
    local norm_value = (value[0] - min) / (max - min)
    norm_value = math.max(0, math.min(1, norm_value)) -- Убедитесь, что значение находится в диапазоне [0, 1]
    local slider_color_start = imgui.ImVec4(0.0, 0.7, 1.0, 1.0) -- Начальный цвет градиента
    local slider_color_end = imgui.ImVec4(0.0, 1.0, 0.5, 1.0) -- Конечный цвет градиента
   
    for i = 0, math.floor(segments * norm_value) - 1 do
        local t = i / (segments - 1)
        local currentAngle = angleMin + t * (angleMax - angleMin)
        local x = centerX + radius * math.cos(currentAngle)
        local y = centerY + radius * math.sin(currentAngle)
        local nextAngle = angleMin + (i + 1) / (segments - 1) * (angleMax - angleMin)
        local x_next = centerX + radius * math.cos(nextAngle)
        local y_next = centerY + radius * math.sin(nextAngle)

        -- Преобразуем значение `t` в промежуточный цвет между начальным и конечным
        local r = slider_color_start.x + t * (slider_color_end.x - slider_color_start.x)
        local g = slider_color_start.y + t * (slider_color_end.y - slider_color_start.y)
        local b = slider_color_start.z + t * (slider_color_end.z - slider_color_start.z)
        local color = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(r, g, b, 1.0))

        draw_list:AddLine(imgui.ImVec2(x, y), imgui.ImVec2(x_next, y_next), color, 8)
    end

    -- Рисуем ползунок (кружок) на конце дуги
    local knobAngle = angleMin + norm_value * (angleMax - angleMin)
    local knobX = centerX + radius * math.cos(knobAngle)
    local knobY = centerY + radius * math.sin(knobAngle)
    draw_list:AddCircleFilled(imgui.ImVec2(knobX, knobY), 10, imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1.0, 1.0, 1.0, 1.0)), 64)

    -- Отображаем текущее значение (центральный текст)
    local text = string.format('%.1f', value[0])
    local textSize = imgui.CalcTextSize(text)
    draw_list:AddText(imgui.ImVec2(centerX - textSize.x / 2, centerY - textSize.y / 2), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.0, 0.7, 1.0, 1.0)), text)

    -- Метки минимального и максимального значения (0 и 70)
    local minText = tostring(min)
    local maxText = tostring(max)
    local minTextSize = imgui.CalcTextSize(minText)
    local maxTextSize = imgui.CalcTextSize(maxText)
   
    -- Отображаем метки на концах дуги
    draw_list:AddText(imgui.ImVec2(centerX - radius - minTextSize.x / 2, centerY + radius - 10), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1.0, 1.0, 1.0, 1.0)), minText)
    draw_list:AddText(imgui.ImVec2(centerX + radius - maxTextSize.x / 2, centerY + radius - 10), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(1.0, 1.0, 1.0, 1.0)), maxText)

    -- Обработка взаимодействия
    if isActive and imgui.IsMouseDown(0) then
        local mousePos = imgui.GetMousePos()
        local deltaX = mousePos.x - centerX
        local deltaY = mousePos.y - centerY

        -- Рассчитываем угол курсора относительно центра слайдера
        local angle = math.atan2(deltaY, deltaX)
        -- Справляемся с отрицательными углами
        if angle < 2 then angle = angle + 2 * math.pi end
        -- Ограничиваем угол между изменёнными углами
        if angle >= angleMin and angle <= angleMax then
            -- Преобразование угла в значение слайдера
            local new_value = ((angle - angleMin) / (angleMax - angleMin)) * (max - min) + min
            value[0] = math.max(min, math.min(max, new_value))
        end
    end

    return isActive
end

--Пример:
--где-то в начале скрипта
local sliderValue = new.int(63) -- начальное значение

-- в окне
imgui.SemiCircularSlider("slider", sliderValue, 0, 100, 80)
 
Последнее редактирование:

Albertio

Attention! Thanks for your attention.
887
717
Описание: Отправка нажатия клавиши с синхронизацией, как для onfoot, так и incar.
Требования: SAMP.Lua

Код:

Lua:
local keysTable = {
    ['Y'] = {
        incar = { value = 1, specKey = true },
        onfoot = { value = 1, specKey = true }
    },
    ['N'] = {
        incar = { value = 2, specKey = true },
        onfoot = { value = 2, specKey = true }
    },
    ['H'] = {
        incar = { value = 2, specKey = false },
        onfoot = { value = 3, specKey = true }
    },
    ['C'] = {
        incar = { value = nil, specKey = false },
        onfoot = { value = 2, specKey = false }
    },
    ['F'] = {
        incar = { value = nil, specKey = false },
        onfoot = { value = 16, specKey = false }
    },
    ['ALT'] = {
        incar = { value = 4, specKey = false },
        onfoot = { value = 1024, specKey = false }
    },
    ['TAB'] = {
        incar = { value = nil, specKey = false },
        onfoot = { value = 1, specKey = false }
    },
    ['RMB'] = {
        incar = { value = 4, specKey = false },
        onfoot = { value = 128, specKey = false }
    },
    ['LMB'] = {
        incar = { value = nil, specKey = false },
        onfoot = { value = 4, specKey = false }
    },
    ['SPRINT'] = {
        incar = { value = nil, specKey = false },
        onfoot = { value = 8, specKey = false }
    },
    ['JUMP'] = {
        incar = { value = 128, specKey = false },
        onfoot = { value = 32, specKey = false }
    }
}

function sendSyncKey(key)
    if key == nil then return end
    local inCar = isCharInAnyCar(PLAYER_PED)
    local data = inCar and samp_create_sync_data('vehicle') or samp_create_sync_data('player')
    local keyData = inCar and keysTable[key].incar or keysTable[key].onfoot
    if keyData.value == nil then return end
    if keyData.specKey then data.specialKey = keyData.value else data.keysData = keyData.value end
    data.send()
end

function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    local raknet = require 'samp.raknet'
    require 'samp.synchronization'

    copy_from_player = copy_from_player or true
    local sync_traits = {
        player = { 'PlayerSyncData', raknet.PACKET.PLAYER_SYNC, sampStorePlayerOnfootData },
        vehicle = { 'VehicleSyncData', raknet.PACKET.VEHICLE_SYNC, sampStorePlayerIncarData },
        passenger = { 'PassengerSyncData', raknet.PACKET.PASSENGER_SYNC, sampStorePlayerPassengerData },
        aim = { 'AimSyncData', raknet.PACKET.AIM_SYNC, sampStorePlayerAimData },
        trailer = { 'TrailerSyncData', raknet.PACKET.TRAILER_SYNC, sampStorePlayerTrailerData },
        unoccupied = { 'UnoccupiedSyncData', raknet.PACKET.UNOCCUPIED_SYNC, nil },
        bullet = { 'BulletSyncData', raknet.PACKET.BULLET_SYNC, nil },
        spectator = { 'SpectatorSyncData', raknet.PACKET.SPECTATOR_SYNC, nil }
    }
    local sync_info = sync_traits[sync_type]
    local data_type = 'struct ' .. sync_info[1]
    local data = ffi.new(data_type, {})
    local raw_data_ptr = tonumber(ffi.cast('uintptr_t', ffi.new(data_type .. '*', data)))
    if copy_from_player then
        local copy_func = sync_info[3]
        if copy_func then
            local _, player_id
            if copy_from_player == true then
                _, player_id = sampGetPlayerIdByCharHandle(PLAYER_PED)
            else
                player_id = tonumber(copy_from_player)
            end
            copy_func(player_id, raw_data_ptr)
        end
    end
    local func_send = function()
        local bs = raknetNewBitStream()
        raknetBitStreamWriteInt8(bs, sync_info[2])
        raknetBitStreamWriteBuffer(bs, raw_data_ptr, ffi.sizeof(data))
        raknetSendBitStreamEx(bs, sampfuncs.HIGH_PRIORITY, sampfuncs.UNRELIABLE_SEQUENCED, 1)
        raknetDeleteBitStream(bs)
    end
    local mt = {
        __index = function(t, index)
            return data[index]
        end,
        __newindex = function(t, index, value)
            data[index] = value
        end
    }
    return setmetatable({ send = func_send }, mt)
end

Пример использования:
Lua:
local actionPattren = '"keyTitle": "(%a+)"'

function onReceivePacket(id, bs)
    if id ~= 220 then return end
    raknetBitStreamIgnoreBits(bs, 8)
    if raknetBitStreamReadInt8(bs) ~= 17 then return end
    raknetBitStreamIgnoreBits(bs, 32)
    local event = (raknetBitStreamReadString(bs, raknetBitStreamReadInt32(bs))):match(actionPattren)
    if event ~= nil then sendSyncKey(event) end
end
 
Последнее редактирование:
  • Эм
Реакции: Corenale и XRLM

Орк

Известный
211
136
Описание: Делает скриншот экрана(не экрана игры). На форуме код гуляет, но в этой теме вроде есть вариант (но оба зачем-то через samp, один два)
Код:
Lua:
function screen(path) -- ffi
    local path = tostring(path)
    local D3D9Device = ffi.cast("void* *", 0xC97C28) --or RwCamera 0xB6F97C or getD3DDevicePtr()
    local TakeScreenshot = ffi.cast("void(__cdecl*)(void *, const char*)", 0x5D0820) -- FUNC_JPegCompressScreenToFile
    TakeScreenshot(D3D9Device, path)
end

function screen(path) -- ffi v2
    local path = tostring(path)
    local TakeScreenshot = ffi.cast("void(__cdecl*)(uintptr_t, const char*)", 0x5D0820) -- FUNC_JPegCompressScreenToFile
    TakeScreenshot(0, path)
end

function screen(path) -- standard funcs
    local path = tostring(path)
    callFunction(0x5D0820, 2, 0, readMemory(0xC97C28 --[[ or RwCamera 0xB6F97C or getD3DDevicePtr() or 0 ]], 4, false), path)
end

Применение:
Lua:
local ppath = getWorkingDirectory() .. "\\screen.jpg"
screen(ppath)
--скриншот будет в этой папке "...\moonloader\screen.jpg"

upd добавил вариант callFunction
upd 2 только что узнал
1727683206679.png
поэтому добавил ffi v2
 
Последнее редактирование:

KyRDa

Участник
86
44
Градиент текст
Код:

Code:
function ImLengthSqr(vec2) return (vec2.x * vec2.x) + (vec2.y * vec2.y) end
function ImDot(a, b) return a.x * b.x + a.y * b.y end
function ImClamp(v, mn, mx) return ((v < mn) and mn or ((v > mx) and mx or v)) end

---@param vert_start_idx number
---@param vert_end_idx number
---@param gradient_p0 ImVec2
---@param gradient_p1 ImVec2
---@param col0 ImU32
---@param col1 ImU32
function imgui.ImDrawList.__index:ShadeVertsLinearColorGradientKeepAlpha(vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col0, col1)
    local gradient_extent = imgui.ImVec2(gradient_p1.x - gradient_p0.x, gradient_p1.y - gradient_p0.y )
    local gradient_inv_length2 = 1.0 / ImLengthSqr(gradient_extent)

    col0 = {
        r = bit.band(bit.rshift(col0, 16), 0xFF),
        g = bit.band(bit.rshift(col0, 8), 0xFF),
        b = bit.band(bit.rshift(col0, 0), 0xFF)
    }

    local col_delta = {
        r = bit.band(bit.rshift(col1, 16), 0xFF) - col0.r,
        g = bit.band(bit.rshift(col1, 8), 0xFF) - col0.g,
        b = bit.band(bit.rshift(col1, 0), 0xFF) - col0.b
    }

    for vert = vert_start_idx, vert_end_idx do
        local d = ImDot(
            imgui.ImVec2(
                self.VtxBuffer.Data[vert].pos.x - gradient_p0.x,
                self.VtxBuffer.Data[vert].pos.y - gradient_p0.y
            ),
            gradient_extent
        )
        local t = ImClamp(d * gradient_inv_length2, 0.0, 1.0)
     
        self.VtxBuffer.Data[vert].col = bit.bor(
            bit.lshift(col0.r + col_delta.r * t, 16),
            bit.lshift(col0.g + col_delta.g * t, 8),
            bit.lshift(col0.b + col_delta.b * t, 0),
            bit.band(self.VtxBuffer.Data[vert].col, 0xFF000000)
        )
    end
end

---@param text string
---@param leftcolor ImU32
---@param rightcolor ImU32
---@param smooth number
function imgui.TextGradiented(text, leftcolor, rightcolor, smooth)
    smooth = smooth or 175

    local pos = imgui.GetCursorScreenPos()
    local dl = imgui.GetWindowDrawList()
    local size = imgui.CalcTextSize(text);
   
    local col_white = imgui.GetColorU32Vec4(ImVec4(1, 1, 1, imgui.GetStyle().Alpha))
    local centeredvertex = math.max(smooth, 35)
    local vertex_out = centeredvertex * 0.5
    local text_inner = vertex_out - centeredvertex
   
    local vert_start_idx = dl.VtxBuffer.Size
    dl:AddText(pos, col_white, text)
    local vert_end_idx = dl.VtxBuffer.Size

    -- for n = 0, 1 do
    local n = 0
    local col_hues =  { leftcolor, rightcolor }
    local textcenter = ImVec2(pos.x + (size.x / 2), pos.y + (size.y / 2))

    local a0 = (n) / 6.0 * 2.0 * math.pi - (0.5 / vertex_out)
    local a1 = (n + 1.0) / 6.0 * 2.0 * math.pi + (0.5 / vertex_out)

    local gradient_p0 = ImVec2(textcenter.x + math.cos(a0) * text_inner, textcenter.y + math.sin(a0) * text_inner)
    local gradient_p1 = ImVec2(textcenter.x + math.cos(a1) * text_inner, textcenter.y + math.sin(a1) * text_inner)
    dl:ShadeVertsLinearColorGradientKeepAlpha(vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n + 1], col_hues[n + 2]);
    -- end

    imgui.SetCursorScreenPos(ImVec2(pos.x, pos.y + size.y + imgui.GetStyle().ItemSpacing.y))
end
Применение:
Применение:
imgui.OnFrame(
    function() return not isGamePaused() end,
    function(self)
        local resX, resY = getScreenResolution()
        local menuWidth = 200
        local menuHeight = resY * 0.55
     
        imgui.SetNextWindowPos(imgui.ImVec2(resX / 2, resY / 2), imgui.Cond.Always, imgui.ImVec2(0.5, 0.5))
        imgui.SetNextWindowSize(imgui.ImVec2(menuWidth, menuHeight), imgui.Cond.Always)
        if imgui.Begin('Menu', nil, imgui.WindowFlags.NoMove + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoTitleBar) then
            imgui.TextGradiented("STRING STRING STRING", 0xFFFF8806, 0xFFFFC586)
            imgui.TextGradiented("STRING STRING STRING", 0xFFFFFF00, 0xFF00FFFF)
            imgui.TextGradiented("STRING STRING STRING", 0xFF0000FF, 0x33FF00FF)

            imgui.End()
        end
    end
)
1728581532048.png

Не нашёл этого на луа, решил адаптировать с C++ на imgui сампа. Надеюсь кому-то поможет)
Переписал на LUA отсюда: https://yougame.biz/threads/269747/?ysclid=m23kmknpma583135197
Функция ShadeVertsLinearColorGradientKeepAlpha отсюда: https://www.blast.hk/threads/13380/post-1258614
 

g305noobo

Известный
Модератор
304
479
описание: Аналог getAllChars из MoonLoader в TrilogyLoader
Lua:
local ffi = require("ffi")

ffi.cdef([[
typedef unsigned __int64 uintptr_t;
void* GetModuleHandleA(const char* lpModuleName);

typedef union {
    struct {
        uint8_t nId : 7;
        bool bEmpty : 1;
    };
    uint8_t nValue;
} tPoolObjectFlags;

typedef struct {
    void* m_aStorage;         
    tPoolObjectFlags* m_aFlags;           
    int32_t m_nSize;           
    int32_t m_nFreeIndex;     
    bool m_bOwnsArrays;       
    bool m_bDealWithNoMemory; 
} CPool;
]])

local CPool = {}
CPool.__index = CPool

function CPool.new(poolPtr)
    local self = setmetatable({}, CPool)
    self.pool = poolPtr
    return self
end

function CPool:IsFreeSlotAtIndex(idx)
    return self.pool.m_aFlags[idx].bEmpty
end

function CPool:GetIndex(pObject)
    local pObjectB = ffi.cast("uintptr_t", pObject)
    local m_aStorageB = ffi.cast("uintptr_t", self.pool.m_aStorage)
    return pObjectB - m_aStorageB
end

function CPool:GetRef(pObject)
    local index = self:GetIndex(pObject)
    local id = self.pool.m_aFlags[index].nValue
    return bit.lshift(index, 8) + id
end

function CPool:GetAt(nIndex)
    if not self:IsFreeSlotAtIndex(nIndex) then
        return ffi.cast("uintptr_t", ffi.cast("uint8_t*", self.pool.m_aStorage) + nIndex * 1)
    else
        return nil
    end
end

function getAddress(offset)
    local baseAddress = ffi.cast("uintptr_t", ffi.C.GetModuleHandleA("SanAndreas.exe"))
    return baseAddress + offset
end

function getAllChars()
    local ms_pPedPool = ffi.cast("CPool**", getAddress(0x55706E0))[0]
    local peds = CPool.new(ms_pPedPool)

    local peds_handles = {}
    for i = 0, peds.pool.m_nSize - 1 do
        local ped = peds:GetAt(i)
        if ped then
            local handle = peds:GetRef(ped)
            table.insert(peds_handles, handle)
        end
    end

    return peds_handles
end
пример:
Lua:
function onScriptLoad()
    local chars = getAllChars()
    for i = 1, #chars do
        print(chars[i])
    end
end