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

sep

Известный
701
79
как поймать сообщение от игрока или свае
function sampev.onServerMessage(color, text)
if text:match('ку') then -- не обязательно полную строку, можно определенный отрывок
sampAddChatMessage("привет")
end
итд
 

Masayuki

Участник
92
36
Lua:
function sampev.onServerMessage(color, text)
    if text:find('ку') then
        lua_thread.create(function()
            wait(0)
            sampAddChatMessage("привет")
        end)
    end
end
 
  • Грустно
Реакции: sep

sep

Известный
701
79
Lua:
function sampev.onServerMessage(color, text)
    if text:find('ку') then
        lua_thread.create(function()
            wait(0)
            sampAddChatMessage("привет")
        end)
    end
end
оно работает только если сообшение от сервера а не от игрока
если в смс или рацую напишут то работает а если просто игрок то нет
 

Masayuki

Участник
92
36
оно работает только если сообшение от сервера а не от игрока
если в смс или рацую напишут то работает а если просто игрок то нет
Кинь строчку из чатлога и кусочек кода, как ты её ищешь. У меня всё норм просто, на мои и на серверные сообщения реагирует
 

sep

Известный
701
79
[11:42:24] <nik_nik> (148): ку
НЕ РАБОТАЕТ
ПИШУ САМ СЕБЕ СМС РАБОТАЕТ
[11:51:31] <nik_nik> (148): ку
[11:51:39] SMS: ку | Отправитель: nik_nik [т.2000]
[11:51:39] SMS: ку | Получатель: nik_nik [т.2000]
[11:51:39] привет
[11:51:39] привет
тесть function sampev.onServerMessage(color, text) серверное сообшение только работает а обычные сообщение от игроков в чат не пашут

Lua:
require "lib.moonloader"
local sf = require 'sampfuncs'
local encoding = require 'encoding'
local sampev = require 'lib.samp.events'



function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end -- Если сф и самп не знагружены - возращаемся обратно
    while not isSampAvailable() do wait(100) end -- Если самп не доступен - ждем 100 ms

-- место под команды

     while true do
      wait(0)

--место под постоянно выполнающие "скрипты" типо бидерови тд

  
     end
end

--место под  function итд

function sampev.onServerMessage(color, text)
    if text:find('ку') then
        lua_thread.create(function()
            wait(0)
            sampAddChatMessage("привет")
        end)
    end
end

Кинь строчку из чатлога и кусочек кода, как ты её ищешь. У меня всё норм просто, на мои и на серверные сообщения реагирует
что не так ?
 
Последнее редактирование:

вайега52

Налуашил состояние
Модератор
2,982
3,097
[11:42:24] <nik_nik> (148): ку
НЕ РАБОТАЕТ
ПИШУ САМ СЕБЕ СМС РАБОТАЕТ
[11:51:31] <nik_nik> (148): ку
[11:51:39] SMS: ку | Отправитель: nik_nik [т.2000]
[11:51:39] SMS: ку | Получатель: nik_nik [т.2000]
[11:51:39] привет
[11:51:39] привет
тесть function sampev.onServerMessage(color, text) серверное сообшение только работает а обычные сообщение от игроков в чат не пашут

Lua:
require "lib.moonloader"
local sf = require 'sampfuncs'
local encoding = require 'encoding'
local sampev = require 'lib.samp.events'



function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then return end -- Если сф и самп не знагружены - возращаемся обратно
    while not isSampAvailable() do wait(100) end -- Если самп не доступен - ждем 100 ms

-- место под команды

     while true do
      wait(0)

--место под постоянно выполнающие "скрипты" типо бидерови тд

 
     end
end

--место под  function итд

function sampev.onServerMessage(color, text)
    if text:find('ку') then
        lua_thread.create(function()
            wait(0)
            sampAddChatMessage("привет")
        end)
    end
end


что не так ?
Попробуй onChatMessage:

Lua:
function sampev.onChatMessage(playerId, text)
    -- ...
end
 
  • Нравится
Реакции: sep

sep

Известный
701
79
Попробуй onChatMessage:

Lua:
function sampev.onChatMessage(playerId, text)
    -- ...
end
реагирую не на целые слова а на любое часть слова
как сделать чтобы реашировало на целые слова

реагирует хоть на ку хать на кушь и тд
if text:find('ку') or text:find('qq') then
sampSendChat(" привет")
end
 

Cottage

Новичок
18
3
Что не так здесь? Логика правильная, но не работает в игре. Я правильно использую hasCharGotWeapon?


switch weapon:
function main()
    repeat wait(0) until isSampAvailable()
        wait(2000)
        sampAddChatMessage("[Swap]{686868}", 0x686868)
        sampRegisterChatCommand("tube", tube)
        sampRegisterChatCommand("m4", m4)
        while true do
        wait(50)
    end
end

function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
        sampSendChat("/takegun 1")

function m4()
    if hasCharGotWeapon(PLAYER_PED, 25) == true then
        sampSendChat("/place 25")
        sampSendChat("/takegun 3")
    else
        sampSendChat("/takegun 3")
    end
end
 

Andrinall

Известный
704
527
Что не так здесь? Логика правильная, но не работает в игре. Я правильно использую hasCharGotWeapon?


switch weapon:
function main()
    repeat wait(0) until isSampAvailable()
        wait(2000)
        sampAddChatMessage("[Swap]{686868}", 0x686868)
        sampRegisterChatCommand("tube", tube)
        sampRegisterChatCommand("m4", m4)
        while true do
        wait(50)
    end
end

function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
        sampSendChat("/takegun 1")

function m4()
    if hasCharGotWeapon(PLAYER_PED, 25) == true then
        sampSendChat("/place 25")
        sampSendChat("/takegun 3")
    else
        sampSendChat("/takegun 3")
    end
end
Табуляция пиздец.
Закрытие end'ами не везде (из-за этого скрипт и крашит)

Lua:
function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    repeat wait(0) until isSampAvailable()
 
    wait(2000)

    sampAddChatMessage("[Swap]{686868}", 0x686868)
    sampRegisterChatCommand("tube", tube)
    sampRegisterChatCommand("m4", m4)
   
    while true do
        wait(50)
    end
end

function tube()
    if not hasCharGotWeapon(PLAYER_PED, 31) then
        return
    end

    sampSendChat("/place 31")
    sampSendChat("/takegun 1")
end

function m4()
    if not hasCharGotWeapon(PLAYER_PED, 25) then
        sampSendChat("/takegun 3")
        return
    end

    sampSendChat("/place 25")
    sampSendChat("/takegun 3")
end
 

Cottage

Новичок
18
3
Да, я исправил код, закрыв конечные операторы. Но вот новая проблема: отправка двух команд одновременно не работает. Есть идеи, почему?


working:
function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
    end
end

not working:
function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
        wait(50)
        sampSendChat("/takegun 1")
    else
        sampSendChat("/takegun 1")
    end
end
 

Andrinall

Известный
704
527
Да, я исправил код, закрыв конечные операторы. Но вот новая проблема: отправка двух команд одновременно не работает. Есть идеи, почему?


working:
function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
    end
end

not working:
function tube()
    if hasCharGotWeapon(PLAYER_PED, 31) == true then
        sampSendChat("/place 31")
        wait(50)
        sampSendChat("/takegun 1")
    else
        sampSendChat("/takegun 1")
    end
end
Антифлуд от сервера скорее всего. (если без wait кидать команды подряд)
А вот использовать wait вне потока - идея так себе.|
Lua:
local tube_thread = lua_thread.create_suspended(function() -- создаём замороженный поток
    if not hasCharGotWeapon(PLAYER_PED, 31) then
        sampSendChat("/takegun 1")
        return
    end

    sampSendChat("/place 31")
    wait(500)
    sampSendChat("/takegun 1")
end)

function tube()
    if not tube_thread.dead then -- проверяем поток на выполнение (или tube_thread:status() == "running", если это не работает)
        sampAddChatMessage("Не так часто!", -1)
        return
    end
    tube_thread:run() -- выполнение потока
end
 

Июнь

Новичок
11
15
Как в mimgui получить возможный размер окна по содержимому?
Есть такой флаг - imgui.WindowFlags.AlwaysAutoResize - он подгоняет размеры окна под его содержимое.
Есть ли способ получить размер, который выдал бы imgui.WindowFlags.AlwaysAutoResize, или другой способ, способный подгонять окно по содержимому?

На примере кода ниже нужен способ, который получил бы размер, не расширяя окно.
К примеру, когда мы откроем вкладку (она по содержанию по ширине явно больше, так как там "Сейчас открыта вторая вкладка! ..............."), но размеры окна остались от предыдущей вкладки, так как у нас не встроен флаг/способ, который расширял бы окно автоматически.

И нужно получить высоту/ширину, которую установил бы autoresize. Нужен именно способ, который определяет размер по содержимому.
Считать (calc'ать) каждый текст вручную - такое решение мне не подойдет, и это только в этом случае дело в тексте; в других это могут быть кнопки, вкладки и т. д.

Интересует решение, если таковое есть, с минималистичным кодом (желательно парой строк :) ).
Прибегал к GetContentRegion, но у меня или лыжи не едут, или он измеряет только видимую область.
Вполне возможно, я делал что-то не так. Мб можно как то с помощью effil?
HELP!!


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

local WinState = imgui.new.bool()

imgui.OnFrame(function() return WinState[0] end, function(player)
    imgui.SetNextWindowPos(imgui.ImVec2(500, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
    imgui.Begin(u8'Пример', WinState)
   
    if imgui.BeginTabBar('Tabs') then
        if imgui.BeginTabItem(u8'Первая') then
            imgui.Text(u8'Сейчас открыта первая вкладка')
            imgui.EndTabItem()
        end
        if imgui.BeginTabItem(u8'Вторая') then
            imgui.Text(u8'Сейчас открыта вторая вкладка! ............................................................. ')
            if imgui.Button('Test') then
                sampAddChatMessage('Вы нажали кнопку во второй вкладке',-1)
            end
            imgui.EndTabItem()
        end
        imgui.EndTabBar()
    end
    imgui.End()
end)

function main()
    sampRegisterChatCommand('cmd', function() WinState[0] = not WinState[0] end)
    wait(-1)
end
UP