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

Naito

Активный
166
36
что именно ты хочешь сделать прозрачным? или полностью отключить отрисовку чата?
Make it a little transparent, something like this code but for the chat::

Code:
local ffi = require("ffi")

function SetRwObjectAlpha(handle, alpha)
    local pedEn = getCharPointer(handle)
    if pedEn ~= 0 then
        ffi.cast("void (__thiscall *)(int, int)", 0x5332C0)(pedEn, alpha)
    end
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    while true do
        wait(0)
        SetRwObjectAlpha(playerPed, 100)
    end
end
 

Winstаl

Известный
1,006
416
Make it a little transparent, something like this code but for the chat::

Code:
local ffi = require("ffi")

function SetRwObjectAlpha(handle, alpha)
    local pedEn = getCharPointer(handle)
    if pedEn ~= 0 then
        ffi.cast("void (__thiscall *)(int, int)", 0x5332C0)(pedEn, alpha)
    end
end

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(100) end

    while true do
        wait(0)
        SetRwObjectAlpha(playerPed, 100)
    end
end
https://www.blast.hk/threads/13380/post-599831
 

kyrtion

Известный
1,358
523
она уже 1251, но всё равно не работает. Возможно это из за дебагера? Подскажите кто как выводит скрипт.
попробуй это:

Убедись что в твоем скрипте не связанно с MoonLoader иначе сообщит ошибку что такой нет функи вроде wait(...), sampSendChat(...)
затем добавить каталог luajit в патч, как примет в силу, то в кмд пишешь luajit test.lua и выполнит работу
 

fsrxvdd

Активный
294
74
подскажите плиз, как сделать так, чтобы при возникновении диалога под айди к примеру 1488, скрипт автоматически выбирал 5-й пункт и нажимал "далее"?
 

kyrtion

Известный
1,358
523
подскажите плиз, как сделать так, чтобы при возникновении диалога под айди к примеру 1488, скрипт автоматически выбирал 5-й пункт и нажимал "далее"?
все просто
Подробнее - sampSendDialogResponse

Lua:
подскажите плиз, как сделать так, чтобы при возникновении диалога под айди к примеру 1488,
скрипт автоматически выбирал 5-й пункт и нажимал "далее"?

local sampev = require 'samp.events'

function sampev.onShowDialog(dialogId, style, title, button1, button2, text)
    if dialogId == 1488 and style == ?? then
        -- sampSendDialogResponse(int dialogId, int button, int listitem, zstring input)
        sampSendDialogResponse(1488, 1, 4, "")
        -- listitem = начиная с 0, если нужно указать пункт 5, то отнимаем на -1
        -- button 1 = Левая кнопка как ОК
        -- button 0 = Правая кнопка как Отмена/Назад
        return false -- не показываем диалог в игре
    end
end
 
  • Нравится
Реакции: fsrxvdd

Fr3sH_HP

Новичок
5
0
Посмотреть вложение 257140
как собрать лицензионные часы (например, водительские права: 124 Hours) и отобразить их в чате? пример:
КОМАНДА: /checklic <имя пользователя> ; информацию возьмите отсюда: https://www.rpg.b-zone.ro/players/general/Username
Отобразите их в чате следующим образом:
Driving: 124 ; Flying: 70; Sailing: 70; ETC
 

chromiusj

модерирую шмодерирую
Модератор
5,996
4,300
Посмотреть вложение 257140
как собрать лицензионные часы (например, водительские права: 124 Hours) и отобразить их в чате? пример:
КОМАНДА: /checklic <имя пользователя> ; информацию возьмите отсюда: https://www.rpg.b-zone.ro/players/general/Username
Отобразите их в чате следующим образом:
Driving: 124 ; Flying: 70; Sailing: 70; ETC
Ну используй это
И регулярками вытягивай че тебе надо
 

llistenok

Известный
89
27
Это дамаг информер, все цвета ников нормальные кроме белых - их рендерит полупрозрачными слабочитаемыми
Может кто-нибудь отредачить, чтобы убрать прозрачность?

Lua:
--******[ Описание Скрипта ]*******
script_authors('Leon4ik')
script_version('1.4')
script_version_number(2)
--******[ Библиотеки ]*******
require ('lib.moonloader')
local sampev = require ('lib.samp.events')
local vkeys = require ('vkeys')
local inicfg = require ('inicfg')
-- Inicfg
local ini = "DamageInformer/settings.ini"
local mainini = inicfg.load(nil, ini)
if mainini == nil then
    main =  {
        main =
        {
            nicks = true,
            takedamage = true,
            givedamage = true,
            TDx = 700,
            TDy = 450,
            GDx = 1100,
            GDy = 450,
            kolokol=true,
            volume=1
        }
    }
        inicfg.save(main, ini)
        mainini = inicfg.load(nil, ini)
end
-- variables
local font = renderCreateFont("Arial Black", 13, 12)
local font2 = renderCreateFont("Libre Sans", 18, 13)
local TID = nil
local GID = nil
local TakeDamage = nil
local GiveDamage = nil
local combo = {}
local Render_y = mainini.main.GDy
local Render_y2 = mainini.main.TDy
local active = false
local shara = nil
local mode, mode2 = false, false

for i=0,1000 do
    table.insert(combo, {0,nil})
end

local Texts = {"Обосран","Выебан","Опущен","Унижен"}

function main()
    while not isSampAvailable() do wait(100) end
    repeat wait(0) until sampIsLocalPlayerSpawned()
    sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}] Author:{42aaff} Leon4ik{FFFFFF}. /dmgi', -1)
    
    sampRegisterChatCommand("dmgi",function()
        sampAddChatMessage("[{1E90FF}DMGInformer{FFFFFF}]:",-1)
        sampAddChatMessage("{1E90FF}/dmgtake{FFFFFF} - включить/выключить полученный урон",-1)
        sampAddChatMessage("{1E90FF}/dmggive{FFFFFF} - включить/выключить наносимый урон",-1)
        sampAddChatMessage("{1E90FF}/dmgnick{FFFFFF} - включить/выключить ники",-1)
        sampAddChatMessage("{1E90FF}/dmgkol{FFFFFF} - включить/выключить колокол",-1)
        sampAddChatMessage("{1E90FF}/dmgkolv{FFFFFF} - Сменить громкость колокола от 0 до 100",-1)
        sampAddChatMessage("{1E90FF}/dmgс 1-2{FFFFFF} - Сменить положение Получаемого[1] или Наносимого[2] урона",-1)
    end)
    sampRegisterChatCommand("dmgс",function(arg)
        if tonumber(arg) == 1 then
            set()
        elseif tonumber(arg) == 2 then
            set2()
        else
            sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}]: Неправильный режим. Нужно 1 или 2.',-1)
        end
    end)
    sampRegisterChatCommand("dmgkolv",function(arg)
        if type(tonumber(arg)) == 'number' then
            if tonumber(arg) > 0 and tonumber(arg) < 101 then
                sampAddChatMessage(mainini.main.takedamage and '[{1E90FF}DMGInformer{FFFFFF}]: Звук сменён с {008000}'..mainini.main.volume ..'{FFFFFF} на {008000}'..arg,-1)
                mainini.main.volume = tonumber(arg)
                inicfg.save(mainini, ini)
            else sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}]: Нужно число больше 0 и не больше 100!',-1) end
        else sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}]: Нужно число!',-1) end
    end)

    sampRegisterChatCommand("dmgtake",function()
        mainini.main.takedamage = not mainini.main.takedamage
        sampAddChatMessage(mainini.main.takedamage and '[{1E90FF}DMGInformer{FFFFFF}]: Полученный урон {008000}включён' or '[{1E90FF}DMGInformer{FFFFFF}]: Полученный урон {ff0000}выключен',-1)
        inicfg.save(mainini, ini)
    end)
        
    sampRegisterChatCommand("dmgnick",function()
        mainini.main.nicks = not mainini.main.nicks
        sampAddChatMessage(mainini.main.nicks and '[{1E90FF}DMGInformer{FFFFFF}]: Ники {008000}включены' or '[{1E90FF}DMGInformer{FFFFFF}]: Ники {ff0000}выключены',-1 )
        inicfg.save(mainini, ini)
    end)
        
    sampRegisterChatCommand("dmggive",function()
        mainini.main.givedamage = not mainini.main.givedamage

        sampAddChatMessage(mainini.main.givedamage and '[{1E90FF}DMGInformer{FFFFFF}]: Нанесёный урон {008000}включён' or '[{1E90FF}DMGInformer{FFFFFF}]: Нанесёный урон {ff0000}выключен',-1)
        inicfg.save(mainini, ini)
    end)
    sampRegisterChatCommand("dmgkol",function()
        mainini.main.kolokol = not mainini.main.kolokol

        sampAddChatMessage(mainini.main.kolokol and '[{1E90FF}DMGInformer{FFFFFF}]: Колокол {008000}включён' or '[{1E90FF}DMGInformer{FFFFFF}]: Колокол {ff0000}выключен',-1)
        inicfg.save(mainini, ini)
    end)

    lua_thread.create(times)
    lua_thread.create(render)
end

function times()
    while true do wait(30)
        Render_y = Render_y - 1
        if Render_y < mainini.main.GDy - 50 then Render_y = mainini.main.GDy  GiveDamage = nil TID = nil end
        Render_y2 = Render_y2 - 1
        if Render_y2 < mainini.main.TDy - 50 then Render_y2 = mainini.main.TDy  TakeDamage = nil GID = nil end
    end
end

function render()
    while true do wait(0)
        if GiveDamage ~= nil and GID ~= nil and not sampIsPlayerPaused(GID) then
            if mainini.main.givedamage then
                renderFontDrawText(font,string.format('{29871f}%0.1f'.."{ff0000}(x"..combo[GID][1]..")",GiveDamage), mainini.main.GDx, Render_y, -1)
            end
            if mainini.main.nicks then
                renderFontDrawText(font2,sampGetPlayerNickname(GID).."["..GID.."]", mainini.main.GDx, mainini.main.GDy+30, sampGetPlayerColor(GID))
            end
        elseif GiveDamage ~= nil and GID ~= nil and  sampIsPlayerPaused(GID) then
            if mainini.main.givedamage then
                renderFontDrawText(font,'{ffff00}AFK', mainini.main.GDx, Render_y, -1)
            end
            if mainini.main.nicks then
                renderFontDrawText(font2,sampGetPlayerNickname(GID).."["..GID.."]", mainini.main.GDx, mainini.main.GDy+30, sampGetPlayerColor(GID))
            end
        end
        
        if TakeDamage ~= nil and sampIsPlayerConnected(TID) and TID ~= nil then
            if mainini.main.takedamage then
                renderFontDrawText(font,string.format('{83020e}%0.1f',TakeDamage), mainini.main.TDx, Render_y2, -1)
            end
            if  mainini.main.nicks and mainini.main.takedamage then
                renderFontDrawText(font2,sampGetPlayerNickname(TID).."["..TID.."]", mainini.main.TDx, mainini.main.TDy+30, sampGetPlayerColor(TID))
            end
        end
        if mainini.main.givedamage and active then
            renderFontDrawText(font,'{83020e}'..shara, mainini.main.GDx, mainini.main.GDy-70, -1)
        end
        if mode then  -- нижняя панель
            local nx, ny = getCursorPos()
            mainini.main.TDx = nx
            mainini.main.TDy = ny
            if isKeyJustPressed(13) then
                showCursor(false, false)
                mode = false
                inicfg.save(mainini, ini)
            end
        end
        if mode2 then  -- нижняя панель
            local nx, ny = getCursorPos()
            mainini.main.GDx = nx
            mainini.main.GDy = ny
            if isKeyJustPressed(13) then
                showCursor(false, false)
                mode2 = false
                inicfg.save(mainini, ini)
            end
        end
        for k,v in ipairs(combo) do
            if combo[k][1] > 0 and combo[k][2] ~= nil and os.time() - combo[k][2] > 5 then combo[k][1] = 0 combo[k][2] = nil end
        end
    end
end

function sampev.onPlayerDeath(id)
    if id == GID then
        lua_thread.create(function()
            shara = Texts[math.random(1,#Texts)]
            active = true
            wait(1000)
            shara = nil
            active = false
        end)
    end
end


function sampev.onSendTakeDamage(playerId, damage, weapon, bodypart)
    TakeDamage = damage
    TID = playerId
    Render_y2 = mainini.main.TDy
end

function sampev.onSendGiveDamage(playerId, damage, weapon, bodypart)
    GiveDamage = damage
    GID = playerId
    combo[GID][1] = combo[GID][1] + 1
    combo[GID][2] = os.time()
    Render_y = mainini.main.GDy
    if mainini.main.kolokol and doesFileExist('moonloader/config/DamageInformer/kolokol.mp3') then
        local audio = loadAudioStream('moonloader/config/DamageInformer/kolokol.mp3')
        setAudioStreamState(audio, 1)
        setAudioStreamVolume(audio, mainini.main.volume)
    end
end

function set() -- перемещение
    sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}]: Нажмите {ffff00}Enter {FFFFFF} чтобы сохранить координаты',-1)
    mode = true
    showCursor(true, true)
end
function set2() -- перемещение
    sampAddChatMessage('[{1E90FF}DMGInformer{FFFFFF}]: Нажмите {ffff00}Enter {FFFFFF} чтобы сохранить координаты',-1)
    mode2 = true
    showCursor(true, true)
end
 

Вложения

  • DamageInformer.lua
    8.4 KB · Просмотры: 3

Орк

Известный
432
370
  • Нравится
Реакции: Naito

Naito

Активный
166
36
Как увеличить скоростной режим автомобиля? Например, буйвол достигает 188 км, и я хочу изменить его на 200 км.
 

tomate kudasai/

Участник
94
18
Кароче, почему то кикает запись маршрутов на раксамп лайт. На обычном сампе, все работает.
Код раксампа:
Lua:
function sampev.onSendPlayerSync()
    if play then return false end
end
function sampev.onSendVehicleSync()
    if play then return false end
end
function sampev.onSendTrailerSync()
    if play then return false end
end
local pack = 0
local sleeping = 50

local message = function(text) return print('[Router-Recorder] '..text) end

function playRoute(name)
    local f = io.open('routes\\'..name..'.rr', 'r')
    if not f then
        return message("Маршрут не найден!")
    end
    local r = f:read('a')
    f:close()
    playroute = json.decode(r)
    play = true
    message('Запустил маршрут "'..name..'" ')
    playcurrsetroute()
end
function bitStream.sendTrailerSynchronization(PACKET)
    local bs = bitStream.new()
    bs:writeUInt8(210)
    bs:writeVector3(PACKET)
    bs:writeUInt16(TrID)
    bs:writeFloat(PACKET.q0)
    bs:writeFloat(PACKET.q1)
    bs:writeFloat(PACKET.q2)
    bs:writeFloat(PACKET.q3)
    bs:writeVector3({x = PACKET.sx, y = PACKET.sy, z = PACKET.sz})
    bs:writeVector3({x = PACKET.sx, y = PACKET.sy, z = PACKET.sz})
    bs:writeVector3({x = 0.0, y = 0.0, z = 0.0}) -- вот тут тупанул, записал маршрут без turnSpeed
    bs:writeVector3({x = PACKET.rx, y = PACKET.ry, z = PACKET.rz})
    bs:writeVector3({x = PACKET.dx, y = PACKET.dy, z = PACKET.dz})
    bs:writeVector3({x = PACKET.spx, y = PACKET.spy, z = PACKET.spz})
    bs:writeUInt32(PACKET.unk)
    bs:sendPacket()
end
function bitStream.sendVehicleSynchronization(PACKET)
    local bs = bitStream.new()
    bs:writeUInt8(200)
    bs:writeUInt16(getBotVehicle())
    bs:writeUInt16(PACKET.lr)
    bs:writeUInt16(PACKET.ud)
    bs:writeUInt16(PACKET.keys)
    bs:writeFloat(PACKET.q0)
    bs:writeFloat(PACKET.q1)
    bs:writeFloat(PACKET.q2)
    bs:writeFloat(PACKET.q3)
    bs:writeVector3(PACKET)
    bs:writeVector3({x = PACKET.sx, y = PACKET.sy, z = PACKET.sz})
    bs:writeFloat(1500)
    bs:writeUInt8(getBotHealth() )
    bs:writeUInt8(getBotArmor() )
    bs:writeUInt8(0)
    bs:writeUInt8(0)
    bs:writeUInt8(0)
    bs:writeUInt16(TrID or 0)
    bs:writeFloat(PACKET.lean)
    bs:writeFloat(0)
    bs:sendPacket()
end
function playcurrsetroute()
    newTask(function ()
       while play do
            pack = pack + 1
            if not playroute[pack] or not play then pack = #playroute goto pepe end
            if playroute[pack].veh_ == 1 and TrID ~= 0 then
                if not playroute[pack] or not play then pack = #playroute goto pepe end
                bitStream.sendVehicleSynchronization(playroute[pack].veh)
                sleeping = int(playroute[pack].veh.timer)
                if not sleeping then sleeping = int(playroute[pack].tr.timer) elseif sleeping < 5 then sleeping = int(playroute[pack].tr.timer) end
                print(sleeping)
                bitStream.sendTrailerSynchronization(playroute[pack].tr)
                setBotPosition(playroute[pack].veh.x, playroute[pack].veh.y, playroute[pack].veh.z)
            end
            if playroute[pack].veh_ == 1 and TrID == 0 then
                if not playroute[pack] or not play then pack = #playroute goto pepe end
                bitStream.sendVehicleSynchronization(playroute[pack].veh)
                setBotPosition(playroute[pack].veh.x, playroute[pack].veh.y, playroute[pack].veh.z)
            end
            ::pepe::
            if pack == #playroute then
                play = false;
                message('Закончил маршрут.')
                playroute = {}
            end
            wait(sleeping)
        end
    end)
end
Код на самп:
Lua:
local message = function (text) return sampAddChatMessage('[{8de33c}Route-Recorder{ffffff}] {1a9ded}'..text, -1); end
require('moonloader')
local sampev = require('samp.events')
local json = require('cjson')
local route_name
local recording = false
local route = {}
local trailer_record = false
local lasttime = os.clock() * 1000
local playroute = {}
local play = false
local int = tonumber
local loop_route
local trailer_Id = 0
function main()
    while not isSampAvailable() do wait(0) end
    message('Загружен! (/rr rec [route name] | /rr trailer_record | /rr play [route name] [if loop route 1 or 0])')
    createDirectory(getWorkingDirectory()..'\\RouteRecorder')
    sampRegisterChatCommand('rr', function (arg)
        if arg == 'trailer_record' then
            trailer_record = not trailer_record
            message('Запись маршрутов с трейлером: '..(trailer_record and '{68ff00}Включена' or "{ff0000}Выключена"))
        elseif arg:match('rec %S+') then
            route_name = arg:match('rec (%S+)')
            message('Чтобы начать запись маршрута {ff0000}"'..route_name..'"{1a9ded} нажмите клавишу {ff0000} Q')
        elseif arg:match('play %S+ %S+') then
            local name, loop = arg:match('play (%S+) (%S+)')
            print(name, loop)
            local f = io.open('moonloader\\RouteRecorder\\'..name..'.rr', 'r')
            if not f then
                return message("Маршрут не найден!")
            end
            loop_route = loop == "1"
            local r = f:read('a')
            f:close()
            playroute = json.decode(r)
            play = true
            message('Запустил маршрут {ff0000}"'..name..'"{1a9ded} Нажмите клавишу {ff0000}Q{1a9ded} чтобы остановить его.')
            playRoute()
        elseif arg:match('trid %d+') then
            trailer_Id = arg:match('trid (%d+)')
            message('Айди трейлера: {ff0000}'..trailer_Id)
        end
    end)
    while true do
        wait(0)
        if route_name then
            if wasKeyPressed(VK_Q) and not sampIsCursorActive() then
                recording = not recording
                if recording then
                    message('Начал записывать маршрут {ff0000}"'..route_name..'"')
                    lasttime = os.clock() * 1000
                    recording = true
                else
                    message('Закончил записывать маршрут! Сохроняю...')
                    local f = io.open('moonloader\\RouteRecorder\\'..route_name..'.rr', 'w')
                    f:write(json.encode(route))
                    f:close()
                    route_name = ''
                    play = false;
                    route = {}
                    playroute = {}
                    trailer_record = false
                    recording = false
                end
            end
        end
        if play then
            if wasKeyPressed(VK_Q) and not sampIsCursorActive() then
                play = false;
                message('Остановил маршрут.')
                route = {}
                playroute = {}
                trailer_record = false
                recording = false
            end
        end
    end
end
function sampev.onSendPlayerSync(data)
    if play then return false end
    if recording then
        route[#route+1] = {
            tr_ = 0,
            pl_ = 1,
            veh_ = 0,
            pl = {
                ud = int(data.upDownKeys),
                keys = int(data.keysData),
                x = int(data.position.x),
                y = int(data.position.y),
                z = int(data. position. z),
                q0 = int(data.quaternion[0]),
                q1 = int(data.quaternion[1]),
                q2 = int(data.quaternion[2]),
                q3 = int(data.quaternion[3]),
                sx = int(data.moveSpeed.x),
                sy = int(data.moveSpeed.y),
                sz = int(data.moveSpeed.z),
                aid = int(data.animation.id),
                timer = int(os.clock() * 1000 - lasttime)
            }
        }
        lasttime = os.clock() * 1000
        printStringNow('~g~[Router-Recorder]~b~~h~ Recording player sync... Recorded: '..#route..' packets.', 1000)
    end
end
function sampev.onSendVehicleSync(data)
    if play then return false end
    if recording then
        if trailer_record then
            route[#route+1] = {
                tr_ = 1,
                pl_ = 0,
                veh_ = 1,
                veh = {
                    lr = int(data.leftRightKeys),
                    ud = int(data.upDownKeys),
                    keys = int(data.keysData),
                    q0 = int(data.quaternion[0]),
                    q1 = int(data.quaternion[1]),
                    q2 = int(data.quaternion[2]),
                    q3 = int(data.quaternion[3]),
                    x = int(data.position.x),
                    y = int(data.position.y),
                    z = int(data.position.z),
                    sx = int(data.moveSpeed.x),
                    sy =int( data.moveSpeed.y),
                    sz = int(data.moveSpeed.z),
                    lean = int(data.bikeLean)
                }
            }
        else
            route[#route+1] = {
                tr_ = 0,
                pl_ = 0,
                veh_ = 1,
                veh = {
                    lr = int(data.leftRightKeys),
                    ud = int(data.upDownKeys),
                    keys = int(data.keysData),
                    q0 = int(data.quaternion[0]),
                    q1 = int(data.quaternion[1]),
                    q2 = int(data.quaternion[2]),
                    q3 = int(data.quaternion[3]),
                    x = int(data.position.x),
                    y = int(data.position.y),
                    z = int(data.position.z),
                    sx = int(data.moveSpeed.x),
                    sy =int( data.moveSpeed.y),
                    sz = int(data.moveSpeed.z),
                    lean = int(data.bikeLean),
                    timer = int(os.clock() * 1000 - lasttime)
                }
            }
            printStringNow('~g~[Router-Recorder]~b~~h~ Recording vehicle sync... Recorded: '..#route..' packets.', 1000)
            lasttime = os.clock() * 1000
        end
    end
end
function sampev.onSendTrailerSync(data)
    if play then return false end
    if recording then
        if route[#route] then
            if route[#route].tr_ then
                route[#route].tr = {
                    x = int(data.position.x),
                    y = int(data.position.y),
                    z = int(data.position.z),
                    q0 = int(data.quaternion[0]),
                    q1 = int(data.quaternion[1]),
                    q2 = int(data.quaternion[2]),
                    q3 = int(data.quaternion[3]),
                    sx = int(data.moveSpeed.x),
                    sy = int(data.moveSpeed.y),
                    sz = int(data.moveSpeed.z),
                    rx = int(data.roll.x),
                    ry = int(data.roll.y),
                    rz = int(data.roll.z),
                    dx = int(data.direction.x),
                    dy = int(data.direction.y),
                    dz = int(data.direction.z),
                    spx =int( data.speed.x),
                    spy =int( data.speed.y),
                    spz =int( data.speed.z),
                    unk =int( data.unk),
                    timer =int( os.clock() * 1000 - lasttime)
                }
                printStringNow('~g~[Router-Recorder]~b~~h~ Recording trailer sync... Recorded: '..#route..' packets.', 1000)
                lasttime = os.clock() * 1000
            end
        end
    end
end
function playRoute()
    lua_thread.create(function ()
        local pack = 0
        local sleeping = 50
        while play do
            wait(sleeping)
            pack = pack + 1
            local q = playroute[pack]
           
            if not q or not play then pack = #playroute goto pepe end
            if q.pl_ == 1 then
                if not q or not play then pack = #playroute goto pepe end
                q = q.pl
                local data = samp_create_sync_data('player')
                data.upDownKeys = q.ud
                data.keysData = q.keys
                data.position.x = q.x
                data.position.y = q.y
                data. position. z = q.z
                data.quaternion[0] = q.q0
                data.quaternion[1] = q.q1
                data.quaternion[2] = q.q2
                data.quaternion[3] = q.q3
                data.moveSpeed.x = q.sx
                data.moveSpeed.y = q.sy
                data.moveSpeed.z = q.sz
                data.animation.id = q.aid
                sleeping = q.timer
                data.send()
                setCharCoordinatesNoOffset(PLAYER_PED, q.x, q.y, q.z)
                setCharQuaternion(PLAYER_PED, q.q1, q.q2, q.q3, q.q0)
                printStringNow('~g~[Router-Recorder]~b~~h~ Playing player sync... Played: '..pack..'/'..#playroute..' packets.', 1000)
            end
            if q.veh_ == 1 and trailer_Id ~= 0 then
                if not q or not play then pack = #playroute goto pepe end
                local old, vehsyncsend, trailersyncsend
                old = q
                q = q.veh
                local data = samp_create_sync_data('vehicle')
                data.leftRightKeys = q.lr
                data.upDownKeys = q.ud
                data.keysData = q.keys
                data.quaternion[0] = q.q0
                data.quaternion[1] = q.q1
                data.quaternion[2] = q.q2
                data.quaternion[3] = q.q3
                data.position.x = q.x
                data.position.y = q.y
                data. position. z = q.z
               
                data.moveSpeed.x = q.sx
                data.moveSpeed.y = q.sy
                data.moveSpeed.z = q.sz
                data.bikeLean = q.lean
                data.vehicleId = select(2, sampGetVehicleIdByCarHandle(storeCarCharIsInNoSave(PLAYER_PED)))
                data.trailerId = int(trailer_Id)
                data.vehicleHealth = 1500
                sleeping = int(old.veh.timer)
                if not sleeping then
                    sleeping = int(old.tr.timer)
                else
                    if sleeping < 10 then
                        sleeping = int(old.tr.timer)
                    end
                end
               
                data.send()
                q = old.tr
               
               
                data = samp_create_sync_data('trailer')
                data.position.x = q.x
                data.position.y = q.y
                data. position. z = q.z
                data.quaternion[0] = q.q0
                data.quaternion[1] = q.q1
                data.quaternion[2] = q.q2
                data.quaternion[3] = q.q3
                data.moveSpeed.x = q.sx
                data.moveSpeed.y = q.sy
                data.moveSpeed.z = q.sz
                data.roll.x = q.rx
                data.roll.y = q.ry
                data.roll.z = q.rz
               
                data.direction.x = q.dz
                data.direction.y = q.dy
                data.direction.z = q.dz
               
                data.speed.x = q.spx
                data.speed.y = q.spy
                data.speed.z = q.spz
                data.unk = q.unk
                data.trailerId = int(trailer_Id)
                print('gg')
               
                data.send()
                setCarCoordinatesNoOffset(storeCarCharIsInNoSave(PLAYER_PED), q.x, q.y, q.z)
                printStringNow('~g~[Router-Recorder]~b~~h~ Playing trailer sync... Played: '..pack..'/'..#playroute..' packets.', 1000)
            end
            if q.veh_ == 1 and q.tr_ == 0 then
                if not q or not play then pack = #playroute goto pepe end
                q = q.veh
                local data = samp_create_sync_data('vehicle')
                data.leftRightKeys = int(q.lr)
                data.upDownKeys = q.ud
                data.keysData = q.keys
                data.quaternion[0] = q.q0
                data.quaternion[1] = q.q1
                data.quaternion[2] = q.q2
                data.quaternion[3] = q.q3
                data.position.x = q.x
                data.position.y = q.y
                data. position. z = q.z
               
                data.moveSpeed.x = q.sx
                data.moveSpeed.y = q.sy
                data.moveSpeed.z = q.sz
                data.bikeLean = q.lean
                sleeping = q.timer
                data.vehicleId = select(2, sampGetVehicleIdByCarHandle(storeCarCharIsInNoSave(PLAYER_PED)))
                data.send()
                setCarCoordinatesNoOffset(storeCarCharIsInNoSave(PLAYER_PED), q.x, q.y, q.z)
                printStringNow('~g~[Router-Recorder]~b~~h~ Playing vehicle sync... Played: '..pack..'/'..#playroute..' packets.', 1000)
            end
            ::pepe::
            if pack == #playroute then
                if loop_route then
                    pack = 0
                else
                    play = false;
                    message('Закончил маршрут.')
                    route = {}
                    playroute = {}
                    trailer_record = false
                    recording = false
                end
            end
        end
    end)
end
function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    local raknet = require 'samp.raknet'
    copy_from_player = copy_from_player or true
    local sync_traits = {
        player = {'PlayerSyncData', raknet.PACKET.PLAYER_SYNC, sampStorePlayerOnfootData},
        vehicle = {'VehicleSyncData', raknet.PACKET.VEHICLE_SYNC, sampStorePlayerIncarData},
        passenger = {'PassengerSyncData', raknet.PACKET.PASSENGER_SYNC, sampStorePlayerPassengerData},
        aim = {'AimSyncData', raknet.PACKET.AIM_SYNC, sampStorePlayerAimData},
        trailer = {'TrailerSyncData', raknet.PACKET.TRAILER_SYNC, sampStorePlayerTrailerData},
        unoccupied = {'UnoccupiedSyncData', raknet.PACKET.UNOCCUPIED_SYNC, nil},
        bullet = {'BulletSyncData', raknet.PACKET.BULLET_SYNC, nil},
        spectator = {'SpectatorSyncData', raknet.PACKET.SPECTATOR_SYNC, nil}
    }
    local sync_info = sync_traits[sync_type]
    local data_type = 'struct ' .. sync_info[1]
    local data = ffi.new(data_type, {})
    local raw_data_ptr = tonumber(ffi.cast('uintptr_t', ffi.new(data_type .. '*', data)))
    if copy_from_player then
        local copy_func = sync_info[3]
        if copy_func then
            local _, player_id
            if copy_from_player == true then
                _, player_id = sampGetPlayerIdByCharHandle(PLAYER_PED)
            else
                player_id = tonumber(copy_from_player)
            end
            copy_func(player_id, raw_data_ptr)
        end
    end
    local func_send = function()
        local bs = raknetNewBitStream()
        raknetBitStreamWriteInt8(bs, sync_info[2])
        raknetBitStreamWriteBuffer(bs, raw_data_ptr, ffi.sizeof(data))
        raknetSendBitStreamEx(bs, sampfuncs.HIGH_PRIORITY, sampfuncs.UNRELIABLE_SEQUENCED, 1)
        raknetDeleteBitStream(bs)
    end
    local mt = {
        __index = function(t, index)
            return data[index]
        end,
        __newindex = function(t, index, value)
            data[index] = value
        end
    }
    return setmetatable({send = func_send}, mt)
end
 
  • Грустно
Реакции: qdIbp