SA:MP Lua Arizona Ловля бочек нефти на дистанции [Наземные/Водные]

Kermi

Активный
Автор темы
239
58
Версия SA-MP
  1. 0.3.7-R3
Автоматичекая ловля бочек нефтевышек [Наземные/Водные] на дистанции


Изначально была идея, как в моём ловце для СТК сделать, но оказалось, что важно находиться не менее нескольких метров от пикапа покупки бочек, в общем этот скрипт позволит вам на дистанции покупать бочки, но за этот скрипт могут забанить, поэтому используйте в то время, когда рядом никого нет и за вами не следит админ, варнинги вроде админам не идут, я около 3 часов катался на наземках, и бана не было.


/oilc - Вкл/выкл
/oilc.b [Клавиша] - Хоткей ловли
/oilc.t
[Задержка в мс] - Задержка телепорта
/oilc.r
- Рисует в мире круги размером 15 метров(дистанция ловли)
Зависимости: vkeys, samp events, moonloader.


Авто-нажатие ALT стало стабильнее, фикс мелких багов.
 

Вложения

  • oilcatcher.lua
    9.4 KB · Просмотры: 5
Последнее редактирование:
  • Нравится
Реакции: MLycoris

MLycoris

На вид оружие массового семяизвержения
Проверенный
2,038
2,285
прикольно, я тоже своего рода читикс написал на автоматизацию этой хуйни. Лучше не setVirtualKeyDown, а отправлять синхру нажатия альт, так он охотнее покупает бочки. Ещё я делал у себя автопогрузку, чтоб после покупки он брал этот пикап сзади т/с с бочками и уже ложить можно было на расстоянии. Короче такой автоматизацией можно сэкономить времени раза в 2, рекомендую взяться за это и доделать у себя, потому что идея реально полезная

Вот код, который я так и не доделал, потому что заебали эти нефтевышки, можешь глянуть мб понравится
Lua:
local font = renderCreateFont('TimesNewRoman', 9, 5)
local sampev = require 'lib.samp.events'
local imgui = require 'mimgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8
local new = imgui.new

local buy = {
    id = -1,
    x = 0,
    y = 0,
    z = 0,
}

local put = {
    id = -1,
    x = 0,
    y = 0,
    z = 0,
}

local saved = {
    x = 0,
    y = 0,
    z = 0,
}

local keysData = {
    [1024] = {structElement = 4, size = 2},
    [64] = {structElement = 36, size = 1},
    [128] = {structElement = 36, size = 1},
    [192] = {structElement = 36, size = 1}
}

local goBuy = false
local addPoint = false

local WinState = 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.SetNextWindowSize(imgui.ImVec2(340), imgui.Cond.Always)
    imgui.Begin('##Window', WinState, imgui.WindowFlags.NoResize)
    if isKeyDown(0x02) then
        imgui.GetIO().MouseDrawCursor = 1
    end
    if imgui.Button(u8'Положить в кар') then
        if put.id ~= -1 and put.x ~= 0 then
            local data = samp_create_sync_data("player")
            data.position = {put.x, put.y, put.z}
            data.send()
            sampSendPickedUpPickup(put.id)
            sampAddChatMessage("send fake sync",-1)
        else
            sampAddChatMessage("none put.id", -1)
        end
    end
    if imgui.Button(u8"Купить") then
        if buy.id ~= -1 and buy.x ~= 0 then
            goBuy = true
            local data = samp_create_sync_data("player")
            data.position = {buy.x, buy.y, buy.z}
            data.send()
            sampSendPickedUpPickup(buy.id)
            sampAddChatMessage("send fake sync",-1)
        else
            sampAddChatMessage("none buy.id", -1)
        end
    end
    if imgui.Button(u8"Обновить") then
        for k, v in pairs(getAllPickups()) do
            if doesPickupExist(v.handle) then
                local x,y,z = getCharCoordinates(1)
                local pickID = sampGetPickupSampIdByHandle(v.handle)
                local pickModel = v.model
                local px, py, pz = getPickupCoordinates(v.handle)
                local distance = getDistanceBetweenCoords2d(px,py,x,y)
                if distance < 10 then
                    if pickModel == 1559 then
                        buy = {id = pickID, x = px, y = py, z = pz}
                    elseif pickModel == 19300 then
                        put = {id = pickID, x = px, y = py, z = pz}
                    end
                end
            end
        end
    end
    if buy.x then
        imgui.Text(string.format("BUY COORDS (%s):\nx %.2f / y %.2f / z %.2f", buy.id, buy.x, buy.y, buy.z))
        imgui.NewLine()
    end
    if put.x then
        imgui.Text(string.format("PUT COORDS (%s):\nx %.2f / y %.2f / z %.2f", put.id, put.x, put.y, put.z))
    end
    imgui.End()
end)

function sampev.onShowDialog(id, style, title, button1, button2, text)
    if goBuy and title:find("Покупка бочки") then
        sampSendDialogResponse(id, 1, nil, nil)
        goBuy = false
        return false
    end
end

addEventHandler('onReceivePacket', function (id, bs)
    if id == 220 then
        raknetBitStreamIgnoreBits(bs, 8)
        local cID = raknetBitStreamReadInt8(bs)
        if (cID == 17) then
            raknetBitStreamIgnoreBits(bs, 32)
            local length = raknetBitStreamReadInt16(bs)
            local encoded = raknetBitStreamReadInt8(bs)
            local str = (encoded ~= 0) and raknetBitStreamDecodeString(bs, length + encoded) or raknetBitStreamReadString(bs, length)
            if goBuy and str:find("Купить бочку с нефтью") then
                sendkey(1024)
            end
        end
    end
end)

function sendkey(keyCode)
    local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
    local mem, data = allocateMemory(68), keysData[keyCode]
    if data then
        sampStorePlayerOnfootData(id, mem)
        setStructElement(mem, data.structElement, data.size, keyCode, false)
        sampSendOnfootData(mem)
        setStructElement(mem, data.structElement, data.size, 0, false)
        sampSendOnfootData(mem)
    end
    freeMemory(mem)
end

function main()
    sampAddChatMessage("++",-1)
    sampRegisterChatCommand("mmode", function(arg)
        asd = tonumber(arg)
        sampAddChatMessage(tostring(arg),-1)
    end) -- 1 buy 2 sell 0 off
    while true do wait(0)
        if not sampIsCursorActive() and wasKeyPressed(0x4F) then
            WinState[0] = not WinState[0]
        end
        for k, v in pairs(getAllPickups()) do
            if doesPickupExist(v.handle) then
                local x,y,z = getCharCoordinates(1)
                local pickID = sampGetPickupSampIdByHandle(v.handle)
                local pickModel = v.model
                local px, py, pz = getPickupCoordinates(v.handle)
                local cx, cy = convert3DCoordsToScreen(px,py,pz)
                local distance = getDistanceBetweenCoords2d(px,py,x,y)
                if distance < 10 and pickModel == 1559 and buy.id == -1 then
                    buy = {id = pickID, x = ox, y = oy, z = oz}
                end
            end
        end
        for k, v in pairs(getAllObjects()) do
            if doesObjectExist(v) then
                local objMod = getObjectModel(v)
                local res, ox, oy, oz = getObjectCoordinates(v)
                local cX, cY = convert3DCoordsToScreen(ox, oy, oz)
                local pX, pY, pZ = getCharCoordinates(1)
                local plCX, plCY = convert3DCoordsToScreen(pX, pY, pZ)
                local dist = getDistanceBetweenCoords2d(pX, pY,ox, oy)
                if dist < 10 and (objMod == 19198 or objMod == 1559 or objMod == 19300) then
                    --4072 / 1239
                    if objMod == 1559 and buy.x == 0 then
                        -- buy = {x = ox, y = oy, z = oz}
                    elseif objMod == 19198 and put.x == 0 then
                        -- put = {id = -1, x = ox, y = oy, z = oz}
                    end
                    renderDrawLine(cX, cY, plCX, plCY, objMod == 1239 and 5 or 2, objMod == 19198 and "0xFFFF0000" or objMod == 1239 and "0xFFFF00FF" or objMod == 19300 and "0xFF0000FF" or "0xFF00FF00")
                    -- renderFontDrawText(font, string.format("objMod: %s\nX: %.2f\n Y: %.2f\nDist:%.2f", objMod, objMod == 1559 and buy.x or put.x, objMod == 1559 and buy.y or put.y,dist), cX, cY, 0xFFFFFFFF)
                end
            end
        end
    end
end

function getAllPickups()
    local pu = {}
    pPu = sampGetPickupPoolPtr()
    for i = 0, 4095 do
        local id = readMemory(pPu + 16388 + 4 * i, 4)
        local model = readMemory((i * 20) + 61444 + pPu, 4, false)
        if id ~= -1 then
            table.insert(pu, {handle = sampGetPickupHandleBySampId(i), model = model})
        end
    end
    return pu
end

function sampev.onServerMessage(color, text)

    --[Информация] {ffffff}Вы взяли бочку из транспорта.
    local text = text:gsub('{......}','')
    local pogrMode = text:match("Режим погрузки (.+)%.")
    if pogrMode then
        if pogrMode:find("включен") then
            addPoint = true
        end
    end
    if text:find('Вы успешно купили бочку') or text:find('Вы успешно подобрали бочку') or text:find('Вы успешно продали бочку с .+ литров нефти и получили (%d+) AZ%-Coins') then
        -- if put.id then
        --     local data = samp_create_sync_data("player")
        --     data.position = {put.x, put.y, put.z}
        --     data.send()
        --     sampSendPickedUpPickup(put.id)
        --     sampAddChatMessage("send fake sync",-1)
        -- end
    end
    if text:find('Вы далеко от выбранного транспорта!') then
        -- sampAddChatMessage("слишком далеко, отправляю снова", -1)
        -- local data = samp_create_sync_data("player")
        -- data.position = {put.x, put.y, put.z}
        -- data.send()
        -- sampSendPickedUpPickup(put.id)
    end
    if text:find('Вы успешно загрузили бочку в транспорт.') then
      
    end
end

function sampev.onSendDialogResponse(id,button,list,input)
    if id == 26123 and put.id then
        local data = samp_create_sync_data("player")
        data.position.x = put.x
        data.position.y = put.y
        data.position.z = put.z
        data.send()
        return true
    end
end

function sampev.onCreatePickup(id, model, type, pos)
    if addPoint then
        local chX, chY, chZ = getCharCoordinates(1)
        local dist = getDistanceBetweenCoords2d(chX, chY, pos.x, pos.y)
        sampAddChatMessage(string.format("id: %s, model: %s dist: %.2f putID: %s", id, model, dist, put.id),-1)
        if model == 19300 and dist < 10 and addPoint then
            put = {id = id, x = pos.x, y = pos.y, z = pos.z}
            sampAddChatMessage("добавил ид обьекта ", -1)
        end
        addPoint = false
    end
    -- sampAddChatMessage(tostring(id)..' / '..tostring(model),-1)
end

function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    -- from SAMP.Lua
    local raknet = require 'samp.raknet'
    require 'samp.synchronization'

    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)))
    -- copy player's sync data to the allocated memory
    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
    -- function to send packet
    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
    -- metatable to access sync data and 'send' function
    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
 

Kermi

Активный
Автор темы
239
58
прикольно, я тоже своего рода читикс написал на автоматизацию этой хуйни. Лучше не setVirtualKeyDown, а отправлять синхру нажатия альт, так он охотнее покупает бочки. Ещё я делал у себя автопогрузку, чтоб после покупки он брал этот пикап сзади т/с с бочками и уже ложить можно было на расстоянии. Короче такой автоматизацией можно сэкономить времени раза в 2, рекомендую взяться за это и доделать у себя, потому что идея реально полезная

Вот код, который я так и не доделал, потому что заебали эти нефтевышки, можешь глянуть мб понравится
Lua:
local font = renderCreateFont('TimesNewRoman', 9, 5)
local sampev = require 'lib.samp.events'
local imgui = require 'mimgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8
local new = imgui.new

local buy = {
    id = -1,
    x = 0,
    y = 0,
    z = 0,
}

local put = {
    id = -1,
    x = 0,
    y = 0,
    z = 0,
}

local saved = {
    x = 0,
    y = 0,
    z = 0,
}

local keysData = {
    [1024] = {structElement = 4, size = 2},
    [64] = {structElement = 36, size = 1},
    [128] = {structElement = 36, size = 1},
    [192] = {structElement = 36, size = 1}
}

local goBuy = false
local addPoint = false

local WinState = 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.SetNextWindowSize(imgui.ImVec2(340), imgui.Cond.Always)
    imgui.Begin('##Window', WinState, imgui.WindowFlags.NoResize)
    if isKeyDown(0x02) then
        imgui.GetIO().MouseDrawCursor = 1
    end
    if imgui.Button(u8'Положить в кар') then
        if put.id ~= -1 and put.x ~= 0 then
            local data = samp_create_sync_data("player")
            data.position = {put.x, put.y, put.z}
            data.send()
            sampSendPickedUpPickup(put.id)
            sampAddChatMessage("send fake sync",-1)
        else
            sampAddChatMessage("none put.id", -1)
        end
    end
    if imgui.Button(u8"Купить") then
        if buy.id ~= -1 and buy.x ~= 0 then
            goBuy = true
            local data = samp_create_sync_data("player")
            data.position = {buy.x, buy.y, buy.z}
            data.send()
            sampSendPickedUpPickup(buy.id)
            sampAddChatMessage("send fake sync",-1)
        else
            sampAddChatMessage("none buy.id", -1)
        end
    end
    if imgui.Button(u8"Обновить") then
        for k, v in pairs(getAllPickups()) do
            if doesPickupExist(v.handle) then
                local x,y,z = getCharCoordinates(1)
                local pickID = sampGetPickupSampIdByHandle(v.handle)
                local pickModel = v.model
                local px, py, pz = getPickupCoordinates(v.handle)
                local distance = getDistanceBetweenCoords2d(px,py,x,y)
                if distance < 10 then
                    if pickModel == 1559 then
                        buy = {id = pickID, x = px, y = py, z = pz}
                    elseif pickModel == 19300 then
                        put = {id = pickID, x = px, y = py, z = pz}
                    end
                end
            end
        end
    end
    if buy.x then
        imgui.Text(string.format("BUY COORDS (%s):\nx %.2f / y %.2f / z %.2f", buy.id, buy.x, buy.y, buy.z))
        imgui.NewLine()
    end
    if put.x then
        imgui.Text(string.format("PUT COORDS (%s):\nx %.2f / y %.2f / z %.2f", put.id, put.x, put.y, put.z))
    end
    imgui.End()
end)

function sampev.onShowDialog(id, style, title, button1, button2, text)
    if goBuy and title:find("Покупка бочки") then
        sampSendDialogResponse(id, 1, nil, nil)
        goBuy = false
        return false
    end
end

addEventHandler('onReceivePacket', function (id, bs)
    if id == 220 then
        raknetBitStreamIgnoreBits(bs, 8)
        local cID = raknetBitStreamReadInt8(bs)
        if (cID == 17) then
            raknetBitStreamIgnoreBits(bs, 32)
            local length = raknetBitStreamReadInt16(bs)
            local encoded = raknetBitStreamReadInt8(bs)
            local str = (encoded ~= 0) and raknetBitStreamDecodeString(bs, length + encoded) or raknetBitStreamReadString(bs, length)
            if goBuy and str:find("Купить бочку с нефтью") then
                sendkey(1024)
            end
        end
    end
end)

function sendkey(keyCode)
    local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
    local mem, data = allocateMemory(68), keysData[keyCode]
    if data then
        sampStorePlayerOnfootData(id, mem)
        setStructElement(mem, data.structElement, data.size, keyCode, false)
        sampSendOnfootData(mem)
        setStructElement(mem, data.structElement, data.size, 0, false)
        sampSendOnfootData(mem)
    end
    freeMemory(mem)
end

function main()
    sampAddChatMessage("++",-1)
    sampRegisterChatCommand("mmode", function(arg)
        asd = tonumber(arg)
        sampAddChatMessage(tostring(arg),-1)
    end) -- 1 buy 2 sell 0 off
    while true do wait(0)
        if not sampIsCursorActive() and wasKeyPressed(0x4F) then
            WinState[0] = not WinState[0]
        end
        for k, v in pairs(getAllPickups()) do
            if doesPickupExist(v.handle) then
                local x,y,z = getCharCoordinates(1)
                local pickID = sampGetPickupSampIdByHandle(v.handle)
                local pickModel = v.model
                local px, py, pz = getPickupCoordinates(v.handle)
                local cx, cy = convert3DCoordsToScreen(px,py,pz)
                local distance = getDistanceBetweenCoords2d(px,py,x,y)
                if distance < 10 and pickModel == 1559 and buy.id == -1 then
                    buy = {id = pickID, x = ox, y = oy, z = oz}
                end
            end
        end
        for k, v in pairs(getAllObjects()) do
            if doesObjectExist(v) then
                local objMod = getObjectModel(v)
                local res, ox, oy, oz = getObjectCoordinates(v)
                local cX, cY = convert3DCoordsToScreen(ox, oy, oz)
                local pX, pY, pZ = getCharCoordinates(1)
                local plCX, plCY = convert3DCoordsToScreen(pX, pY, pZ)
                local dist = getDistanceBetweenCoords2d(pX, pY,ox, oy)
                if dist < 10 and (objMod == 19198 or objMod == 1559 or objMod == 19300) then
                    --4072 / 1239
                    if objMod == 1559 and buy.x == 0 then
                        -- buy = {x = ox, y = oy, z = oz}
                    elseif objMod == 19198 and put.x == 0 then
                        -- put = {id = -1, x = ox, y = oy, z = oz}
                    end
                    renderDrawLine(cX, cY, plCX, plCY, objMod == 1239 and 5 or 2, objMod == 19198 and "0xFFFF0000" or objMod == 1239 and "0xFFFF00FF" or objMod == 19300 and "0xFF0000FF" or "0xFF00FF00")
                    -- renderFontDrawText(font, string.format("objMod: %s\nX: %.2f\n Y: %.2f\nDist:%.2f", objMod, objMod == 1559 and buy.x or put.x, objMod == 1559 and buy.y or put.y,dist), cX, cY, 0xFFFFFFFF)
                end
            end
        end
    end
end

function getAllPickups()
    local pu = {}
    pPu = sampGetPickupPoolPtr()
    for i = 0, 4095 do
        local id = readMemory(pPu + 16388 + 4 * i, 4)
        local model = readMemory((i * 20) + 61444 + pPu, 4, false)
        if id ~= -1 then
            table.insert(pu, {handle = sampGetPickupHandleBySampId(i), model = model})
        end
    end
    return pu
end

function sampev.onServerMessage(color, text)

    --[Информация] {ffffff}Вы взяли бочку из транспорта.
    local text = text:gsub('{......}','')
    local pogrMode = text:match("Режим погрузки (.+)%.")
    if pogrMode then
        if pogrMode:find("включен") then
            addPoint = true
        end
    end
    if text:find('Вы успешно купили бочку') or text:find('Вы успешно подобрали бочку') or text:find('Вы успешно продали бочку с .+ литров нефти и получили (%d+) AZ%-Coins') then
        -- if put.id then
        --     local data = samp_create_sync_data("player")
        --     data.position = {put.x, put.y, put.z}
        --     data.send()
        --     sampSendPickedUpPickup(put.id)
        --     sampAddChatMessage("send fake sync",-1)
        -- end
    end
    if text:find('Вы далеко от выбранного транспорта!') then
        -- sampAddChatMessage("слишком далеко, отправляю снова", -1)
        -- local data = samp_create_sync_data("player")
        -- data.position = {put.x, put.y, put.z}
        -- data.send()
        -- sampSendPickedUpPickup(put.id)
    end
    if text:find('Вы успешно загрузили бочку в транспорт.') then
     
    end
end

function sampev.onSendDialogResponse(id,button,list,input)
    if id == 26123 and put.id then
        local data = samp_create_sync_data("player")
        data.position.x = put.x
        data.position.y = put.y
        data.position.z = put.z
        data.send()
        return true
    end
end

function sampev.onCreatePickup(id, model, type, pos)
    if addPoint then
        local chX, chY, chZ = getCharCoordinates(1)
        local dist = getDistanceBetweenCoords2d(chX, chY, pos.x, pos.y)
        sampAddChatMessage(string.format("id: %s, model: %s dist: %.2f putID: %s", id, model, dist, put.id),-1)
        if model == 19300 and dist < 10 and addPoint then
            put = {id = id, x = pos.x, y = pos.y, z = pos.z}
            sampAddChatMessage("добавил ид обьекта ", -1)
        end
        addPoint = false
    end
    -- sampAddChatMessage(tostring(id)..' / '..tostring(model),-1)
end

function samp_create_sync_data(sync_type, copy_from_player)
    local ffi = require 'ffi'
    local sampfuncs = require 'sampfuncs'
    -- from SAMP.Lua
    local raknet = require 'samp.raknet'
    require 'samp.synchronization'

    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)))
    -- copy player's sync data to the allocated memory
    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
    -- function to send packet
    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
    -- metatable to access sync data and 'send' function
    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
Идея прикольная, мб возьму что-то, и реализую в том что я сделал, особенно синхру альта. Такой бы скрипт в 2023 реализовать было б круто, так как щас особой борьбы за бочки нет, но место быть имеет даже в реалиях 2026.
 

MLycoris

На вид оружие массового семяизвержения
Проверенный
2,038
2,285
Идея прикольная, мб возьму что-то, и реализую в том что я сделал, особенно синхру альта. Такой бы скрипт в 2023 реализовать было б круто, так как щас особой борьбы за бочки нет, но место быть имеет даже в реалиях 2026.
в 2023 тоже писал такой себе, но там сложнее было тк пикап на диалог с бочками был крайне нестабильный