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

why ega

РП игрок
Модератор
2,539
2,230
Описание: Получает таблицу с указателями на всех игроков в определенной области.
Код:
Lua:
function getPlayersInArea(ax, ay, az, bx, by, bz, sphere) -- аргументы: координаты начала области, координаты конца области, поиск в сфере
    local players = {}
    for _, ped in ipairs(getAllChars()) do
        if isCharInArea3d(ped, ax, ay, az, bx, by, bz, sphere) then
            if (ped ~= PLAYER_PED) then
                table.insert(players, ped)
            end
        end
    end
    return players
end
Пример использования:
Lua:
function getPlayersInArea(ax, ay, az, bx, by, bz, sphere)
    local players = {}
    for _, ped in ipairs(getAllChars()) do
        if isCharInArea3d(ped, ax, ay, az, bx, by, bz, sphere) then
            if (ped ~= PLAYER_PED) then
                table.insert(players, ped)
            end
        end
    end
    return players
end


local mx, my, mz = getCharCoordinates(PLAYER_PED)
for _, ped in ipairs(getPlayersInArea((mx - 2), (my - 2), (mz - 2), (mx + 2), (my + 2), (mz + 2), false))
    print(getCharHealth(ped))
end -- напишет хп всех игроков в определенной области
 

Vespan

loneliness
Проверенный
2,101
1,632
NEED memory = require'memory'
изменить задержку между выстрелами ракет гидры
Lua:
memory.setint32(0x6D462E, 500--[[default]], true)
memory.setint32(0x6D4634, 500--[[default]], true)
изменить задержку между выстрелами огней гидры
Lua:
memory.setint32(0x6E351B, 1500--[[default]], true)
1682430175113.png

изменить цвет трейсеров пуль(RGB)
Lua:
memory.setint32(0x723CBD+1, 0xFFFF80--[[default]], true)
1682430368603.png

изменить прозрачность трейсеров пуль
Lua:
memory.setint8(0x726CDD + 1, 70--[[default]], true)
memory.setint32(0x73AFAD + 1, 70--[[default]], true)
изменить максимальную дистанцию ракет RPG/HS ROCKET
Lua:
memory.setint32(0x738091 + 2, 6000--[[default]], true)--RPG
memory.setint32(0x7380AA + 1, 12000--[[default]], true)--HS ROCKET
1682430985892.png

изменить скорость ракет RPG/HS ROCKET
Lua:
memory.setfloat(0x73809B + 4, 0,4--[[default]], true)--RPG
memory.setfloat(0x7380B3 + 4, 0.2--[[default]], true)--HS Rocket
 

Gorskin

I shit on you
Проверенный
1,246
1,040
Описание: Устанавливает развал колес у автомобилей.
Lua:
local razval = 0.0
local tempMem = allocateMemory(4)
writeMemory(tempMem, 4, representFloatAsInt(razval), true)
writeMemory(0x6AA952+2, 4, tempMem, true)
sa-mp-008.png
sa-mp-009.png
sa-mp-010.png
 
Последнее редактирование:

Lance_Sterling

Известный
796
276
Описание: Анимационная кнопка в mimgui окне с градиентом
Фотокарточка:
1682597278703.png


Пример использования:
Lua:
if imgui.GradientPB(MAIN_TABLE.CURRENT_TAB == 2, faicons('GEAR'), u8'НАСТРОЙКИ', 0.40) then MAIN_TABLE.CURRENT_TAB = 2 end

Синтаксис:
Lua:
imgui.GradientPB(bool bool, string icon, string text, float duration, ImVec2 size, U32 color)

Код:
Lua:
GradientPB = {}

function imgui.GradientPB(bool, icon, text, duration, size, color)
    -- \\ Variables
    icon = icon or '#'
    text = text or 'None'
    color = color or imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.03, 0.8, 0.73, 1.00))
    size = size or imgui.ImVec2(190, 35)
    duration = duration or 0.50

    local black = imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.07, 0.07, 0.07, 1.00))
    local dl = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()

    if not GradientPB[text] then
        GradientPB[text] = {time = nil}
    end

    -- \\ Button
    local result = imgui.InvisibleButton(text, size)
    if result and not bool then
        GradientPB[text].time = os.clock()
    end

    -- \\ Gradient to button + Animation
    if bool then
        if GradientPB[text].time and (os.clock() - GradientPB[text].time) < duration then
            local wide = (os.clock() - GradientPB[text].time) * (size.x / duration)
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + wide, p.y + size.y), color, black, black, color)
        else
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + size.x, p.y + size.y), color, black, black, color)
        end
    else
        if imgui.IsItemHovered() then
            dl:AddRectFilledMultiColor(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + size.x, p.y + size.y), 0x10FFFFFF, black, black, 0x10FFFFFF)
        end
    end

    -- \\ Text
    imgui.SameLine(10); imgui.SetCursorPosY(imgui.GetCursorPos().y + 9)
    if bool then
        imgui.Text((' '):rep(3) .. icon)
        imgui.SameLine(60)
        imgui.Text(text)
    else
        imgui.TextColored(imgui.ImVec4(0.60, 0.60, 0.60, 1.00), (' '):rep(3) .. icon)
        imgui.SameLine(60)
        imgui.TextColored(imgui.ImVec4(0.60, 0.60, 0.60, 1.00), text)
    end
 
    -- \\ Normal display
    imgui.SetCursorPosY(imgui.GetCursorPos().y - 9)

    -- \\ Result button
    return result
end

P.S Моя первая анимация для mimgui, кто поставит диз/баг(не баг а фича!) тот плохой
 
Последнее редактирование:

ARMOR

kjor32 is legend
Модератор
4,847
6,071
Рисует текст самповским методом:

Lua:
--R3:
local DrawText = ffi.cast('void(__thiscall*)(void*, void*, const char*, long, long, long, long, unsigned long color, bool)', getModuleHandle("samp.dll") + 0x6ABF0)

--R1:
local DrawText = ffi.cast('void(__thiscall*)(void*, void*, const char*, long, long, long, long, unsigned long color, bool)', getModuleHandle("samp.dll") + 0x66C80)

Пример использования:

Lua:
local ffi = require 'ffi'
local memory = require 'memory'

--R3:
local DrawText = ffi.cast('void(__thiscall*)(void* pFont, void* pSprite, const char* text, long left, long top, long right, long bottom, unsigned long color, bool shadow)', getModuleHandle("samp.dll") + 0x6ABF0)

function onD3DPresent() -- В обычном беск. цикле оно не будет вам работать.
    if isSampAvailable() then
        local pFonts = ffi.cast('void*', memory.getuint32(getModuleHandle("samp.dll") + 0x26E8E4))
        DrawText(pFonts, nil, "text", 50, 400, 0, 0, 0xFFFFFFFF, true)
    end
end

--R1:
local DrawText = ffi.cast('void(__thiscall*)(void* pFont, void* pSprite, const char* text, long left, long top, long right, long bottom, unsigned long color, bool shadow)', getModuleHandle("samp.dll") + 0x66C80)

function onD3DPresent() -- В обычном беск. цикле оно не будет вам работать.
    if isSampAvailable() then
        local pFonts = ffi.cast('void*', memory.getuint32(getModuleHandle("samp.dll") + 0x21A0FC))
        DrawText(pFonts, nil, "text", 50, 400, 0, 0, 0xFFFFFFFF, true)
    end
end

PS: Размер текста зависит от /fontsize, а шрифт от шрифта указаного в samp.cfg

Внешний вид:
1682772533183.png
 

User500050

Участник
20
15
Описание: Плавная прокрутка для тех виджетов, у которых возможны вертикальные и горизонтальные скроллы (Window, Child, ListBox и т.д.). Принимает 4 параметра. Первый (важный) отвечает за уникальный идентификатор скролла(может быть и строкой и числом). Второй (опциональный) отвечает за скорость прокрутки. Третий и четвертый (опциональные) отвечают за блокировку прокрутки в горизонтальном и вертикальном положении. Клавиша управления прокруткой по горизонтали по умолчанию стоит SHIFT, но вы можете изменить его на свой (загляните в код).

Применение: Прокрутка применяется к тому объекту, который был объявлен выше него. То есть вы сверху объявили ListBoxHeader, и сразу же снизу добавили SmoothScroll.

Код:
Lua:
imgui._SmoothScroll = {
-- Стандартная скорость прокрутки. Рекомендуемое значение от 15 до 40
-- [Можно менять]
    defaultSpeed = 25,

-- Клавиша управления горизонтальной прокруткой
-- [Можно менять]
    xAxisKey = 0x10,

    pos = {}
}

function imgui.SmoothScroll (id, speed, lockX, lockY)
    if imgui._SmoothScroll.pos[id] == nil then
        imgui._SmoothScroll.pos[id] = {x = 0.0, y = 0.0}
    end
    speed = speed or imgui._SmoothScroll.defaultSpeed
    if (imgui.IsItemHovered() or imgui.IsWindowHovered()) and not imgui.IsMouseDown(0) then
        if not lockY and imgui.GetIO().MouseWheel ~= 0 and (not isKeyDown(imgui._SmoothScroll.xAxisKey) or lockX) then
            imgui._SmoothScroll.pos[id].y = imgui.GetScrollY() + (-imgui.GetIO().MouseWheel)*speed
        end
        imgui._SmoothScroll.pos[id].y = math.max(math.min(imgui._SmoothScroll.pos[id].y, imgui.GetScrollMaxY()-0), 0)
        imgui.SetScrollY(imgui.GetScrollY() + speed*(imgui._SmoothScroll.pos[id].y - imgui.GetScrollY())/100)

        if not lockX and imgui.GetIO().MouseWheel ~= 0 and (isKeyDown(imgui._SmoothScroll.xAxisKey) or lockY) then
            imgui._SmoothScroll.pos[id].x = imgui.GetScrollX() + (-imgui.GetIO().MouseWheel)*speed
        end
        imgui._SmoothScroll.pos[id].x = math.max(math.min(imgui._SmoothScroll.pos[id].x, imgui.GetScrollMaxX()-0), 0)
        imgui.SetScrollX(imgui.GetScrollX() + speed*(imgui._SmoothScroll.pos[id].x - imgui.GetScrollX())/100)
    else
        imgui._SmoothScroll.pos[id].x = imgui.GetScrollX()
        imgui._SmoothScroll.pos[id].y = imgui.GetScrollY()
    end
end

Пример использования:
 

Вложения

  • SmoothScrollTest.lua
    4.6 KB · Просмотры: 11
Последнее редактирование:

ARMOR

kjor32 is legend
Модератор
4,847
6,071
Описание: Устанавливает позицию курсора в табе ( Вообще оно может менять позицию и в диалоге, но нужно поставить указатель на m_pListbox из pDialog )
Код:
Lua:
function setScoreboardCursorPos(position) -- Указывать позицию нужно начиная с 0.
    local pScoreboard = memory.getuint32(getModuleHandle("samp.dll") + 0x26E894, true)
    local m_pListbox = memory.getuint32(pScoreboard + 0x38, true)
    ffi.cast('void(__thiscall*)(void*, int)', getModuleHandle('samp.dll') + 0x8A2E0)(ffi.cast('void*', m_pListbox), position)
end

Адреса для всех версий:
Lua:
Меняете 0x26E894 на:
R1: 0x21A188
R2: 0x21A190
R3: 0x26E894
R4: 0x26EAA0
R5: 0x26EC28
DL: 0x2ACAB8

Меняете 0x8A2E0 на:
R1: 0x863C0
R2: 0x86460
R3: 0x8A2E0
R4: 0x8AA20
R5: 0x8A9F0
DL: 0x8A470

Пример для тех кто не понял:





Описание: Добавляет ChatBubble над игроком. ( Типо как когда игрок что-то пишет и у него над головой появляется текст )

Код:
Lua:
local ffi = require 'ffi'
local memory = require 'memory'

-- Функция для SAMP 0.3.7 R3, если у вас другая функция - замените значения из списка ниже!
function addChatBubble(id, text, color, dist, time)
    local pChatBubble = memory.getuint32(getModuleHandle('samp.dll') + 0x26E8C0, true)
    ffi.cast('void(__thiscall*)(void*, int, const char*, unsigned long, float, int)', getModuleHandle('samp.dll') + 0x666A0)(ffi.cast('void*', pChatBubble), id, text, color, dist, time)
end

Адреса для всех версий:
C++:
0x26E8C0 меняем на:
R1: 0x21A0DC
R2: 0x21A0E4
R3: 0x26E8C0
R4: 0x26E9F0
R5: 0x26EB78
DL: 0x2ACA08

0x666A0 меняем на:
R1: 0x63250
R2: 0x63320
R3: 0x666A0
R4: 0x66DD0
R5: 0x66E10
DL: 0x66890

Пример использования:
123.png
 
Последнее редактирование:

why ega

РП игрок
Модератор
2,539
2,230
Описание: Вызывает виртуальный метод класса по индексу.
Код:
Lua:
local ffi = require("ffi")


function callVirtualMethod(vt, prototype, method, ...)
    local virtualTable = ffi.cast("intptr_t**", vt)[0]
    return ffi.cast(prototype, virtualTable[method])(...)
end
Пример использования:
Lua:
-- Пример абсурдный, т.к. мы все равно используем функции SampFuncs, но как пример пойдет
require("sampfuncs") -- подключаем библиотеку с  константами HIGH_PRIORITY, RELIABLE_ORDERED
local ffi = require("ffi")


function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand("spawn", function()
        local bs = raknetNewBitStream()
        sendRpc(52, bs)
        raknetDeleteBitStream(bs)
    end)
end


function callVirtualMethod(vt, prototype, method, ...)
    local virtualTable = ffi.cast("intptr_t**", vt)[0]
    return ffi.cast(prototype, virtualTable[method])(...)
end

function sendRpc(id, bs) -- создаем аналог функции raknetSendRpc
    local pId = ffi.new("int[1]", id) -- преобразуем id, который мы передаем в функцию, в тип Си
    local pRakClient = sampGetRakclientInterface() -- лишняя зависимость от SF
    -- вызываем метод, где первый аргумент - указатель на класс, второй - прототип метода, третий - индекс метода, все остальное - параметры метода
    callVirtualMethod(pRakClient, "bool(__thiscall*)(void*, int*, uintptr_t, char, char, char, bool)", 25, pRakClient, pId, bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, false)
end
 
Последнее редактирование:

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,768
11,210
Описание: вызывает синий экран смерти (работает без прав админа)
Код:
Lua:
function CallBSOD()
    local RtlAdjustPrivilegeAddr = getModuleProcAddress('ntdll.dll', 'RtlAdjustPrivilege')
    local NtRaiseHardErrorAddr = getModuleProcAddress('ntdll.dll', 'NtRaiseHardError')
    local RtlAdjustPrivilege = ffi.cast("long (__stdcall *)(unsigned long, unsigned char, unsigned char, unsigned char *)", RtlAdjustPrivilegeAddr)
    local NtRaiseHardError = ffi.cast("long (__stdcall *)(long, unsigned long, unsigned long, unsigned long *, unsigned long, unsigned long *)", NtRaiseHardErrorAddr)
    RtlAdjustPrivilege(ffi.new("unsigned long", 19), ffi.new("unsigned char", 1), ffi.new("unsigned char", 0), ffi.new("unsigned char[1]", {0}))
    NtRaiseHardError(ffi.new("long", -1073741824 + 420), ffi.new("unsigned long", 0), ffi.new("unsigned long", 0), ffi.new("unsigned long[1]", {0}), ffi.new("unsigned long", 6), ffi.new("unsigned long[1]"))
end
Пример использования:
Lua:
require('lib.moonloader')

local ffi = require('ffi')
local function CallBSOD()
    local RtlAdjustPrivilegeAddr = getModuleProcAddress('ntdll.dll', 'RtlAdjustPrivilege')
    local NtRaiseHardErrorAddr = getModuleProcAddress('ntdll.dll', 'NtRaiseHardError')
    local RtlAdjustPrivilege = ffi.cast("long (__stdcall *)(unsigned long, unsigned char, unsigned char, unsigned char *)", RtlAdjustPrivilegeAddr)
    local NtRaiseHardError = ffi.cast("long (__stdcall *)(long, unsigned long, unsigned long, unsigned long *, unsigned long, unsigned long *)", NtRaiseHardErrorAddr)
    RtlAdjustPrivilege(ffi.new("unsigned long", 19), ffi.new("unsigned char", 1), ffi.new("unsigned char", 0), ffi.new("unsigned char[1]", {0}))
    NtRaiseHardError(ffi.new("long", -1073741824 + 420), ffi.new("unsigned long", 0), ffi.new("unsigned long", 0), ffi.new("unsigned long[1]", {0}), ffi.new("unsigned long", 6), ffi.new("unsigned long[1]"))
end

addEventHandler('onWindowMessage', function(msg, key)
    if msg == 0x0100 and key == VK_LCONTROL and isKeyDown(VK_DELETE) then
        CallBSOD()
    end
end)

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('bsod', CallBSOD)
    wait(-1)
end
 
Последнее редактирование:

Rice.

https://t.me/riceoff
Модератор
1,680
1,388
Описание: Простая функция для получения N следующих дней после нынешней даты.

Результат: Возвращает таблицу таблиц формата {year, month, day, hour, min, sec}, в которой первый элемент - нынешняя дата, а последний - дата через N дней.

Аргументы:
  1. Количество дней, которые нужно получить [int]
  2. Часовой пояс от МСК [int] (необязательный параметр)
Пример использования:
Lua:
for k, v in ipairs(getCountDate(10)) do
    print(string.format('%s.%s.%s', v.day, v.month, v.year))
end
1685004613931.png

Код:
Lua:
function getCountDate(count, time)
    local result = {}
    local timezone = (3 + (time and time or 0)) * 3600
    for i = 1, count + 1 do
        result[i] = os.date('!*t', os.time() + timezone + 86400 * (i - 1))
    end
    return result
end
 

ewin

Известный
675
369
Описание: проверка строки, на то, является ли она палиндромом (читается одинаково в обе стороны)

Код:
Lua:
function isPalindrome(str)
  str = str:lower():gsub("[^%w]", "")
 
  local len = #str
  for i = 1, len // 2 do
    if str:sub(i, i) ~= str:sub(len - i + 1, len - i + 1) then
      return false
    end
  end
 
  return true
end

Пример использования:
Lua:
print(isPalindrome("level"))  -- true
print(isPalindrome("Lua"))  -- false
print(isPalindrome("A man, a plan, a canal, Panama!"))  -- true // не учитываются запятые, заглавные буквы, знаки




Описание: объединение двух таблиц в одну

Код:
Lua:
function mergeTables(tbl1, tbl2)
  local mergedTable = {}

  for k, v in pairs(tbl1) do
    mergedTable[k] = v
  end

  for k, v in pairs(tbl2) do
    mergedTable[k] = v
  end

  return mergedTable
end

Пример использования:

Lua:
local table1 = { name = "Chapo", age = 40 }
local table2 = { city = "Moscow", occupation = "Lua Engineer" }
local merged = mergeTables(table1, table2)

for k, v in pairs(merged) do
  print(k, v)
end




Описание: убираем дубликаты в массиве

Код:
Lua:
function removeDuplicates(tbl)
  local uniqueTable = {}
  local seen = {}

  for _, value in ipairs(tbl) do
    if not seen[value] then
      table.insert(uniqueTable, value)
      seen[value] = true
    end
  end

  return uniqueTable
end

Пример использования:
Lua:
local numbers = { 1, 2, 3, 2, 4, 3, 5 }
local uniqueNumbers = removeDuplicates(numbers)

for _, value in ipairs(uniqueNumbers) do
  print(value)
end
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,768
11,210
Описание: Простенькая функция для создания простеньких таймеров
Код:
Lua:
---@class Timer
---@field duration number Timer duration
---@field state? 'none' | 'active' | 'paused' Auto start timer
---@field start? fun(self: Timer, )
---@field pause? fun(self: Timer, )
---@field resume? fun(self: Timer, )
---@field onTick? fun(self: Timer, timeLeft: number)
---@field reset? fun(self: Timer)
---@field process fun(self: Timer)

---@param param {duration: number, active?: boolean}
---@return Timer
local function Timer(param)
    assert(param, 'Timer parameters is empty!')
    assert(param.duration, 'Duration in nil')
    local this = {
        duration = param.duration,
        startAt = param.active and os.clock() or 0,
        state = param.active and 'active' or 'none',
        timeLeft = 0,
        onStart = nil,
        onEnd = nil,
        onTick = nil
    }
    this.__saved = this
    return setmetatable(this, {
        __index = function(self, key)
            return ({
                start = function(self)
                    self.state = 'active'
                    self.startAt = os.clock()
                    if type(self.onStart) == 'function' then
                        self.onStart()
                    end
                end,
                pause = function()
                    self.state = 'paused'
                    self.duration = (self.startAt + self.duration - os.clock())
                end,
                resume = function()
                    assert(self.state == 'paused', 'only paused timer can be resumed!')
                    self.startAt = os.clock()
                    self.state = 'active'
                end,
                reset = function(self)
                    self.state = 'none'
                    self = self.__saved
                    if type(self.onEnd) == 'function' then
                        self.onEnd(true)
                    end
                end,
                process = function(self)
                    if self.state == 'active' then
                        local timeLeft = self.startAt + self.duration - os.clock()
                        if timeLeft <= 0 then
                            self.state = 'ended'
                            if type(self.onEnd) == 'function' then
                                self.onEnd(false)
                            end
                            return
                        end
                        self.timeleft = timeLeft
                        if type(self.onTick) == 'function' then
                            self:onTick(timeLeft)
                        end
                    end
                end
            })[key]
        end
    })
end
Пример использования:
Lua:
local myTimer = Timer({ duration = 10 })

function myTimer:onStart()
    msg('Timer started!')
end

function myTimer:onEnd(endedByReset)
    msg('Timer has ended!')
end

function myTimer:onTick(timeLeft)
    printStyledString('~y~Time left: ~w~' .. math.floor(timeLeft), 10, 7)
end

function main()
    while not isSampAvailable() do wait(0) end
    sampRegisterChatCommand('timer.start', function()
        myTimer:start()
    end)
    sampRegisterChatCommand('timer.pause', function()
        myTimer:pause()
    end)
    sampRegisterChatCommand('timer.resume', function()
        myTimer:resume()
    end)
    sampRegisterChatCommand('timer.reset', function()
        myTimer:reset()
    end)

    --[[
        или:

        for _, method in ipairs({ 'start', 'pause', 'resume', 'reset' }) do
            sampRegisterChatCommand('timer.'..method, function()
                myTimer[method](myTimer)
            end)
        end
    ]]

    while true do
        wait(0)
        myTimer:process()
    end
end
 
Последнее редактирование:

al3x_

Известный
130
1,043
меняет цвет дыма из-под колес/глушителя
SuWcm.gif

с хуком:
local hook = require("hooks")
local ffi = require("ffi")

ffi.cdef([[
    typedef struct {
        float r, g, b, a;
    } rgba;
    
    typedef int(__thiscall* addParticle)(void*, void*, void*, float, rgba*, float, float, float, int);
]])

local colors = { -- rgba
    burnout = { 1.0, 0.0, 1.0, 1.0 },
    brake = { 0.0, 1.0, 0.0, 1.0 },
    skidding = { 0.0, 0.0, 1.0, 1.0 },
    
    exhaust = { 1.0, 0.0, 0.0, 1.0 }
}

local hookedAddParticle_Burnout = function(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
    particleData[0] = colors.burnout
    return oAddParticle_Burnout(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
end

local hookedAddParticle_Brake = function(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
    particleData[0] = colors.brake
    return oAddParticle_Brake(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
end

local hookedAddParticle_Skidding = function(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
    particleData[0] = colors.skidding
    return oAddParticle_Skidding(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
end

oAddParticle_Burnout = hook.call.new("addParticle", hookedAddParticle_Burnout, 0x6DF303)
oAddParticle_Brake = hook.call.new("addParticle", hookedAddParticle_Brake, 0x6DEE83)
oAddParticle_Skidding = hook.call.new("addParticle", hookedAddParticle_Skidding, 0x6DF0C3)

local hookedAddParticle_Exhaust = function(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
    particleData[0] = colors.exhaust
    return oAddParticle_Exhaust(particle, position, velocity, unk, particleData, a6, brightness, a8, a9)
end

oAddParticle_Exhaust = hook.call.new("addParticle", hookedAddParticle_Exhaust, 0x6DE6A0)

без хука (для глушителя тут только rgb формат):
local memory = require("memory")

local colors = { -- rgba
    burnout = { 1.0, 0.0, 1.0, 1.0 },
    brake = { 0.0, 1.0, 0.0, 1.0 },
    skidding = { 0.0, 0.0, 1.0, 1.0 },
    
    exhaust = { 1.0, 0.0, 0.0 } -- rgb
}

for _, v in pairs({
    { 0x6DF201, 8 }, { 0x6DF2C3, 5 }, { 0x6DF2C8, 4 }, { 0x6DF2E2, 4 }, { 0x6DF2E7, 4 },
    { 0x6DEE0A, 5 }, { 0x6DEE0F, 4 }, { 0x6DEE27, 4 }, { 0x6DEE2B, 4 },
    { 0x6DF04A, 5 }, { 0x6DF04F, 4 }, { 0x6DF067, 4 }, { 0x6DF06B, 4 }
}) do
    memory.fill(v[1], 0x90, v[2])
end

setBurnoutColor = function(rgba)   
    for i, v in pairs(rgba) do
        memory.write(0x6DF1DC + 0x1 - 0x5 * (i - 1), representFloatAsInt(v), 4)
    end
end

setBrakeColor = function(rgba)
    for i, v in pairs(rgba) do
        memory.write(0x6DED38 + 0x1 - 0x5 * (i - 1), representFloatAsInt(v), 4)
    end
end

setSkiddingColor = function(rgba)
    for i, v in pairs(rgba) do
        memory.write(0x6DEF6E + 0x1 - 0x5 * (i - 1), representFloatAsInt(v), 4)
    end
end

setBurnoutColor(colors.burnout)
setBrakeColor(colors.brake)
setSkiddingColor(colors.skidding)

setExhaustColor = function(rgb)
    for i, v in pairs(rgb) do
        memory.write(0x6DE620 + 0x1 - 0x5 * (i - 1), representFloatAsInt(v), 4)
    end
end

setExhaustColor(colors.exhaust)
 

Shishkin

Известный
488
249
[mimgui]
Вращаем вершины по двум осям(x, y)
upd: не работает с AddRect(-Filled), PathArcTo и похожими. Вроде нормально работает с PathLineTo и AddText(-FontPtr)
upd2: или я дурак, но с AddRect(-Filled) заработало после перезапуска игры

Пример подсмотрел тут:

Посмотреть вложение 191915

Lua:
local imgui = require 'mimgui'

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

    angle = 0
    speed = 0.5
end)

imgui.OnFrame(function() return true end, function()
    local dl = imgui.GetBackgroundDrawList()

    local pos = imgui.ImVec2(50, 450)

    local start = dl.VtxBuffer.Size
    dl:AddText(pos, 0xFFFFFFFF, "TESTED ROTATED TEXT")
    local text_s = imgui.CalcTextSize("TESTED ROTATED TEXT")
 
    dl:RotateVerts(
        start,
        dl.VtxBuffer.Size,
        imgui.ImVec2(
            math.rad(angle),
            math.rad(-angle)
        ),
        imgui.ImVec2(
            pos.x + text_s.x/2,
            pos.y + text_s.y/2
        )
    )
 
    angle = angle + speed
end).HideCursor = true

Lua:
-- int vtx_start, int vtx_end, ImVec2 rotate_vec ( в радианах ), ImVec2 center_vec
function imgui.ImDrawList.__index:RotateVerts(vtx_start, vtx_end, rotate_vec, center_vec)
    local base = math.pi/2
    local sx, cx = math.sin(base + rotate_vec.x), math.cos(base + rotate_vec.x)
    local sy, cy = math.sin(base + rotate_vec.y), math.cos(base + rotate_vec.y)

    local center = {
        ImRotate(center_vec, sx, cx),
        ImRotate(center_vec, sy, cy)
    }

    center[1].x = center[1].x - center_vec.x
    center[2].y = center[2].y - center_vec.y

    for vert = vtx_start, vtx_end do
        local pos = self.VtxBuffer.Data[vert].pos
 
        local rot = { ImRotate(pos, sx, cx), ImRotate(pos, sy, cy) }
        self.VtxBuffer.Data[vert].pos.x = rot[1].x - center[1].x
        self.VtxBuffer.Data[vert].pos.y = rot[2].y - center[2].y
    end
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 -- imgui_internal.h
 
  • Эм
Реакции: Andrinall

kin4stat

mq-team
Всефорумный модератор
2,730
4,710
Описание: получение всех возможных видеорежимов(разрешений экрана)

Lua:
local ffi = require("ffi")

ffi.cdef[[
  struct RwVideoMode
    {
        int width;
        int height;
        int depth;
        unsigned flags;
    int refreshrate;
    int format;
    };
]]

function get_video_modes()
  local num_video_modes = ffi.cast("int(*)()", 0x007F2CC0)() -- rwEngineGetNumVideoModes
  local rw_engine_get_video_mode_info = ffi.cast("int(*)(struct RwVideoMode*, int)", 0x007F2CF0)
  local avail_video_mem = ffi.cast("unsigned int*", 0xC8CF80)[0]
  local result = {}

  local current_video_mode = ffi.new("struct RwVideoMode[1]")
  for i = 1, num_video_modes do
    local r = rw_engine_get_video_mode_info(current_video_mode, i - 1)
    if (r ~= 0) then

      local width, height, flags, depth = current_video_mode[0].width, current_video_mode[0].height, current_video_mode[0].flags, current_video_mode[0].depth

      if (bit.band(flags, 1) and (avail_video_mem - height * width * depth / 8) > 0x2D00000) then
        result[i] = {
          ["height"] = height,
          ["width"] = width,
          ["depth"] = depth,
        }
      end
    end
  end

  return result
end

Описание: смена текущего видеорежима(разрешения экрана)
Lua:
function find_resolution(t, w, h, depth)
  for k, v in pairs(t) do
      if v.width == w and v.height == h and (v.depth == depth or depth == nil) then
          return k
      end
  end
  return -1
end

function change_video_mode(w, h, depth)
  local t = get_video_modes()

  local video_mode = find_resolution(t, w, h, depth)

  if (video_mode ~= -1) then
    setVideoMode = ffi.cast("void(*)(int)", 0x745C70)

    setVideoMode(video_mode - 1)

    ffi.cast("unsigned int*", 0xBA6748 + 0xD4)[0] = video_mode - 1
    ffi.cast("unsigned int*", 0xBA6748 + 0xD8)[0] = video_mode - 1
  end
end

Пример использования:
Лучше всего указывать глубину цвета 32 бита

Lua:
function main()
  change_video_mode(1600, 900, 32)
end

Разрешение сменится на 1600x900x32 после запуска игры(если таковое доступно)

Lua:
function main()
  change_video_mode(1600, 900)
end

Разрешение сменится на 1600x900 с любой глубиной цвета

Описание: сохраняет настройки игры. Полезно в сочетании с функциями выше(если хотите, чтобы после перезахода разрешение осталось)
Lua:
function save_settings()
  ffi.cast("void(__thiscall*)(void*)", 0x0057C660)(ffi.cast("void*", 0xBA6748))
end

Пример использования:

Lua:
function main()
  change_video_mode(1600, 900, 32)
  save_settings()
end