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

RTD

Потужно
Модератор
399
470
Описание: Простейшая функция для того чтобы писать на hex asm(оно же байтами ассемблера). Теоретически можно любую функцию Си перевести в hex asm и вставить в эту функцию, потом вызывать с луа(хе-хе, извращение). Написал по фану, но может кому-то нужно будет, возможно даже кто-нибудь улучшит(к примеру добавит расчет смещения для E8(call - опкод asm) и E9(jmp - опкод asm))
Первый параметр сам hex asm, а второй прототип функции.
Lua:
local ffi = require 'ffi'
ffi.cdef [[
    void* VirtualAlloc(void* lpAddress, unsigned long dwSize, unsigned long  flAllocationType, unsigned long flProtect);
    int VirtualFree(void* lpAddress, unsigned long dwSize, unsigned long dwFreeType);
]]
function hexAsmCode(asm, prototype)
    local bytes = {}
    for byte in asm:gmatch('(%x%x)') do
        table.insert(bytes, tonumber('0x'..byte))
    end
    local code = ffi.new('uint8_t[?]', #bytes, bytes)
    local addr = ffi.gc(ffi.C.VirtualAlloc(nil, ffi.sizeof(code), 0x1000, 0x40), function(addr) ffi.C.VirtualFree(addr, 0, 0x8000) end)
    ffi.copy(addr, code, ffi.sizeof(code))
    return ffi.cast(prototype, addr)
end
Пример использования:
Lua:
local code = [[
    55                  
    89 E5              
    8B 45 08            
    0F AF 45 08          
    5D                  
    C3
]] -- или просто в одну строку типа 5589E58B45080FAF45085DC3
--Это функция int square(int a) return a*a
local square = hexAsmCode(code, 'int (__cdecl*)(int)')
print(square(4)) --вернет 16
 

AnWu

Известный
Всефорумный модератор
4,777
5,400
Описание: Добавляет в игру собственный таргет, вычисляет ближайшего игрока или машину НАПРОТИВ педа (требуется доработка, но выбирает из всего рядом именно то что перед игроком). Возвращает таблицу
Lua:
 local result = {
    exists, -- Найден ли модификатор
    eType, -- Тип "Char" или "Car"
    value, -- Возвращенный хендл
    dist -- дистанция до него
  }
ЗАВИСИМО ОТ https://github.com/DonHomka/extensions-lite
Lua:
function getTargetOnDistance(distance)
  local distance = distance or 0.0
  local allElement = {}
  local chars = table.transform(getAllChars(), function (v)
    return {
      eType = "Char",
      value = v,
    }
  end)
  local vehs = table.transform(getAllVehicles(), function (v)
    return {
      eType = "Car",
      value = v,
    }
  end)
  local allElement = table.merge(chars, vehs)
  local ox, oy, oz = getCharCoordinates(PLAYER_PED)
  local angle = getCharHeading(PLAYER_PED)
  local x, y, z = getOffsetFromCharInWorldCoords(PLAYER_PED, 0.0, 0.5, 0.0)
  local result = {
    exists = false,
    eType = nil,
    value = nil,
    dist = 1488.0
  }
  for k, v in ipairs(allElement) do
    if v.value ~= PLAYER_PED then
      local xt, yt, zt = _G["get" .. v.eType .. "Coordinates"](v.value)
      local distance_ = getDistanceBetweenCoords3d(x, y, z, xt, yt, zt)
      if distance_ < result.dist and distance_ <= distance then
        result = {
          exists = true,
          eType = v.eType,
          value = v.value,
          dist = distance_
        }
      end
    end
  end
  return result
end
Пример использования:
Lua:
    local element = getTargetOnDistance(3.0)
    if element.exists then
      if element.eType == "Char" then
        local ped = element.value
        local result, id = sampGetPlayerIdByCharHandle(ped)
        if result and not sampIsPlayerNpc(id) then
          data.id = id
          data.name = sampGetPlayerNickname(id)
          data.health = sampGetPlayerHealth(id)
          data.maxHealth = 100
          data.armor = sampGetPlayerArmor(id)
          data.maxArmor = 100
        end
      elseif element.eType == "Car" then
        local car = element.value
        local result, id = sampGetVehicleIdByCarHandle(car)
        if result then
          local model = getCarModel(car)
          data.id = id
          data.name = tCarsName[model - 399]
          data.health = getCarHealth(car)
          data.maxHealth = 1000
        end
      end
  end
 

Akionka

akionka.lua
Проверенный
742
502
Описание: Вычисляет соотношение сторон экрана. Мало-ли кому-то понадобится.
Lua:
function getScreenAspect()
  local function gcd (a, b)
    return b == 0 and a or gcd (b, a%b)
  end
  local w, h = getScreenResolution()
  local r = gcd (w, h)
  return w / r, h / r
end
Пример использования:
Lua:
local w, h = getScreenAspect()
print(w, h)
 

ufdhbi

Известный
Проверенный
1,460
866
Imgui текст с тенью
Автор: @FYP
p.s. Теперь можете делать чат на имгуи, проблема шрифтов с обводкой решена
Lua:
function im_colored_text_with_shadow(color, text)
    local pos = imgui.GetCursorPos()
    imgui.SetCursorPos(imgui.ImVec2(pos.x + 1, pos.y + 1))
    imgui.TextColored(imgui.ImVec4(0, 0, 0, 1), text) -- shadow
    imgui.SetCursorPos(pos)
    imgui.TextColored(color, text)
end
 

ImPasha

Software Developer & System Administrator
Друг
1,788
2,142
Описание: Система, которая добавляет возможность создать точечно-круговой лоадер в mimgui.
Огромное спасибо мобильному приложению QIWI за то, что вдохновили меня идеей сделать такое.
Lua:
local mimgui_loader_circle, mimgui_loader_time = 1, os.clock()
local function mimgui_loader(speed)
    local draw_list = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()
    draw_list:AddCircleFilled(imgui.ImVec2(p.x, p.y), 14.0, (mimgui_loader_circle == 1 and 0x25FFFFFF or 0xFFFFFFFF), 30)
    draw_list:AddCircleFilled(imgui.ImVec2(p.x + 64, p.y), 14.0, (mimgui_loader_circle == 2 and 0x25FFFFFF or 0xFFFFFFFF), 30)
    draw_list:AddCircleFilled(imgui.ImVec2(p.x + 128, p.y), 14.0, (mimgui_loader_circle == 3 and 0x25FFFFFF or 0xFFFFFFFF), 30)
    draw_list:AddCircleFilled(imgui.ImVec2(p.x + 192, p.y), 14.0, (mimgui_loader_circle == 4 and 0x25FFFFFF or 0xFFFFFFFF), 30)
    if mimgui_loader_time + speed < os.clock() then  mimgui_loader_time = os.clock()
        if mimgui_loader_circle == 4 then mimgui_loader_circle = 1
        else mimgui_loader_circle = mimgui_loader_circle + 1 end
    end
end
Пример использование:
Lua:
-- Устанавливаем точку, где будет находиться центр первого круга
imgui.SetCursorPos(imgui.ImVec2(800 / 2 - 96, 400))
-- При помощи заранее заготовленной функции запускаем наш лоадер
mimgui_loader(0.3)



Описание: Система, которая добавляет возможность создавать точечно-круговой лоадер в mimgui v.2.0.
Особенность данной версии заключается в том, что лоадер возможно завершить, и он анимировано объединит 4 точки в две.
Lua:
local mimgui_loader_circle, mimgui_loader_time, mimgui_loader_finish = 1, os.clock(), 0
local function mimgui_loader(speed, color)
    if not color then color = 0xFFFFFFFF end
    local draw_list = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()
    if mimgui_loader_finish < 1 then
        draw_list:AddCircleFilled(imgui.ImVec2(p.x, p.y), 14.0, (mimgui_loader_circle == 1 and 0x25FFFFFF or color), 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 64, p.y), 14.0, (mimgui_loader_circle == 2 and 0x25FFFFFF or color), 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 128, p.y), 14.0, (mimgui_loader_circle == 3 and 0x25FFFFFF or color), 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 192, p.y), 14.0, (mimgui_loader_circle == 4 and 0x25FFFFFF or color), 30)
        if mimgui_loader_time + speed < os.clock() then  mimgui_loader_time = os.clock()
            if mimgui_loader_circle == 4 then mimgui_loader_circle = 1
            else mimgui_loader_circle = mimgui_loader_circle + 1 end
        end
    elseif mimgui_loader_finish >= 1 then
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + mimgui_loader_finish / 2, p.y), 14.0, color, 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 64 + mimgui_loader_finish, p.y), 14.0, color, 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 128 - mimgui_loader_finish, p.y), 14.0, color, 30)
        draw_list:AddCircleFilled(imgui.ImVec2(p.x + 192 - mimgui_loader_finish / 2, p.y), 14.0, color, 30)
        if mimgui_loader_time + speed < os.clock() then mimgui_loader_time = os.clock()
            if mimgui_loader_finish < 88 then mimgui_loader_finish = mimgui_loader_finish + 1 end
        end
    end
end
Пример использования:
Lua:
function main()
    sampRegisterChatCommand("openmenu", function()
        mimgui_loader_circle, mimgui_loader_time, mimgui_loader_finish = 1, os.clock(), 0
        mimgui_loading_window[0] = true -- Показываем окно с лоадером
        lua_thread.create(function()
            wait(5000) -- Ожидаем 5 секунд, эмитируя загрузку
            mimgui_loader_finish = 1 -- Завершаем процесс загрузки
        end)
    end)
end

-- Код ниже нужно поместить куда-нибудь в тело mimgui окна
local lspeed = 0.3 -- Задаём скорость мигания точек
if mimgui_loader_finish >= 1 then lspeed = 0.005 end -- Задаём скорость соединения точек
mimgui_loader(lspeed, 0xFFFFFFFF) -- Производим рисование точечно-кругового рендера
P.S. Простите, если я что-то некорректно посчитал, я кодер-гуманитарий, не бейте, пожалуйста.
 
Последнее редактирование:

Carrentine

Потрачен
569
462
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Описание: получает коэффициент смещения прицела для всех оружий по X и по Z координате, учтено и с widescreen, и без.
Код:
Lua:
function getCrosshairOffset()
    local weapon = getCurrentCharWeapon(PLAYER_PED)
    local coefficent = {0.0, 0.0}
    if (weapon >= 22 and weapon <= 29) or weapon == 32 then
        coefficent[1] = 0.04253
        if isWidescreenOnInOptions() then coefficent[2] = 0.0778 else coefficent[2] = 0.103 end
    elseif weapon == 30 or weapon == 31 then
        coefficent[1] = 0.028
        if isWidescreenOnInOptions() then coefficent[2] = 0.052 else coefficent[2] = 0.07 end
    elseif weapon == 33 then
        coefficent[1] = 0.01897
        if isWidescreenOnInOptions() then coefficent[2] = 0.0357 else coefficent[2] = 0.046 end
    end
    return coefficent[1], coefficent[2]
end
Для фикса угла по X нужно суммировать, а по Z вычитать.
 
Последнее редактирование:
  • Злость
Реакции: brabus

Carrentine

Потрачен
569
462
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Описание: устанавливает угол поворота камеры. В оригинальной функции был баг, что если камера более приближена или отдалена от стандартной, то она возвращалась обратно на ту же позицию. Один человек написал мне про эту проблему в моем аимботе, и я сделал функцию без этого бага. Кстати, при слайдах она поварачивает камеру намного плавнее, чем та функция. Вот видео с багом.

Код:
Lua:
function setCameraPositionFixed(zAngle, xAngle) 
    writeMemory(0xB6F258, 4, representFloatAsInt(xAngle), true)
    writeMemory(0xB6F248, 4, representFloatAsInt(zAngle), true)
end

Кстати, @FYP, что ты такого запихнул в функцию, что она так по уебански себя ведет?
 
Последнее редактирование:

imring

Ride the Lightning
Всефорумный модератор
2,365
2,552
Описание: устанавливает угол поворота камеры. В оригинальной функции был баг, что если камера более приближена или отдалена от стандартной, то она возвращалась обратно на ту же позицию. Один человек написал мне про эту проблему в моем аимботе, и я сделал функцию без этого бага. Кстати, при слайдах она поварачивает камеру намного плавнее, чем та функция. Вот видео с багом.

Код:
Lua:
function setCameraPositionFixed(zAngle, xAngle)
    writeMemory(0xB6F258, 4, representFloatAsInt(xAngle), true)
    writeMemory(0xB6F248, 4, representFloatAsInt(zAngle), true)
end

Кстати, @FYP, что ты такого запихнул в функцию, что она так по уебански себя ведет?
чем memory.setfloat плох?
Lua:
memory.setfloat(0xB6F258, xAngle, true)
memory.setfloat(0xB6F248, zAngle, true)
 
  • Нравится
Реакции: AnWu

oxexoexeo

Потрачен
14
7
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Описание:
Функции камер для ботов, можете брать любую

Код:

Lua:
function setCum(px, py)
    local xpos, ypos, _ = getActiveCameraCoordinates()
    local v = {x = px - xpos, y = py - ypos}
    local d = math.sqrt(v.x ^ 5 + v.y ^ 5)
    local ay, ax = math.atan2(d, v.y), math.atan2(v.y, -v.x)
    setCameraPositionUnfixed(-ay/5, -ax)
end

Lua:
function setCum(a, b) -- 1 аргумент координаты персонажа ()таблицей), 2 аргумент координаты куда повернуть ()таблицей)
    local z = b[1] - a[1]
    local cumZ = math.atan((b[2] - a[2]) / z)
    if z >= 0.0 then
        cumZ = cumZ + 3.14
    end
    setCameraPositionUnfixed(0.0, cumZ)
end

Lua:
function setCum(pos1, pos2) -- тут аналогично как и в прошлой функц
   local function f(ang)
    if ang > math.pi then
        ang = ang - (math.pi * 2)
    elseif ang < -math.pi then
        ang = ang + (math.pi * 2)
    end
    return ang
   end
   local vector = {pos1[1] - pos2[1], pos1[2] - pos2[2], pos1[3] - pos2[3]}
     if isWidescreenOnInOptions() then coefficentZ = 0.0778 else coefficentZ = 0.103 end
       local ang = {(math.atan2(vector[2], vector[1]) + 0.04253), (math.atan2((math.sqrt((math.pow(vector[1], 2) + math.pow(vector[2], 2)))), vector[3]) - math.pi / 2 - coefficentZ)}
       local vw = {f(representIntAsFloat(readMemory(0xB6F258, 4, false))), f(representIntAsFloat(readMemory(0xB6F248, 4, false)))}
       local df = {ang[1] - vw[1], ang[2] - vw[2]}
       local smth = {df[1] / 7, df[2] / 7}
   setCameraPositionUnfed((vw[2] + smth[2]), (vw[1] + smth[1]))
end




Описание:
Снимает паблик обфускатор от luaseel (который превращает код в IlIlIllIlIlI и кучу байтов , раньше висел тут но уже нет)

Код:

Lua:
local text = [==[
   --obf
]==]

function split (inputstr, sep)
  if sep == nil then
    sep = "%s"
  end
  local t={}
  for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
    table.insert(t, str)
  end
  return t
end

function deobf(text)
  for w in text:gmatch("(IlIlIlIlIlIlIlIlII = {.*})") do
    loadstring(w)()
    print(table.concat(IlIlIlIlIlIlIlIlII, nil))
  end
end

print(deobf(text))
 
Последнее редактирование:
  • Нравится
Реакции: Eugene Crabs и Rei

The Spark

Известный
664
700
Аналог функции @Carrentine (намного проще и не багает из-за функции получения корд прицела)
Описание: Ищет ближайшего человека к прицелу, с учётом радиуса
Использование:
Lua:
local id, handle = GetClosestToSight(100)
if id and handle then
    sampAddChatMessage(sampGetPlayerNickname(id), -1)
end
Код:
Lua:
function GetClosestToSight(fov)
    local id, va = false, false
    local posX, posY = convertGameScreenCoordsToWindowScreenCoords(339.1, 179.1)
    for k, v in ipairs(getAllChars()) do
        local bool, ida = sampGetPlayerIdByCharHandle(v)
        local x, y, z = getCharCoordinates(v)
        local xi, yi = convert3DCoordsToScreen(x, y, z)
        local dist = math.sqrt( (xi - posX) ^ 2 + (yi - posY) ^ 2)
        if dist < fov then
            fov, id, va = dist, ida, v
        end
    end
    return id, va
end




Описание: Проверяет, виден ли ник игрока по ид. Сверяется с дальностью видимости ников установленную на сервере + стенка + маска
Использование:
Lua:
local id = 19
if isNameTagVisible(id) then
    print("true")
else
    print("false")
end
Код:
Lua:
function isNameTagVisible(id)
    local function getBodyPartCoordinates(id, handle)
        local ffi = require "ffi"
        local getBonePosition = ffi.cast("int (__thiscall*)(void*, float*, int, bool)", 0x5E4280)
        local pedptr = getCharPointer(handle)
        local vec = ffi.new("float[3]")
        getBonePosition(ffi.cast("void*", pedptr), vec, id, true)
        return vec[0], vec[1], vec[2]
    end

    local function GetMaskStats(id)
        local StructPtr = readMemory(sampGetPlayerStructPtr(id), 4, true)
        local Element = getStructElement(StructPtr, 179, 2, false)
        if Element == 0 then return false else return true end
    end

    local res = false
    local pStSet = sampGetServerSettingsPtr()
    local NTdist = representIntAsFloat(readMemory(pStSet + 39, 4, false))
    local bool, v = sampGetCharHandleBySampPlayerId(id)
    if bool and isCharOnScreen(v) then
        local x, y, z = getBodyPartCoordinates(8, v)
        local xi, yi, zi = getActiveCameraCoordinates()
        local result = isLineOfSightClear(x, y, z, xi, yi, zi, true, false, false, true, false)
        local dist = math.sqrt( (xi - x) ^ 2 + (yi - y) ^ 2 + (zi - z) ^ 2 )
        if result and dist <= NTdist and GetMaskStats(id) then
            res = true
        end
    end
    return res
end
 
Последнее редактирование:

imring

Ride the Lightning
Всефорумный модератор
2,365
2,552
LuaJIT-ImGui (mimgui)
Описание: перенос текста.
Lua:
-- https://github.com/juliettef/imgui_markdown/blob/master/imgui_markdown.h#L230
local function imgui_text_wrapped(clr, text)
    if clr then imgui.PushStyleColor(ffi.C.ImGuiCol_Text, clr) end

    text = ffi.new('char[?]', #text + 1, text)
    local text_end = text + ffi.sizeof(text) - 1
    local pFont = imgui.GetFont()

    local scale = 1.0
    local endPrevLine = pFont:CalcWordWrapPositionA(scale, text, text_end, imgui.GetContentRegionAvail().x)
    imgui.TextUnformatted(text, endPrevLine)

    while endPrevLine < text_end do
        text = endPrevLine
        if text[0] == 32 then text = text + 1 end
        endPrevLine = pFont:CalcWordWrapPositionA(scale, text, text_end, imgui.GetContentRegionAvail().x)
        if text == endPrevLine then
            endPrevLine = endPrevLine + 1
        end
        imgui.TextUnformatted(text, endPrevLine)
    end

    if clr then imgui.PopStyleColor() end
end
Использование:
Lua:
imgui_text_wrapped(imgui.ImVec4(1.0, 0.0, 0.0, 1.0) --[[red color]], 'Hello, World!')

Описание: заменяет цвет текста форматом RRGGBB(AA).
Вернуть цвет текста на стандартный (ImGuiCol_Text) - {STANDART}.
Lua:
local function imgui_text_color(text, wrapped)
    text = text:gsub('{(%x%x%x%x%x%x)}', '{%1FF}')
    local render_func = wrapped and imgui_text_wrapped or function(clr, text)
        if clr then imgui.PushStyleColor(ffi.C.ImGuiCol_Text, clr) end
        imgui.TextUnformatted(text)
        if clr then imgui.PopStyleColor() end
    end


    local color = colors[ffi.C.ImGuiCol_Text]
    for _, w in ipairs(split(text, '\n')) do
        local start = 1
        local a, b = w:find('{........}', start)
        while a do
            local t = w:sub(start, a - 1)
            if #t > 0 then
                render_func(color, t)
                imgui.SameLine(nil, 0)
            end

            local clr = w:sub(a + 1, b - 1)
            if clr:upper() == 'STANDART' then color = colors[ffi.C.ImGuiCol_Text]
            else
                clr = tonumber(clr, 16)
                if clr then
                    local r = bit.band(bit.rshift(clr, 24), 0xFF)
                    local g = bit.band(bit.rshift(clr, 16), 0xFF)
                    local b = bit.band(bit.rshift(clr, 8), 0xFF)
                    local a = bit.band(clr, 0xFF)
                    color = imgui.ImVec4(r / 255, g / 255, b / 255, a / 255)
                end
            end

            start = b + 1
            a, b = w:find('{........}', start)
        end
        imgui.NewLine()
        if #w > start - 1 then
            imgui.SameLine(nil, 0)
            render_func(color, w:sub(start))
        end
    end
end
Пример:
Lua:
imgui_text_color('{FFFFFF}text1 {STANDART}text2 {CCFF00}text3 {FF0000}text4')
 

AnWu

Известный
Всефорумный модератор
4,777
5,400
Описание: Выставляет элемент под углом. Можно анимировать иконки (вращение). Например шестеренку настроек. С углами не совсем разобрался, выставляйте как вам удобно.
Не помещайте более одного элемента между функциями! (Увидите вальс элементов где-то в начале окна)
Lua:
local rotation_start_index
function ImMin(lhs, rhs) return imgui.ImVec2(math.min(lhs.x, rhs.x), math.min(lhs.y, rhs.y)); end
function ImMax(lhs, rhs) return imgui.ImVec2(math.max(lhs.x, rhs.x), math.max(lhs.y, rhs.y)); end
function ImRotate(v, cos_a, sin_a) return imgui.ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); end
function ImRotateStart()
   rotation_start_index = imgui.GetWindowDrawList().VtxBuffer.Size;
end
function ImRotationCenter()
   local l, u = imgui.ImVec2(imgui.FLT_MAX, imgui.FLT_MAX), imgui.ImVec2(-imgui.FLT_MAX, -imgui.FLT_MAX); -- bounds
   local buf = imgui.GetWindowDrawList().VtxBuffer
   for i = rotation_start_index, buf.Size - 1 do
      l, u = ImMin(l, buf.Data[i].pos), ImMax(u, buf.Data[i].pos);
   end
   return imgui.ImVec2((l.x+u.x)/2, (l.y+u.y)/2); -- or use _ClipRectStack?
end
function calcImVec2(l, r) return { x = l.x - r.x, y = l.y - r.y } end
function ImRotateEnd(rad, center)
   if center == nil then
      center = ImRotationCenter()
   end
   local s, c = math.sin(rad), math.cos(rad);
   center = calcImVec2(ImRotate(center, s, c), center);
   local buf = imgui.GetWindowDrawList().VtxBuffer;
   for i = rotation_start_index, buf.Size - 1 do
      buf.Data[i].pos = calcImVec2(ImRotate(buf.Data[i].pos, s, c), center);
   end
end
Пример использования:
Lua:
   ImRotateStart();
   imgui.TextDisabled(u8"Загрузка ..")
   ImRotateEnd(-os.clock() * 5.5);
+ файл.
 

Вложения

  • mimgui blank.lua
    7.8 KB · Просмотры: 50
Последнее редактирование:

ImPasha

Software Developer & System Administrator
Друг
1,788
2,142
Описание: Функция сравнивает любое количество наборов дат и выводит самую наибольшую.
Примечание: если все даты равны, функция просто будет выводить "true"; для сравнения нужны как минимум две даты.
Lua:
function cmpDates(...)
  if type(arg) ~= 'table' then return false end -- if no args, return false
  local arguments = {}
  if #arg == 1 and type(arg[1]) == 'table' then -- if dates in one table
    local temp_arr = {}
    for i, v in ipairs(arg[1]) do
      if #arg[1][i] == 3 then
        temp_arr[#temp_arr+1] = {v[1], v[2], v[3]}
      end
    end arguments = temp_arr
  else arguments = arg end
  local valid_dates = {}
  for i, v in ipairs(arguments) do -- validation dates process
    if type(v[1]) == 'number' and type(v[2]) == 'number' and type(v[3]) == 'number' then
      if v[1] > 0 and v[1] <= 31 and v[2] > 0 and v[2] <= 12 and v[3] > 0 then
        valid_dates[#valid_dates+1] = {v[3], v[2], v[1]} -- year, month, date
      end
    end
  end
  if #valid_dates < 2 then return false end -- if less than two dates, return false
  local all_equals = true
  local d, m, y = valid_dates[1][1], valid_dates[1][2], valid_dates[1][3]
  for i, v in ipairs(valid_dates) do
    if i > 1 then
      if v[1] ~= d or v[2] ~= m or v[3] ~= y then
        all_equals = false
      end
    end
  end
  if all_equals then return true end
  local date_leader = -1
  local max_year, max_month, max_date = 0, 0, 0
  for i, v in ipairs(valid_dates) do
    if max_year == 0 then date_leader, max_year, max_month, max_date = i, v[1], v[2], v[3]
    elseif max_year < v[1] then
      date_leader, max_year, max_month, max_date = i, v[1], v[2], v[3]
    elseif max_year == v[1] then
      if max_month < v[2] then
        date_leader, max_year, max_month, max_date = i, v[1], v[2], v[3]
      elseif max_month == v[2] then
        if max_date < v[3] then
          date_leader, max_year, max_month, max_date = i, v[1], v[2], v[3]
        end
      end
    end
  end
  return date_leader
end
Пример использования: Сравниваем даты рождения пользователей и выводим самого старшего.
Lua:
local users, frm_dates = {
  {'Данилочка', '12.06.2000'},
  {'Виталечка', '02.12.1991'},
  {'Пашечка', '16.03.2013'},
  {'Алёшечка', '23.08.1976'}
}, {}
for i, v in ipairs(users) do
  if type(v[2]) == 'string' then
  local day, month, year = v[2]:match("^(%d+)%.(%d+)%.(%d+)$")
    if day and month and year then
      frm_dates[#frm_dates+1] = {tonumber(day), tonumber(month), tonumber(year)}
    end
  end
end
local result = cmpDates(frm_dates)
if result == true then print("Все мальчики одинакового возраста!")
elseif type(result) == 'number' and result > 0 and result <= #users then
  print(users[result][1] .. ' старше, чем остальные мальчики!')
else print('Произошла ошибка!') end
Обратите внимание, что можно помещать массивы с датами в один массив и отправлять одним параметром, либо указывать несколько массивов с датами прямо в параметрах функции. Ниже имеется второй пример с самым простым использованием и указанием нескольких массивных параметров.
Lua:
local result = cmpDates({1, 1, 2010}, {1, 1, 2015}, {1, 1, 2020})
print(result) -- RESPONSE: 3
 
  • Нравится
Реакции: ShuffleBoy, AnWu и Dan4s

Musaigen

abobusnik
Проверенный
1,619
1,396
Описание: позволяет отрисовать градиент(квадрат).
Lua:
function join_argb(a, r, g, b)
    local argb = b -- b
    argb = bit.bor(argb, bit.lshift(g, 8)) -- g
    argb = bit.bor(argb, bit.lshift(r, 16)) -- r
    argb = bit.bor(argb, bit.lshift(a, 24)) -- a
    return argb
end

function explode_argb(argb)
    local a = bit.band(bit.rshift(argb, 24), 0xFF)
    local r = bit.band(bit.rshift(argb, 16), 0xFF)
    local g = bit.band(bit.rshift(argb, 8), 0xFF)
    local b = bit.band(argb, 0xFF)
    return a, r, g, b
end

--[[
    @params:
        * from от какого цвета(в HEX)
        * to до какого цвета(в HEX)
        * vertical true = сверху вниз
]]
function gradient_box(x, y, w, h, from, to, vertical)
    renderDrawBox(x, y, w, h, from)
    local a, r, g, b = explode_argb(to)

    local w_h = vertical and h or w

    for i = 0, w_h do
        local a = (i / w_h) * 255
        if vertical then
            renderDrawBox(x, y + i, w, 1, join_argb(a, r, g, b))
        else
            renderDrawBox(x + i, y, 1, h, join_argb(a, r, g, b))
        end
    end
end
Пример использования:
Lua:
function main()
    while true do
        wait(0)

        gradient_box(250, 250, 100, 100, 0xFF007FFF, 0xFFFF00FF, true)
        gradient_box(350, 350, 100, 100, 0xFF007FFF, 0xFFFF00FF)
        -- Также можно сделать ColorPicker как в imgui.
    end
end
Credits: GitHub
 

Xenocell

Новичок
1
3
Описание: Позволяет получить угол поворота игрока к игроку.
Lua:
function GetPedAngleToPed(ped_1, ped_2)
    local p1X, p1Y, p1Z = getCharCoordinates(ped_1)
    local p2X, p2Y, p2Z = getCharCoordinates(ped_2)
    local p2A = getCharHeading(ped_2)
    local diffX, diffY = p1X - p2X, p1Y - p2Y
    local Angle = getHeadingFromVector2d(diffX, diffY)
    Angle = (Angle < p2A) and (360 - p2A) + Angle or Angle - p2A
    return math.floor(Angle)
end

Пример использования: Получаем угол поворота игрока в таргете относительно вашего персонажа.
Lua:
function main()
    while not isSampAvailable() do wait(0) end
    while true do
        wait(500)
        local result, target_ped = getCharPlayerIsTargeting(0)
        if result then 
            local _, id = sampGetPlayerIdByCharHandle(target_ped)
            sampAddChatMessage('Угол '..sampGetPlayerNickname(id) .. ' относительно вашего персонажа составляет: ' .. GetPedAngleToPed(PLAYER_PED, target_ped) .. '°', 0xAFAFAF)
        end
    end
end