Вопросы по 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
 
Последнее редактирование:

Lucifer Melton

Активный
164
57
Бля, всё равно откррывается этот сраный чат
у меня работает :D
Lua:
local memory = require "memory"

function main()
    if not isSampLoaded() and not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    memory.setint8(sampGetBase() + 0x5DAFA, 0, true)
    memory.setint8(sampGetBase() + 0x5DB04, 0, true)
    while true do
        wait(0)
        
    end
end
 
  • Нравится
Реакции: 4el0ve4ik

Mr_Incognito

Активный
331
50
разве? там же в муне выглядит это примерно так:

C++:
auto __stdcall WindowProc(HWND hWnd, unsigned int uiMsg, unsigned int uiOneParam, unsigned int uiTwoParam) -> long {
  
    if (!onWindowMessage(&uiMsg, &uiOneParam, &uiTwoParam))
        return;
  
    return CallWindowProcA(hWnd, uiMsg, uiOneParam, uiTwoParam);
  
}

Бля, жди, специально для тебя все сделаю.
Спасибо)
у меня работает :D
Lua:
local memory = require "memory"

function main()
    if not isSampLoaded() and not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    memory.setint8(sampGetBase() + 0x5DAFA, 0, true)
    memory.setint8(sampGetBase() + 0x5DB04, 0, true)
    while true do
        wait(0)
       
    end
end
Да как так то? На двух разных серваках проверял - открывает чат и всё
 

Carrentine

Потрачен
569
460
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
@4el0ve4ik ты нопишь неправильно, нельзя просто нулем заполнять.
 

Mamory

Участник
34
1
Здравствуйте, можно ли как то сделать что бы перед крашем информация скрипта сохранялась в файл txt? Заранее спасибо
 

Carrentine

Потрачен
569
460
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Бля, всё равно откррывается этот сраный чат
Lua:
local ffi = require("ffi")
local memory = require("memory")

ffi.cdef [[
    int VirtualProtect(void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect);
]]

function main()

    if not isSampAvailable() then return false end
   
    local address = getModuleHandle("SAMP.DLL") + 0x5DB05
    local ptr_address = ffi.cast("void*", address)
    local oldProtection = ffi.new("unsigned long[1]")  
    local byte = ffi.new("uint8_t[?]", 0x01, 0xEB)

    ffi.C.VirtualProtect(ptr_address, 0x01, 0x40, oldProtection)

    ffi.copy(ptr_address, byte, 0x01)

    ffi.C.VirtualProtect(ptr_address, 0x01, oldProtection[0], oldProtection)

end
Чтобы снять 0xEB поменяй на 0x75.
 

Mr_Incognito

Активный
331
50
Lua:
local ffi = require("ffi")
local memory = require("memory")

ffi.cdef [[
    int VirtualProtect(void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect);
]]

function main()

    if not isSampAvailable() then return false end
  
    local address = getModuleHandle("SAMP.DLL") + 0x5DB05
    local ptr_address = ffi.cast("void*", address)
    local oldProtection = ffi.new("unsigned long[1]") 
    local byte = ffi.new("uint8_t[?]", 0x01, 0xEB)

    ffi.C.VirtualProtect(ptr_address, 0x01, 0x40, oldProtection)

    ffi.copy(ptr_address, byte, 0x01)

    ffi.C.VirtualProtect(ptr_address, 0x01, oldProtection[0], oldProtection)

end
Чтобы снять 0xEB поменяй на 0x75.
Всё короче, не буду больше вас мучать, забейте. Мне уже неудобно писать, но у меня опять не работает. Не знаю почему. Я просто скопировал. Попробовал на двух серверах, но нет. Может в сборке что то или как там я хз.
 

Carrentine

Потрачен
569
460
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Всё короче, не буду больше вас мучать, забейте. Мне уже неудобно писать, но у меня опять не работает. Не знаю почему. Я просто скопировал. Попробовал на двух серверах, но нет. Может в сборке что то или как там я хз.
У меня все работает, кинь ка moonloader.log, попробуем помочь тебе.
 

Adam_Rockwell

Активный
143
25
Я вот глянул на стандартную мантру мэйна, и не до конца осмысляю написанное. Разжуйте пожалуйста)

function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end


До того, как самп загрузится, это условие not isSampLoaded() or not isSampfuncsLoaded() будет выполняться, т.е оператор перейдёт к return , что должно завершить код, т.к весь main() выполняется лишь один раз, но код почему-то продолжается...
 

ufdhbi

Известный
Проверенный
1,455
861
Я вот глянул на стандартную мантру мэйна, и не до конца осмысляю написанное. Разжуйте пожалуйста)

function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end


До того, как самп загрузится, это условие not isSampLoaded() or not isSampfuncsLoaded() будет выполняться, т.е оператор перейдёт к return , что должно завершить код, т.к весь main() выполняется лишь один раз, но код почему-то продолжается...
это на случай если что-то случиться и скрипт загрузится, а самп и сф нет
 

sadbones

Известный
375
175
Я вот глянул на стандартную мантру мэйна, и не до конца осмысляю написанное. Разжуйте пожалуйста)

function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end


До того, как самп загрузится, это условие not isSampLoaded() or not isSampfuncsLoaded() будет выполняться, т.е оператор перейдёт к return , что должно завершить код, т.к весь main() выполняется лишь один раз, но код почему-то продолжается...

main() выполняется не один раз, а в цикле
 

ufdhbi

Известный
Проверенный
1,455
861
Знающие, вот смотрите, есть имгуи, заметил такую фишку что некоторые используют imgui.ImBuffer(128), или imgui.ImBuffer(64), а не imgui.ImBuffer(256), вопрос - По-че-му?
размер буффера, чем больше - тем больше туда влезет)
 

Adam_Rockwell

Активный
143
25
Lua:
function sampev.onSendDialogResponse(id, button, listboxId, input)
    if input == 'test'
        return {id, button, listboxId, '1yjmnwHkgrY'}
    else return true end
end
в чём ошибка?