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

astynk

Известный
Проверенный
741
533
И что делать с динамическими данными?

Нет, нашел ошибку, я считал правильно и потом в биты переводил, но Float посчитал, как 4 бита, а не байта.
Я поправил оффсет, но толку мало :cautious:
Код:
ID_ONFOOT_SYNC - ID: 207
Parameters: UINT8 Packet_ID, UINT16 lrKey, UINT16 udKey, UINT16 keys, float X,
float Y, float Z, float quat_w, float quat_x, float quat_y, float quat_z,
UINT8 health, UINT8 armour, 2_BITS additional_key, 6_BITS weapon_id, UINT8 special_action,
float velocity_x, float velocity_y, float velocity_z, float surfing_offsets_x,
float surfing_offsets_y, float surfing_offsets_z, UINT16 surfing_vehicle_id, INT16 animation_id,
INT16 animation_flags
Код:
Lua:
raknetBitStreamSetReadOffset(bs, 280) --[[8+16+16+16+32+32+32+32+32+32+32 - следующий идет Uint8 Health.
                                                                        32 - Float (4 байта). Считал сразу в битах]]
local health = raknetBitStreamReadInt8(bs)
sampAddChatMessage(health, -1)
В raknetBitStreamSetReadOffset на вики указано, что оффсет в битах.
Что не так сделано? Выше человек упоминал про динамические данные в Onfoot синхре. Может из-за них? Что с ними делать?
В данном коде выдает рандомные числа до 300, с ХП ничего общего не нашел
Оффсет в байтах нужен, а ты указываешь в битах.
 

Musaigen

shitposter
Проверенный
1,654
1,471
Оффсет в байтах нужен, а ты указываешь в битах.
В битах, а не в байтах.

И что делать с динамическими данными?
Динамические данные только в входящих пакетах, а именно в синхронизации игрока(stOnFootData) и в синхре машины(stInCarData)
 
Последнее редактирование:

astynk

Известный
Проверенный
741
533
как FFFFFF перевести в RGBA и наоборот?
Там ARGB получится, потому что прозрачность первой указывается.
Lua:
    local explode_argb = function(argb)
        local a = bit.band(bit.rshift(argb, 24), 0xFF)
        local r = bit.band(bit.rshift(argb, 16), 0xFF)
        local g = bit.band(bit.rshift(argb, 8), 0xFF)
        local b = bit.band(argb, 0xFF)
        return a, r, g, b
    end

Lua:
function join_argb(a, r, g, b)
  local argb = b  -- b
  argb = bit.bor(argb, bit.lshift(g, 8))  -- g
  argb = bit.bor(argb, bit.lshift(r, 16)) -- r
  argb = bit.bor(argb, bit.lshift(a, 24)) -- a
  return argb
end
Запустил у себя, все верно выводит, и реагирует на изменение хп.

Lua:
function onSendPacket(id, bs)
    if id == 207 then
        raknetBitStreamSetReadOffset(bs, 280)
        local hp = raknetBitStreamReadInt8(bs)
        sampAddChatMessage(hp, -1)
    end
end

P.S. про биты просто шок сенсация, всю жизнь думал что там байты
 
Последнее редактирование:

FBenz

Активный
328
40
Lua:
function onSendPacket(id, bs)
    if id == 207 then
        raknetBitStreamSetReadOffset(bs, 280)
        local hp = raknetBitStreamReadInt8(bs)
        sampAddChatMessage(hp, -1)
    end
end

P.S. про биты просто шок сенсация, всю жизнь думал что там байты
Этот код у тебя работает? У меня отсебятину выводит и рандомные числа до 255
СФ и Мун подключены, хм
 

FBenz

Активный
328
40
Заметил, что мои хп отображаются корректно, а чужие - нет. У меня, допустим, хп 72 и у другого игрока 98. Он единственный в зоне стрима и на сервере вообще. В моей синхре хп - 72, а в его - 255
 

Quasper

Известный
835
354
Как сделать больше строк в флудере?
Сколько их не ставлю больше 500 не выдает!
флудер:
function flood()
    lua_thread.create(function()
        while true do wait(0)
            if flooder.v then
                if floodText.v ~= nil and floodTime.v ~= nil then
                    sampSendChat(u8:decode(floodText.v))  
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))  
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))
                    sampSendChat(u8:decode(floodText.v))  
                    wait(floodTime.v * 0)
                end
            end
        end
    end)
end
Юзай циклы
Код:
for i = 0, 500 do
    sampSendChat(u8:decode(floodText.v))
end
профлудит 501 раз
 

FBenz

Активный
328
40
Динамические данные только в входящих пакетах, а именно в синхронизации игрока(stOnFootData) и в синхре машины(stInCarData)
Вот в них и проблема. Я читаю входящие пакеты. И, видимо, мешают динамические данные. Как подобрать нужный оффсет?
Он не может выводить 300, если ты читаешь 8 бит.
Я на глаз прикидывал. Только когда почитал про последовательности битов понял, что это вообще такое)
 

Musaigen

shitposter
Проверенный
1,654
1,471
Вот в них и проблема. Я читаю входящие пакеты. И, видимо, мешают динамические данные. Как подобрать нужный оффсет?

Я на глаз прикидывал. Только когда почитал про последовательности битов понял, что это вообще такое)
Самый простой вариант это читать всю структуру, вот пример снизу, ну или @legend2360 тебе сверху кинул
Lua:
function readQuaternion(bs)
    local readBool, readShort = raknetBitStreamReadBool, raknetBitStreamReadInt16
    local cwNeg, cxNeg, cyNeg, czNeg = readBool(bs), readBool(bs), readBool(bs), readBool(bs)
    local cx, cy, cz = readShort(bs), readShort(bs), readShort(bs)
    local x = cx / 65535
    local y = cy / 65535
    local z = cz / 65535
    if cxNeg then x = -x end
    if cyNeg then y = -y end
    if czNeg then z = -z end
    local diff = 1 - x * x - y * y - z * z
    if diff < 0 then diff = 0 end
    local w = math.sqrt(diff)
    if cwNeg then w = -w end
    return {w, x, y, z}
end

function decompressHealthAndArmor(bs)
    hpAp = raknetBitStreamReadInt8(bs)
    local hp = bit.rshift(hpAp, 4)
    local armor = bit.band(hpAp, 0x0F)
    if hp == 0x0F then hp = 100
    elseif hp ~= 0 then hp = hp * 7
    end
    if armor == 0x0F then armor = 100
    elseif armor ~= 0 then armor = armor * 7
    end
    return hp, armor
end

function onReceivePacket(id, bs)
    if id == 207 then
        raknetBitStreamIgnoreBits(bs, 8)
        local playerId = raknetBitStreamReadInt16(bs)
        local hasLeftRightKeys = raknetBitStreamReadBool(bs)
        if hasLeftRightKeys then
            LeftRightKeys = raknetBitStreamReadInt16(bs)
        end
        local hasupDownKeys = raknetBitStreamReadBool(bs)
        if hasupDownKeys then
            upDownKeys = raknetBitStreamReadInt16(bs)
        end
        local keysData = raknetBitStreamReadInt16(bs)
        local positionX = raknetBitStreamReadFloat(bs)
        local positionY = raknetBitStreamReadFloat(bs)
        local positionZ = raknetBitStreamReadFloat(bs)
        local quat = readQuaternion(bs)
        local hp, armor = decompressHealthAndArmor(bs)
        print(playerId, hp, armor)
    end
end
 
  • Нравится
Реакции: FBenz

tlwsn

Известный
537
85
Там ARGB получится, потому что прозрачность первой указывается.
Lua:
    local explode_argb = function(argb)
        local a = bit.band(bit.rshift(argb, 24), 0xFF)
        local r = bit.band(bit.rshift(argb, 16), 0xFF)
        local g = bit.band(bit.rshift(argb, 8), 0xFF)
        local b = bit.band(argb, 0xFF)
        return a, r, g, b
    end

Lua:
function join_argb(a, r, g, b)
  local argb = b  -- b
  argb = bit.bor(argb, bit.lshift(g, 8))  -- g
  argb = bit.bor(argb, bit.lshift(r, 16)) -- r
  argb = bit.bor(argb, bit.lshift(a, 24)) -- a
  return argb
end
Запустил у себя, все верно выводит, и реагирует на изменение хп.

Lua:
function onSendPacket(id, bs)
    if id == 207 then
        raknetBitStreamSetReadOffset(bs, 280)
        local hp = raknetBitStreamReadInt8(bs)
        sampAddChatMessage(hp, -1)
    end
end

P.S. про биты просто шок сенсация, всю жизнь думал что там байты
как можно строку FFFFFF перевести в hex, 0xFFFFFF
 

FBenz

Активный
328
40
как можно строку FFFFFF перевести в hex, 0xFFFFFF
Lua:
local hhex = tonumber('0x'..'цвет(строка)')
Как вариант.:-p Каждый цвет в hex - это 16-ричное число. И можно работать как с числами.
Но там альфа еще должна быть вроде в HEX'е, потому вместо 0x поставь 0xFF (альфа будет равна 1).
Или в самом цвете впереди добавь FF - альфа = 1

В итоге hhex будет равно числу 0xFF*твой цвет*
 
Последнее редактирование: