Вопросы по Lua скриптингу

Общая тема для вопросов по разработке скриптов на языке программирования Lua, в частности под MoonLoader.
  • Задавая вопрос, убедитесь, что его нет в списке частых вопросов и что на него ещё не отвечали (воспользуйтесь поиском).
  • Поищите ответ в теме посвященной разработке Lua скриптов в MoonLoader
  • Отвечая, убедитесь, что ваш ответ корректен.
  • Старайтесь как можно точнее выразить мысль, а если проблема связана с кодом, то обязательно прикрепите его к сообщению, используя блок [code=lua]здесь мог бы быть ваш код[/code].
  • Если вопрос связан с MoonLoader-ом первым делом желательно поискать решение на wiki.

Частые вопросы

Как научиться писать скрипты? С чего начать?
Информация - Гайд - Всё о Lua скриптинге для MoonLoader(https://blast.hk/threads/22707/)
Как вывести текст на русском? Вместо русского текста у меня какие-то каракули.
Изменить кодировку файла скрипта на Windows-1251. В Atom: комбинация клавиш Ctrl+Shift+U, в Notepad++: меню Кодировки -> Кодировки -> Кириллица -> Windows-1251.
Как получить транспорт, в котором сидит игрок?
Lua:
local veh = storeCarCharIsInNoSave(PLAYER_PED)
Как получить свой id или id другого игрока?
Lua:
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED) -- получить свой ид
local _, id = sampGetPlayerIdByCharHandle(ped) -- получить ид другого игрока. ped - это хендл персонажа
Как проверить, что строка содержит какой-то текст?
Lua:
if string.find(str, 'текст', 1, true) then
-- строка str содержит "текст"
end
Как эмулировать нажатие игровой клавиши?
Lua:
local game_keys = require 'game.keys' -- где-нибудь в начале скрипта вне функции main

setGameKeyState(game_keys.player.FIREWEAPON, -1) -- будет сэмулировано нажатие клавиши атаки
Все иды клавиш находятся в файле moonloader/lib/game/keys.lua.
Подробнее о функции setGameKeyState здесь: lua - setgamekeystate | BlastHack — DEV_WIKI(https://www.blast.hk/wiki/lua:setgamekeystate)
Как получить id другого игрока, в которого целюсь я?
Lua:
local valid, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- получить хендл персонажа, в которого целится игрок
if valid and doesCharExist(ped) then -- если цель есть и персонаж существует
  local result, id = sampGetPlayerIdByCharHandle(ped) -- получить samp-ид игрока по хендлу персонажа
  if result then -- проверить, прошло ли получение ида успешно
    -- здесь любые действия с полученным идом игрока
  end
end
Как зарегистрировать команду чата SAMP?
Lua:
-- До бесконечного цикла/задержки
sampRegisterChatCommand("mycommand", function (param)
     -- param будет содержать весь текст введенный после команды, чтобы разделить его на аргументы используйте string.match()
    sampAddChatMessage("MyCMD", -1)
end)
Крашит игру при вызове sampSendChat. Как это исправить?
Это происходит из-за бага в SAMPFUNCS, когда производится попытка отправки пакета определенными функциями изнутри события исходящих RPC и пакетов. Исправления для этого бага нет, но есть способ не провоцировать его. Вызов sampSendChat изнутри обработчика исходящих RPC/пакетов нужно обернуть в скриптовый поток с нулевой задержкой:
Lua:
function onSendRpc(id)
  -- крашит:
  -- sampSendChat('Send RPC: ' .. id)

  -- норм:
  lua_thread.create(function()
    wait(0)
    sampSendChat('Send RPC: ' .. id)
  end)
end
 
Последнее редактирование:

chapo

tg/inst: @moujeek
Модератор
9,075
12,037
Можно как то блокировать абсолютно все пакеты от сервера(сообщения из чата(других игроков я тоже имею ввиду))
сообщения это не пакеты, а rpc
Lua:
addEventHandler('onReceiveRpc', function(id) return false end)
addEventHandler('onReceivePacket', function(id) return false end)
 
  • Нравится
Реакции: ARMOR

Gorskin

🖕
Проверенный
1,350
1,201
Попытался увеличить дистанцию LOD текстур, получилось. Но гта крашит когда летаю на самолёте. Стандарт значение 1.2 но с ним лоды рисуются близко. А когда ставлю 2.5 то самый раз. Краш код указывает на функцию PreRender. И всегда краш из-за этой функции. Я понимаю что там лимит на что-то и гта не успевает что-то сделать. Можно ли как-то пофиксить краш? Или как лучше сделать дистанцию лодов чуть больше?
cDr3MPBLyho.jpg
Можно менять значение и просто в db но я использую метод перезаписи.
Переврайт памяти (0xCB9990 - просто свободная память, используется как хранилище):
memory.setfloat(0xCB9990, 2.5, true)
memory.write(0x52C9F7+2, 0xCB9990, 4, true)
 

vobz

Новичок
1
0
Хочу сделать скрипт, чтобы он тепался по точкам (не кладмен), в точках есть свои цвета, как сделать данный скрипт?
Хочу сделать скрипт, чтобы он бегал по точкам, в этих точках есть свои цвета, как сделать данный скрипт?
 

Pashyka

Участник
220
17
Добрый день, такая проблема:
Есть имгуи окно, в котором есть text.Buffer, проблема заключается в том, что когда пишешь текст в поле и если в других скриптах есть бинды например на клавишу P, то когда в поле пишешь букву P срабатывает другой скрипт.

Буду благодарен если поможете, никак в голову не приходит как это поправить
 

moreveal

Известный
Проверенный
928
624
Добрый день, такая проблема:
Есть имгуи окно, в котором есть text.Buffer, проблема заключается в том, что когда пишешь текст в поле и если в других скриптах есть бинды например на клавишу P, то когда в поле пишешь букву P срабатывает другой скрипт.

Буду благодарен если поможете, никак в голову не приходит как это поправить
как вариант, с помощью consumeWindowMessage (использовать внутри этой функции) не отправлять нажатия клавиш другим скриптам при открытой менюшке
 
  • Нравится
Реакции: YarikVL

Pashyka

Участник
220
17
как вариант, с помощью consumeWindowMessage (использовать внутри этой функции) не отправлять нажатия клавиш другим скриптам при открытой менюшке
Как я понял в функции onWindowMessage() сделать проверку на открытое imgui окно, но как я вижу там распространяет ток на lua скрипты, а если скрипт Cleo?
 

YarikVL

Известный
Проверенный
4,740
1,816
когда тпаюсь бью кулаком, как фиксануть?
Lua:
-- while true do
while isPauseMenuActive() do
    if cursorEnabled then
        showCursor(false)
    end
    wait(100)
end
if isKeyDown(VK_MBUTTON) then
    cursorEnabled = not cursorEnabled
    clickWarp()
    showCursor(cursorEnabled)
    while isKeyDown(VK_MBUTTON) do wait(80) end
end
--end
function clickWarp()
    lua_thread.create(function()
        while true do
            if cursorEnabled then
                local mode = sampGetCursorMode()
                if mode == 0 then
                    showCursor(true)
                end
                local sx, sy = getCursorPos()
                local swc, shc = getScreenResolution()
                local color = join_argb(255, 255, 255, 255)
                if sx >= 0 and sy >= 0 and sx < swc and sy < shc then
                    local posX, posY, posZ = convertScreenCoordsToWorld3D(sx, sy, 700.0)
                    local camX, camY, camZ = getActiveCameraCoordinates()
                    local result, colpoint = processLineOfSight(camX, camY, camZ, posX, posY, posZ, true, true, false, true, false, false, false)
                    if result and colpoint.entity ~= 0 then
                        local normal = colpoint.normal
                        local pos = Vector3D(colpoint.pos[1], colpoint.pos[2], colpoint.pos[3]) - (Vector3D(normal[1], normal[2], normal[3]) * 0.1)
                        local zOffset = 300
                        if normal[3] >= 0.5 then zOffset = 1 end
                        local result, colpoint2 = processLineOfSight(pos.x, pos.y, pos.z + zOffset, pos.x, pos.y, pos.z - 0.3, true, true, false, true, false, false, false)
                        if result then
                            pos = Vector3D(colpoint2.pos[1], colpoint2.pos[2], colpoint2.pos[3] + 1)
                            local curX, curY, curZ  = getCharCoordinates(playerPed)
                            local dist              = getDistanceBetweenCoords3d(curX, curY, curZ, pos.x, pos.y, pos.z)
                            local hoffs             = renderGetFontDrawHeight(font)
                            sy = sy - 2
                            sx = sx - 2
                            renderFontDrawText(font, string.format("%0.2fm", dist), sx, sy - hoffs, color)
                            local tpIntoCar = nil
                            if colpoint.entityType == 2 then
                                local car = getVehiclePointerHandle(colpoint.entity)
                                if doesVehicleExist(car) and (not isCharInAnyCar(playerPed) or storeCarCharIsInNoSave(playerPed) ~= car) then
                                    displayVehicleName(sx, sy - hoffs * 2, getNameOfVehicleModel(getCarModel(car)))
                                    if isKeyDown(VK_RBUTTON) then
                                        tpIntoCar = car
                                    end
                                    renderFontDrawText(font2, "Hold right mouse button to teleport into the car", sx, sy - hoffs * 3, color)
                                end
                            end
                            createPointMarker(pos.x, pos.y, pos.z)
                            if isKeyDown(VK_LBUTTON) then
                                if tpIntoCar then
                                    if not jumpIntoCar(tpIntoCar) then
                                        teleportPlayer(pos.x, pos.y, pos.z)
                                        local veh = storeCarCharIsInNoSave(playerPed)
                                        local cordsVeh = {getCarCoordinates(veh)}
                                        setCarCoordinates(veh, cordsVeh[1], cordsVeh[2], cordsVeh[3])
                                        cursorEnabled = false
                                        showCursor(false)
                                        removePointMarker()
                                        break
                                    end
                                else
                                    if isCharInAnyCar(playerPed) then
                                        local norm = Vector3D(colpoint.normal[1], colpoint.normal[2], 0)
                                        local norm2 = Vector3D(colpoint2.normal[1], colpoint2.normal[2], colpoint2.normal[3])
                                        rotateCarAroundUpAxis(storeCarCharIsInNoSave(playerPed), norm2)
                                        pos = pos - norm * 1.8
                                        pos.z = pos.z - 1.1
                                    end
                                    teleportPlayer(pos.x, pos.y, pos.z)
                                    cursorEnabled = false
                                    showCursor(false)
                                    removePointMarker()
                                    break
                                end
                                while isKeyDown(VK_LBUTTON) do wait(0) end
                                cursorEnabled = false
                                showCursor(false)
                                removePointMarker()
                                break
                            end
                        end
                    end
                end
            end
            wait(0)
            removePointMarker()
        end
        cursorEnabled = false
        showCursor(false)
        removePointMarker()
    end)
end
local Matrix3X3 = require 'Matrix3x3'
function rotateCarAroundUpAxis(car, vec)
  local mat = Matrix3X3(getVehicleRotationMatrix(car))
  local rotAxis = Vector3D(mat.up:get())
  vec:normalize()
  rotAxis:normalize()
  local theta = math.acos(rotAxis:dotProduct(vec))
  if theta ~= 0 then
    rotAxis:crossProduct(vec)
    rotAxis:normalize()
    rotAxis:zeroNearZero()
    mat = mat:rotate(rotAxis, -theta)
  end
  setVehicleRotationMatrix(car, mat:get())
end

function readFloatArray(ptr, idx)
  return representIntAsFloat(readMemory(ptr + idx * 4, 4, false))
end

function writeFloatArray(ptr, idx, value)
  writeMemory(ptr + idx * 4, 4, representFloatAsInt(value), false)
end

function getVehicleRotationMatrix(car)
  local entityPtr = getCarPointer(car)
  if entityPtr ~= 0 then
    local mat = readMemory(entityPtr + 0x14, 4, false)
    if mat ~= 0 then
      local rx, ry, rz, fx, fy, fz, ux, uy, uz
      rx = readFloatArray(mat, 0)
      ry = readFloatArray(mat, 1)
      rz = readFloatArray(mat, 2)

      fx = readFloatArray(mat, 4)
      fy = readFloatArray(mat, 5)
      fz = readFloatArray(mat, 6)

      ux = readFloatArray(mat, 8)
      uy = readFloatArray(mat, 9)
      uz = readFloatArray(mat, 10)
      return rx, ry, rz, fx, fy, fz, ux, uy, uz
    end
  end
end

function setVehicleRotationMatrix(car, rx, ry, rz, fx, fy, fz, ux, uy, uz)
  local entityPtr = getCarPointer(car)
  if entityPtr ~= 0 then
    local mat = readMemory(entityPtr + 0x14, 4, false)
    if mat ~= 0 then
      writeFloatArray(mat, 0, rx)
      writeFloatArray(mat, 1, ry)
      writeFloatArray(mat, 2, rz)

      writeFloatArray(mat, 4, fx)
      writeFloatArray(mat, 5, fy)
      writeFloatArray(mat, 6, fz)

      writeFloatArray(mat, 8, ux)
      writeFloatArray(mat, 9, uy)
      writeFloatArray(mat, 10, uz)
    end
  end
end

function displayVehicleName(x, y, gxt)
  x, y = convertWindowScreenCoordsToGameScreenCoords(x, y)
  useRenderCommands(true)
  setTextWrapx(640.0)
  setTextProportional(true)
  setTextJustify(false)
  setTextScale(0.33, 0.8)
  setTextDropshadow(0, 0, 0, 0, 0)
  setTextColour(255, 255, 255, 230)
  setTextEdge(1, 0, 0, 0, 100)
  setTextFont(1)
  displayText(x, y, gxt)
end

function createPointMarker(x, y, z)
  pointMarker = createUser3dMarker(x, y, z + 0.3, 4)
end

function removePointMarker()
  if pointMarker then
    removeUser3dMarker(pointMarker)
    pointMarker = nil
  end
end

function getCarFreeSeat(car)
  if doesCharExist(getDriverOfCar(car)) then
    local maxPassengers = getMaximumNumberOfPassengers(car)
    for i = 0, maxPassengers do
      if isCarPassengerSeatFree(car, i) then
        return i
      end
      i = i+1
    end
    return nil
  else
    return nil
  end
end

function jumpIntoCar(car)
  if not isKeyDown(vkeys.VK_LCONTROL) then
    for i=0,1999 do
        local _, c = sampGetCarHandleBySampVehicleId(i)
        if _ and car == c then
            thread_tp = lua_thread.create(function()
                sampSendEnterVehicle(i,false)
                wait(1000)
                if doesVehicleExist(car) then
                    warpCharIntoCar(playerPed, car)
                    thread_tp = nil
                end
            end)
            break
        end
    end
  else
  local seat = -1
  for i=0, getMaximumNumberOfPassengers(car) do
    if isCarPassengerSeatFree(car, i) then
        seat = i
    end
  end
    if seat == -1 then return false end 
    for i=0,1999 do
        local _, c = sampGetCarHandleBySampVehicleId(i)
        if _ and car == c then
            thread_tp = lua_thread.create(function()
                sampSendEnterVehicle(i,true)
                wait(1000)
                if doesVehicleExist(car) then
                    if seat ~= nil then
                        warpCharIntoCarAsPassenger(playerPed, car, seat) -- passenger seat
                        thread_tp = nil
                    end
                end
            end)
            break
        end
    end
  end
  restoreCameraJumpcut()
  return true
end
function teleportPlayer(x, y, z)
  if isCharInAnyCar(playerPed) then
    setCharCoordinates(playerPed, x, y, z)
  end
  setCharCoordinatesDontResetAnim(playerPed, x, y, z)
end
function setCharCoordinatesDontResetAnim(char, x, y, z)
  if doesCharExist(char) then
    local ptr = getCharPointer(char)
    setEntityCoordinates(ptr, x, y, z)
  end
end
function setEntityCoordinates(entityPtr, x, y, z)
  if entityPtr ~= 0 then
    local matrixPtr = readMemory(entityPtr + 0x14, 4, false)
    if matrixPtr ~= 0 then
      local posPtr = matrixPtr + 0x30
      writeMemory(posPtr + 0, 4, representFloatAsInt(x), false) -- X
      writeMemory(posPtr + 4, 4, representFloatAsInt(y), false) -- Y
      writeMemory(posPtr + 8, 4, representFloatAsInt(z), false) -- Z
    end
  end
end
function showCursor(toggle)
    if toggle then
        sampSetCursorMode(CMODE_LOCKCAM)
    else
        sampToggleCursor(false)
    end
end
Вроде можно через consumeWindowMessage не передавать нажатие мышки в игру ( на wiki посмотри какие и куда аргументы надо поставить https://wiki.blast.hk/ru/moonloader/lua/consumeWindowMessage )
 

YarikVL

Известный
Проверенный
4,740
1,816
хз как сделать чтобы блокало, пробовал так
Lua:
function onWindowMessage(msg, wparam, lparam) -- anti alt+enter
    if cursorEnable and wparam == 1 then consumeWindowMessage(true, false) end
end
но все равно не блокает, нажимаю лкм, cursorEnable = false, с ним и эта штука перестает работать
Lua:
require 'lib.moonloader'
addEventHandler('onWindowMessage', function(msg, key)
    if msg == 0x0100 then
        if cursorEnabled and (key == VK_RBUTTON or key == VK_LBUTTON) then
            print("запрещаю")
            consumeWindowMessage(true, false)
        end
    end
end)
 

Gorskin

🖕
Проверенный
1,350
1,201
Попытался увеличить дистанцию LOD текстур, получилось. Но гта крашит когда летаю на самолёте. Стандарт значение 1.2 но с ним лоды рисуются близко. А когда ставлю 2.5 то самый раз. Краш код указывает на функцию PreRender. И всегда краш из-за этой функции. Я понимаю что там лимит на что-то и гта не успевает что-то сделать. Можно ли как-то пофиксить краш? Или как лучше сделать дистанцию лодов чуть больше?
Можно менять значение и просто в db но я использую метод перезаписи.
Переврайт памяти (0xCB9990 - просто свободная память, используется как хранилище):
memory.setfloat(0xCB9990, 2.5, true)
memory.write(0x52C9F7+2, 0xCB9990, 4, true)
Up
 

whyega52

Eblang головного мозга
Модератор
2,839
2,779
Lua:
local config = {
    twist = new.int(1),
}

imgui.InputFloat("WindowsRoud", config.twist)

Код:
[ML] (error) RakNet Changer: C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:336: bad argument #2 to 'InputFloat' (cannot convert 'int [1]' to 'float *')
stack traceback:
    [C]: in function 'InputFloat'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\raknet.lua:336: in function '_draw'
    C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:107: in function <C:\ÂÀÆÍÎÅ!!!\ega-nrp\moonloader\lib\mimgui\init.lua:91>
[ML] (error) RakNet Changer: Script died due to an error. (2FE9AD34)
 

shibaTaidjy

Известный
447
155
как менять ник при отключении сервера именно чтобы сам скрипт менял
 

whyega52

Eblang головного мозга
Модератор
2,839
2,779
как менять ник при отключении сервера именно чтобы сам скрипт менял
хукаешь входящий пакет о дисконнекте, после чего меняешь ник (можешь чекнуть код реконнектов)

Как сделать так, чтобы при выборе 1 из селектабл все сворачивались(исчезали)?
Lua:
            if #str(config.search) > 0 then
                for i = 1, #OUTCOMING_RPC do
                    local info = getRPC(OUTCOMING_RPC[i])
                    local title = info.name .. " [" .. info.id .. "]"
                    if title:lower():find(str(config.search):lower()) then
                        if imgui.Selectable(info.name .. " [" .. info.id .. "]", send_RPC.selected == i) then
                            send_RPC.selected = i
                            
                        end
                        imgui.SameLine()
                        imgui.TextQuestion("( ? )", u8(OUTCOMING_RPC[i].description))
                    end
                end
            else
                for i = 1, #OUTCOMING_RPC do
                    local info = getRPC(OUTCOMING_RPC[i])
                    if imgui.Selectable(info.name .. " [" .. info.id .. "]", send_RPC.selected == i) then
                        
                    end
                    imgui.SameLine()
                    imgui.TextQuestion("( ? )", u8(OUTCOMING_RPC[i].description))
                end
            end
 
Последнее редактирование:
  • Нравится
Реакции: YarikVL и shibaTaidjy

Sadow

Известный
1,427
592
Как получить айди игрока сидящего именно за определённой машиной? Например 401 (клиентский айди)