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

Samohvaov

Известный
13
5
Привет. У меня проблема с тема, что string.find() и text:find() работают только с английскими строками, а с русскими не работает. Возможно кто-то знает решение этой проблемы? Может надо как-то сменить кодировку?
 

Rice.

Известный
Модератор
1,758
1,714
Привет. У меня проблема с тема, что string.find() и text:find() работают только с английскими строками, а с русскими не работает. Возможно кто-то знает решение этой проблемы? Может надо как-то сменить кодировку?
кодировку меняй на windows-1251
 
  • Нравится
Реакции: Samohvaov

Rice.

Известный
Модератор
1,758
1,714
Посмотреть вложение 154731
немного тупанул про горизонтальную и вертикальную. В общем мне такая нужна.
Вне фрейма:
local font_custom_button = nil
imgui.OnInitialize(function()
    imgui.GetIO().IniFilename = nil
 
    --> Настройки
    local config = imgui.ImFontConfig()
    config.MergeMode = true
    local glyph_ranges = imgui.GetIO().Fonts:GetGlyphRangesCyrillic()
    local iconRanges = imgui.new.ImWchar[3](fa.min_range, fa.max_range, 0)

    --> Стандартный
    imgui.GetIO().Fonts:AddFontFromFileTTF('trebucbd.ttf', 14.0, nil, glyph_ranges)
    icon = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fa-solid-900.ttf', 14.0, config, iconRanges)
 
    --> font_custom_button
    if font_custom_button == nil then
        font_custom_button = imgui.GetIO().Fonts:AddFontFromFileTTF(getFolderPath(0x14) .. '\\trebucbd.ttf', 25.0, nil, glyph_ranges)
        font_custom_button = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fa-solid-900.ttf', 30.0, config, iconRanges)
    end
end)
Во фрейме:
if imgui.custom_button(250, 90, fa.ICON_FA_USER, 'Взаимодействие', {'Удобные', 'Лёгкие'}) then
    print('test')
end
Lua:
function imgui.custom_button(sizeX, sizeY, icon, title, text)
    local dl = imgui.GetWindowDrawList()
    local p = imgui.GetCursorScreenPos()
    local mx, my = getCursorPos()
    local bool = false

    imgui.Dummy(imgui.ImVec2(sizeX, sizeY))

    if mx >= p.x and mx <= p.x + sizeX and my >= p.y and my <= p.y + sizeY then
        dl:AddRectFilled(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + sizeX, p.y + sizeY), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.15, 0.15, 0.15, 1)), imgui.GetStyle().WindowRounding)
    else
        dl:AddRectFilled(imgui.ImVec2(p.x, p.y), imgui.ImVec2(p.x + sizeX, p.y + sizeY), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.1, 0.1, 0.1, 1)), imgui.GetStyle().WindowRounding)
    end

    imgui.PushFont(font_custom_button)
    dl:AddText(imgui.ImVec2(p.x + 10, p.y + 10), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.86, 0.86, 0.86, 1.0)), icon)
    dl:AddText(imgui.ImVec2(p.x + 50, p.y + 6), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.86, 0.86, 0.86, 1.0)), u8(title))
    imgui.PopFont()
    for k, v in pairs(text) do
        dl:AddText(imgui.ImVec2(p.x + 50, p.y + 20 + 12.5 * k), imgui.ColorConvertFloat4ToU32(imgui.ImVec4(0.86, 0.86, 0.86, 0.4)), u8(v))
    end

    if mx >= p.x and mx <= p.x + sizeX and my >= p.y and my <= p.y + sizeY then
        if imgui.IsMouseClicked(0) then
            bool = true
        end
    end
 
    return bool
end
Переводить на imgui желания нету, может быть, найдешь добровольца
Результат:
1656596339500.png
 
  • Нравится
Реакции: Gorskin
D

deleted-user-139653

Гость
Приветствую, помогите пожалуйста, когда я падаю с высоты и получаю урон от сервера, скрипт крашится, что делать?
local ev = require 'lib.samp.events'
local damaglog = {out = {}, inc = {}}
local timetoshow = 0
local lasttime = 1
local weaponz = ""
local weaponz2 = ""

local names = {
[0] = "Fist",
[1] = "Brass Knuckles",
[2] = "Golf Club",
[3] = "Nightstick",
[4] = "Knife",
[5] = "Baseball Bat",
[6] = "Shovel",
[7] = "Pool Cue",
[8] = "Katana",
[9] = "Chainsaw",
[10] = "Purple Dildo",
[11] = "Dildo",
[12] = "Vibrator",
[13] = "Silver Vibrator",
[14] = "Flowers",
[15] = "Cane",
[16] = "Grenade",
[17] = "Tear Gas",
[18] = "Molotov Cocktail",
[22] = "9mm",
[23] = "Silenced 9mm",
[24] = "Desert Eagle",
[25] = "Shotgun",
[26] = "Sawnoff Shotgun",
[27] = "Combat Shotgun",
[28] = "Micro SMG/Uzi",
[29] = "MP5",
[30] = "AK-47",
[31] = "M4",
[32] = "Tec-9",
[33] = "Country Rifle",
[34] = "Sniper Rifle",
[35] = "RPG",
[36] = "HS Rocket",
[37] = "Flamethrower",
[38] = "Minigun",
[39] = "Satchel Charge",
[40] = "Detonator",
[41] = "Spraycan",
[42] = "Fire Extinguisher",
[43] = "Camera",
[44] = "Night Vis Goggles",
[45] = "Thermal Goggles",
[46] = "Parachute" }

function ev.onSendGiveDamage(playerId,damage,weapon)
if playerId ~= 65535 then
timetoshow=lasttime+3
if #damaglog.out > 0 then
ch = false
for k,v in pairs(damaglog.out) do
if v.id == playerId then
weaponz = tostring(names[weapon])
v.damage = v.damage + damage
ch = true
end
end
if not ch then
table.insert(damaglog.out,1,{id = playerId,damage = damage})
if #damaglog.out > 6 then
table.remove(#damaglog.out,6)
end
end
else
table.insert(damaglog.out,1,{id = playerId,damage = damage})
end
end
function ev.onSendTakeDamage(playerId,damage,weapon)
if playerId ~= 65535 then
timetoshow=lasttime+3
if #damaglog.inc > 0 then
ch = false
for k,v in pairs(damaglog.inc) do
if v.id == playerId then
weaponz2 = tostring(names[weapon])
v.damage = v.damage + damage
ch = true
end
end
end
if not ch then
table.insert(damaglog.inc,1,{id = playerId,damage = damage})
if #damaglog.inc > 6 then
table.remove(#damaglog.inc,6)
end
end
else
table.insert(damaglog.inc,1,{id = playerId,damage = damage})
end
end
function main()
while not isSampAvailable() do wait(0) end
font = renderCreateFont("Arial", 15, 8)
while true do wait(0)
health = getCharHealth(playerPed)
if health == 0 then damaglog = {out = {}, inc = {}} end
local posx, posy = convertGameScreenCoordsToWindowScreenCoords(150,400)
local posx2 = convertGameScreenCoordsToWindowScreenCoords(450)
lasttime=os.clock()
if timetoshow > lasttime then
if #damaglog.out > 0 then
for k,v in pairs(damaglog.out) do
renderFontDrawText(font,sampGetPlayerNickname(v.id)..' - '..weaponz..' +'..string.format('%.2f',v.damage), posx,posy-renderGetFontDrawHeight(font)*k,0xff26e01d)
end
end
if #damaglog.inc > 0 then
for k,v in pairs(damaglog.inc) do
renderFontDrawText(font,sampGetPlayerNickname(v.id)..' - '..weaponz2..' -'..string.format('%.2f',v.damage), posx2,posy-renderGetFontDrawHeight(font)*k,0xFF44A6C5)
end
end
else
damaglog = {out = {}, inc = {}}
end
end
end
 

Вложения

  • Damage_Informer.lua
    3.2 KB · Просмотры: 8

RaMero

Известный
444
137
Как сделать так, что бы когда зашёл в чекпоинт, он удалился и потом создался новый? в скрипте всё написано, сделайте так что бы после удаления первого маркера появился второй, после наступления на второй скрипт остановился
p.s: 39 строчка лишняя

1. Три кнопки в диалоге к сожалению никак не сделать, нужно делать листбоксы.

2.

Lua:
require 'lib.moonloader'
local inicfg = require 'inicfg'

local cfg = inicfg.load({
    config = {
        off = false
    }
}, 'script')

function main()
    while not isSampAvailable() do wait(0) end

    if cfg.config.off then
        thisScript():unload()
    end

    if not doesFileExist('moonloader/config/script.ini') then inicfg.save(cfg, 'script.ini') end

    sampRegisterChatCommand('offscript', function()
        cfg.config.off = true
        inicfg.save(cfg, 'script.ini')
        sampAddChatMessage('откисай, скрипт больше не включится', -1)
        thisScript():unload()
    end)

    while true do
        wait(0)
    end
end
Куда это впихнуть нужно в мой скрипт?
 

Вложения

  • Marker.lua
    1.9 KB · Просмотры: 4

Sanchez.

Известный
704
190
Как сделать так, что бы когда зашёл в чекпоинт, он удалился и потом создался новый? в скрипте всё написано, сделайте так что бы после удаления первого маркера появился второй, после наступления на второй скрипт остановился
p.s: 39 строчка лишняя


Куда это впихнуть нужно в мой скрипт?
Lua:
script_name('Checkpoint') -- название скрипта
script_author('FORMYS') -- автор скрипта
script_description('Dialog samp') -- описание скрипта
local inicfg = require 'inicfg'
require "lib.moonloader" -- подключение библиотеки

local cfg = inicfg.load({
    config = {
        off = false
    }
}, 'script')

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end
    
    if cfg.config.off then
        thisScript():unload()
    end

    if not doesFileExist('moonloader/config/script.ini') then inicfg.save(cfg, 'script.ini') end

    sampRegisterChatCommand('offscript', function()
        cfg.config.off = true
        inicfg.save(cfg, 'script.ini')
        sampAddChatMessage('откисай, скрипт больше не включится', -1)
        thisScript():unload()
    end)

    
    sampRegisterChatCommand("start", start_cmd)

    while true do
        wait(0)
    end
end

function start_cmd()
    sampShowDialog(18,"{FF4500}Иваныч", "{FFFFFF}Эй, ты живой? Очнись же, тюфяк. Очухался наконец и думаю у тебя много вопросов,\n{FFFFFF}так что слушай: -  Ты попал под мощное влияние выброса,  судну,  на котором ты плыл п*здец!,\n\n{FFFFFF}Увидев тебя, лежащего у берега я понял что на берегу ты не протянешь и часа,\n{FFFFFF}поэтому притащил тебя в деревню 'Angel Pine', наши врачи тебя здорово облатали.\n\n{FFFFFF}По следам видно что тебя кто-то вытащил,  но вот где этот человек уже не узнаем,\n{FFFFFF}знаю лишь одно, если бы не он, то так бы ты и пожёг на корабле\n\n{FFFFFF}Подойди к Володе,  который стоит у выхода  - он ответит на все интересующие тебя вопросы.\n{FFFFFF}Потом следуй к Сидоровичу,  тебе покажут дорогу.", "Ого!")

    
    setMarker(1, -2099.419922, -2465.347168, 30.625000, 1, 3)

end

function setMarker(type, x, y, z, radius, color)
    deleteCheckpoint(marker)
    removeBlip(checkpoint)
    checkpoint = addBlipForCoord(x, y, z)
    marker = createCheckpoint(type, x, y, z, 1, 1, 1, radius)
    changeBlipColour(checkpoint, color)
    lua_thread.create(function()
    repeat
        wait(0)
        local x1, y1, z1 = getCharCoordinates(PLAYER_PED)
        until getDistanceBetweenCoords3d(x, y, z, x1, y1, z1) < radius or not doesBlipExist(checkpoint)
        deleteCheckpoint(marker)
        removeBlip(checkpoint)
        addOneOffSound(0, 0, 0, 1149)
        setMarker(1, -2181.382324, -2432.114990, 35.523438, 1, 3)

    end)
end
 

Vadimka3636

Известный
55
36
Здрасьте, использую такой код для автоматического включения фар при посадке в авто
Lua:
if isCharInAnyCar(PLAYER_PED) and isCarEngineOn(storeCarCharIsInNoSave(playerPed)) and not isCarLightsOn(storeCarCharIsInNoSave(playerPed)) then
    sampSendChat("/lights")
end
Так вот, когда сажусь в лодку/мавер то кикает за флуд функция, как сделать проверки именно в авто ли, а не в лодке/воздушеном тс
Кикает за флуд наверняка потому что это в цикле. Пока сервер пришлёт клиенту, что фары включились - клиент успеет отправить ему тысячи сообщений. Сделайте ожидание, в этом месте, секунду что-ли. А ещё лучше это ожидание в отдельный поток запихнуть, чтобы весь скрипт не тормозило
 

ARMOR

God has forsaken us
Модератор
5,067
7,436
Но если сажусь в авто, все отлично. Кикает когда сажусь в лодку/мавер, так как на них нету фар.
Нужно сделать проверку именно в тачке ли я, или за другим т/с
Lua:
bool result = isCharInAnyBoat(Ped ped) -- Проверка на то в лодке пед, или нет
bool result = isCharInAnyHeli(Ped ped) -- Проверка на то в вертолете пед, или нет
bool result = isCharInAnyPlane(Ped ped) -- Проверка на то в самолете пед, или нет
bool result = isCharOnAnyBike(Ped ped) -- Проверка на то в велосепеде пед, или нет
 

Vadimka3636

Известный
55
36
Но если сажусь в авто, все отлично. Кикает когда сажусь в лодку/мавер, так как на них нету фар.
Нужно сделать проверку именно в тачке ли я, или за другим т/с
Я так понял, что ischarinanycar делает проверку не на авто, а на любой транспорт. Сделайте исключение на функции, которые в комментарии выше, думаю должно заработать
 

Vadimka3636

Известный
55
36
Сделал так:
Lua:
if isCharInAnyCar(PLAYER_PED) and not isCharInAnyBoat(PLAYER_PED) and not isCharInAnyHeli(PLAYER_PED) and not isCharInAnyPlane(PLAYER_PED) and not isCharOnAnyBike(PLAYER_PED) and isCarEngineOn(storeCarCharIsInNoSave(playerPed)) and not isCarLightsOn(storeCarCharIsInNoSave(playerPed)) then
    sampSendChat("/lights")
end
Вроде работает, не кикает

Теперь у меня следущий вопрос)
Пример:
text = "Просто рандомный текст"
sampAddChatMessage(text,-1)
У меня есть переменная с текстом, как мне получить из неё только 2 первых буквы?
Чтоб в чат вывело только "Пр"
string.sub(text, 1, 2) -- вроде так
 

Mico

Известный
252
50
Как исправить?
Код:
imgui.PushFont(fa_font2)
imgui.Button(fa.ICON_FA_ANGLE_LEFT..' Test')
imgui.PopFont()

Поскольку у меня в скрипте разные размеры иконок, то надо постоянно менять размер, но если в кнопке имеется текст, то текст исчезает. А размер иконки меняется. А мне надо, чтобы текст не пропадал.
 

Muzaffar4ik

Новичок
4
0
Всем привет, недавно у меня появились 2 вопроса, спросите вы когда? В 2 часа ночи. Так вот, как сделать так чтобы при виде текста в чате бот прописал команду? А теперь второй вопрос, как мы знаем если авто дривер подходит ли он для лодок? Искал для лодок авто дривер но не нашел(. Помогите кто может буду очень благодарен!
 

Rice.

Известный
Модератор
1,758
1,714
Как исправить?
Код:
imgui.PushFont(fa_font2)
imgui.Button(fa.ICON_FA_ANGLE_LEFT..' Test')
imgui.PopFont()

Поскольку у меня в скрипте разные размеры иконок, то надо постоянно менять размер, но если в кнопке имеется текст, то текст исчезает. А размер иконки меняется. А мне надо, чтобы текст не пропадал.
Lua:
local fa_font2 = nil
local fa_glyph_ranges = imgui.ImGlyphRanges({ fa.min_range, fa.max_range })
function imgui.BeforeDrawFrame()
    local font_config = imgui.ImFontConfig()
    font_config.MergeMode = true

    if fa_font2 == nil then
        fa_font2 = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fa-solid-900.ttf', 30, font_config, fa_glyph_ranges)
        fa_font2 = imgui.GetIO().Fonts:AddFontFromFileTTF(getFolderPath(0x14) .. '\\trebucbd.ttf', 30, nil, imgui.GetIO().Fonts:GetGlyphRangesCyrillic())
    end
end

Lua:
imgui.PushFont(fa_font2)
imgui.Button(fa.ICON_FA_ANGLE_LEFT..' Test')
imgui.PopFont()

Попробуй.
 

Mico

Известный
252
50
Lua:
local fa_font2 = nil
local fa_glyph_ranges = imgui.ImGlyphRanges({ fa.min_range, fa.max_range })
function imgui.BeforeDrawFrame()
    local font_config = imgui.ImFontConfig()
    font_config.MergeMode = true

    if fa_font2 == nil then
        fa_font2 = imgui.GetIO().Fonts:AddFontFromFileTTF('moonloader/resource/fonts/fa-solid-900.ttf', 30, font_config, fa_glyph_ranges)
        fa_font2 = imgui.GetIO().Fonts:AddFontFromFileTTF(getFolderPath(0x14) .. '\\trebucbd.ttf', 30, nil, imgui.GetIO().Fonts:GetGlyphRangesCyrillic())
    end
end

Lua:
imgui.PushFont(fa_font2)
imgui.Button(fa.ICON_FA_ANGLE_LEFT..' Test')
imgui.PopFont()

Попробуй.
Вместо иконки - знак вопроса.
 

qdIbp

Автор темы
Проверенный
1,438
1,199
Вместо иконки - знак вопроса.
Прошу к ознакомлению