onCreateObject and onSetObjectMaterial

Revalto

Известный
Автор темы
532
225
Версия MoonLoader
.026-beta
Привет молодые! Нужна помощь. Нужно не дать создаться объекту, если идет применение материала на него.

Накидал максимально глупый и очевидный код, который собственно не работает:
Lua:
function e.onCreateObject(objectId, data)
    local isSetMaterial = false
    e.onSetObjectMaterial = function(mObjectId, mData)
        if objectId == mObjectId then
            isSetMaterial = true
        end
    end
    if isSetMaterial then
        return false
    end
end

Но так как мы понимаем, выполнение кода спешит дальше, не дожидаясь завершения функции. Тогда я задумался о асинхронности, на счет неё я не нарыл информации в lua.

Так же пробовал deleteObject, но словил краш из-за большего количества объектов, да и не удаляет он в каких-то случаях
 
Последнее редактирование модератором:
Решение
Нужно не дать создаться объекту, если идет применение материала на него.
Применение материла может быть и после того как объект уже создан.
Так же пробовал deleteObject, но словил краш из-за большего количества объектов, да и не удаляет он в каких-то случаях
Данная функция принимает хендл объекта, а не самповский идентификатор объекта.

Накидал максимально глупый и очевидный код, который собственно не работает:
В обработчике события создания объекта, ты каждый раз перезаписываешь обработчик события установки материала, и в нем пытаешься изменить переменную взятую лямбда-захватом. А после ты проверяешь что эта переменная изменилась, но она не изменится потому как обработчик того события вызывается как минимум...

#Rin

Известный
Всефорумный модератор
1,214
1,036
Нужно не дать создаться объекту, если идет применение материала на него.
Применение материла может быть и после того как объект уже создан.
Так же пробовал deleteObject, но словил краш из-за большего количества объектов, да и не удаляет он в каких-то случаях
Данная функция принимает хендл объекта, а не самповский идентификатор объекта.

Накидал максимально глупый и очевидный код, который собственно не работает:
В обработчике события создания объекта, ты каждый раз перезаписываешь обработчик события установки материала, и в нем пытаешься изменить переменную взятую лямбда-захватом. А после ты проверяешь что эта переменная изменилась, но она не изменится потому как обработчик того события вызывается как минимум после выхода из текущего обработчика.

Для удаления объекта по самповскому иду объекта, можно воспользоваться следующей функцией:
Lua:
function deleteObjectBySampId(objectId)
    local object = sampGetObjectHandleBySampId(objectId)
    if object then
        deleteObject(object)
    end
end
Но самп скорее всего продолжить считать что объект существует, что может вызвать проблемы.

Так что лучше эмулировать получение сообщения о уничтожении объекта:
Lua:
require "lib.sampfuncs"

function emulRpcDestroyObject(objectId)
    local bs = raknetNewBitStream()
    raknetBitStreamWriteInt16(bs, objectId)
    raknetEmulRpcReceiveBitStream(RPC_SCRDESTROYOBJECT, bs)
    raknetDeleteBitStream(bs)
end

Но производительнее будет сразу удалять объект из пула:
Lua:
local ffi = require "ffi"

function deleteObjectFromSampPool(objectId)
    local sampBaseAddr = sampGetBase()
    local objectPoolDeleteFuncPtr = sampBaseAddr + 0xF3F0 -- Адрес для SAMP 0.3.7 R1
    local objectPoolPtr = sampGetObjectPoolPtr()
    local objectPoolDelete = ffi.cast("int(__thiscall*)(void*, unsigned short)", objectPoolDeleteFuncPtr)
    objectPoolDelete(objectPoolPtr, objectId)
end
Адреса лучше не вычислять каждый раз при вызове функции, поэтому лучше проинициализируй один раз где-нибудь в функции main, после инициализации сампа.

В итоге:
Lua:
local sampev = require "lib.samp.events"

function sampev.onCreateObject(objectId, data)
    if next(data.materials) ~= nil then
        return false
    end
end

function sampev.onSetObjectMaterial(objectId, material)
    -- deleteObjectBySampId(objectId)
    emulRpcDestroyObject(objectId)
    -- deleteObjectFromSampPool(objectId)   
    return false
end
Функцию для удаления выбирай на свой вкус.

P.S. Я ничего не проверял на работоспособность.