local ffi = require('ffi')
--HOOKS
local hook = {hooks = {}}
addEventHandler('onScriptTerminate', function(scr)
if scr == script.this then
for i, hook in ipairs(hook.hooks) do
if hook.status then
hook.stop()
end
end
end
end)
ffi.cdef [[
int VirtualProtect(void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect);
]]
function hook.new(cast, callback, hook_addr, size)
jit.off(callback, true) --off jit compilation | thx FYP
local size = size or 5
local new_hook = {}
local detour_addr = tonumber(ffi.cast('intptr_t', ffi.cast('void*', ffi.cast(cast, callback))))
local void_addr = ffi.cast('void*', hook_addr)
local old_prot = ffi.new('unsigned long[1]')
local org_bytes = ffi.new('uint8_t[?]', size)
ffi.copy(org_bytes, void_addr, size)
local hook_bytes = ffi.new('uint8_t[?]', size, 0x90)
hook_bytes[0] = 0xE9
ffi.cast('uint32_t*', hook_bytes + 1)[0] = detour_addr - hook_addr - 5
new_hook.call = ffi.cast(cast, hook_addr)
new_hook.status = false
local function set_status(bool)
new_hook.status = bool
ffi.C.VirtualProtect(void_addr, size, 0x40, old_prot)
ffi.copy(void_addr, bool and hook_bytes or org_bytes, size)
ffi.C.VirtualProtect(void_addr, size, old_prot[0], old_prot)
end
new_hook.stop = function() set_status(false) end
new_hook.start = function() set_status(true) end
new_hook.start()
table.insert(hook.hooks, new_hook)
return setmetatable(new_hook, {
__call = function(self, ...)
self.stop()
local res = self.call(...)
self.start()
return res
end
})
end
--HOOKS
function main()
--[[ https://github.com/DarkP1xel/SAMP-API/tree/master/src/0.3.7-R1 ]]
--[[ onShowDialog ]]
dialogHook = hook.new('void(__thiscall *)(void *this, int nId, int nType, char *szCaption, char *szText, char *szLeftButton, char *szRightButton, bool bServerside)', dialogHook, getModuleHandle('samp.dll') + 0x6B9C0)
--[[ onDisplayGameText ]]
gameTextHook = hook.new('void(__thiscall *)(void *this, const char* szText, int nTime, int nSize)', gameTextHook, getModuleHandle('samp.dll') + 0x9C2C0)
--[[ onServerMessage ]]
entryHook = hook.new('void(__thiscall *)(void* this, int nType, const char* szText, const char* szPrefix, unsigned long textColor, unsigned long prefixColor)', entryHook, getModuleHandle('samp.dll') + 0x64010)
end
function dialogHook(this, nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside)
sampAddChatMessage(string.format('DialogId: %s', nId), -1)
return dialogHook(this, nId, nType, szCaption, szText, szLeftButton, szRightButton, bServerside)
end
function gameTextHook(this, szText, nTime, iSize)
sampAddChatMessage(string.format('GameText: %s', ffi.string(szText)), -1)
return gameTextHook(this, szText, nTime, iSize)
end
function entryHook(this, nType, szText, szPrefix, textColor, prefixColor)
if (ffi.string(szText) == 'у вас нету зажигалки') then
...
end
return entryHook(this, nType, szText, szPrefix, textColor, prefixColor)
end