- Статус
- Оффлайн
- Регистрация
- 13 Май 2022
- Сообщения
- 166
- Реакции
- 33
Lua:
local ffi = require("ffi")
local bit = require("bit")
local entity = entity
local globals = globals
ffi.cdef[[
typedef uintptr_t (__thiscall* get_client_entity_t)(void*, int);
]]
local entity_list_pointer = ffi.cast("void***", client.create_interface("client.dll", "VClientEntityList003"))
local get_client_entity_fn = ffi.cast("get_client_entity_t", entity_list_pointer[0][3])
local get_entity_address = function(entity)
entity = type(entity) == "number" and entity or entity:get_index()
return get_client_entity_fn(entity_list_pointer, entity)
end
local function get_vfunc(ptr, index)
if not ptr or ptr == 0 then
return nil
end
local vtable = ffi.cast("void***", ptr)[0]
if not vtable then
return nil
end
return ffi.cast("void*", vtable[index])
end
local function get_weapon_spread(weapon_ptr)
if not weapon_ptr or weapon_ptr == 0 then
return 0
end
local vfunc = get_vfunc(weapon_ptr, 453) -- vfunc idx
if not vfunc then
return 0
end
local get_spread_func = ffi.cast("float(__thiscall*)(void*)", vfunc)
if not get_spread_func then
return 0
end
return get_spread_func(weapon_ptr)
end
local function get_weapon_inaccuracy(weapon_ptr)
if not weapon_ptr or weapon_ptr == 0 then
return 0
end
local vfunc = get_vfunc(weapon_ptr, 483) -- vfunc idx
if not vfunc then
return 0
end
local get_inaccuracy_func = ffi.cast("float(__thiscall*)(void*)", vfunc)
if not get_inaccuracy_func then
return 0
end
return get_inaccuracy_func(weapon_ptr)
end
local function get_local_weapon_spread_info()
local local_player = entity.get_local_player()
if not local_player then
return 0, 0
end
local weapon = entity.get_player_weapon(local_player)
if not weapon or weapon == -1 then
return 0, 0
end
local weapon_ptr = ffi.cast("void*", get_entity_address(weapon))
if not weapon_ptr or weapon_ptr == 0 then
return 0, 0
end
local spread = get_weapon_spread(weapon_ptr)
local inaccuracy = get_weapon_inaccuracy(weapon_ptr)
return spread, inaccuracy
end
local weapon_virtuals = {}
local function setup_weapon_virtuals(weapon_ptr)
if not weapon_ptr or weapon_ptr == 0 then
return false
end
if weapon_virtuals[weapon_ptr] then
return true
end
local vtable = ffi.cast("void***", weapon_ptr)[0]
if not vtable then
return false
end
weapon_virtuals[weapon_ptr] = {
get_spread = ffi.cast("float(__thiscall*)(void*)", vtable[453]),
get_inaccuracy = ffi.cast("float(__thiscall*)(void*)", vtable[483])
}
return true
end
local function get_weapon_info_optimized()
local local_player = entity.get_local_player()
if not local_player then
return 0, 0
end
local weapon = entity.get_player_weapon(local_player)
if not weapon or weapon == -1 then
return 0, 0
end
local weapon_ptr = ffi.cast("void*", entity.get_address(weapon))
if not weapon_ptr or weapon_ptr == 0 then
return 0, 0
end
if not setup_weapon_virtuals(weapon_ptr) then
return 0, 0
end
local virtuals = weapon_virtuals[weapon_ptr]
local spread = 0
local inaccuracy = 0
if virtuals.get_spread then
spread = virtuals.get_spread(weapon_ptr)
end
if virtuals.get_inaccuracy then
inaccuracy = virtuals.get_inaccuracy(weapon_ptr)
end
return spread, inaccuracy
end
local last_weapon = nil
client.set_event_callback("run_command", function()
local local_player = entity.get_local_player()
if not local_player then
return
end
local weapon = entity.get_player_weapon(local_player)
if weapon and weapon ~= last_weapon then
if last_weapon and last_weapon ~= -1 then
local old_ptr = ffi.cast("void*", get_entity_address(last_weapon))
if old_ptr and old_ptr ~= 0 then
weapon_virtuals[old_ptr] = nil
end
end
last_weapon = weapon
end
end)
return {
get_weapon_spread = get_local_weapon_spread_info,
get_weapon_info = get_weapon_info_optimized,
get_spread_and_inaccuracy = get_local_weapon_spread_info
}
usage:
local weapon_spread = require("weaponspread")
local spread, inaccuracy = weapon_spread.get_spread_and_inaccuracy()