local hook=require("hooks")
local function vtable_bind(module, interface, index, type)
local addr = ffi.cast("void***", utils.find_interface(module, interface)) or error(interface .. " is nil.")
return ffi.cast(ffi.typeof(type), addr[0][index]), addr
end
local function __thiscall(func, this)
return function(...)
return func(this, ...)
end
end
local function vtable_thunk(index, typestring)
local t = ffi.typeof(typestring)
return function(instance, ...)
assert(instance ~= nil)
if instance then
local addr=ffi.cast("void***", instance)
return __thiscall(ffi.cast(t, (addr[0])[index]),addr)
end
end
end
local cheat_refs = {
fast_fire_ref = gui.get_config_item("rage>aimbot>aimbot>double tap"),
anti_exploit = gui.get_config_item("rage>aimbot>aimbot>anti-exploit")
}
local menu_elements = {
enable_ping = gui.add_checkbox("Ping Spike", "Lua>Tab A"),
bind_ping = gui.add_keybind("Lua>Tab A>Ping Spike"),
ping_amount = gui.add_slider("Amount", "Lua>Tab A", 5, 180, 1) -- increase at own risk, anything above this value causes inaccuracy issues.
}
ffi.cdef[[
typedef struct
{
char pad0[0x14]; //0x0000
bool bProcessingMessages; //0x0014
bool bShouldDelete; //0x0015
char pad1[0x2]; //0x0016
int iOutSequenceNr; //0x0018 last send outgoing sequence number
int iInSequenceNr; //0x001C last received incoming sequence number
int iOutSequenceNrAck; //0x0020 last received acknowledge outgoing sequence number
int iOutReliableState; //0x0024 state of outgoing reliable data (0/1) flip flop used for loss detection
int iInReliableState; //0x0028 state of incoming reliable data
int iChokedPackets; //0x002C number of choked packets
char pad2[0x414]; //0x0030
} INetChannel; // Size: 0x0444
]]
local nullptr = ffi.new('void*')
local nativeGetNetChannel = __thiscall(vtable_bind("engine.dll", "VEngineClient014", 78, "INetChannel*(__thiscall*)(void*)"))
local INetChannelPtr=nullptr
local nativeINetMessageGetType=vtable_thunk(7,"int(__thiscall*)(void*)")
local nativeINetChannelGetLatency=vtable_thunk(9,"float(__thiscall*)(void*,int)")
local vecSequences={}
local nLastIncomingSequence=0
local function UpdateIncomingSequences(pNetChannel)
if nLastIncomingSequence==0 then nLastIncomingSequence=pNetChannel.iInSequenceNr end
if pNetChannel.iInSequenceNr > nLastIncomingSequence then
nLastIncomingSequence=pNetChannel.iInSequenceNr
table.insert(vecSequences,1,{pNetChannel.iInReliableState,pNetChannel.iChokedPackets,pNetChannel.iInSequenceNr,global_vars.realtime})
end
if #vecSequences > 128 then
table.remove(vecSequences)
end
end
local function ClearIncomingSequences()
nLastIncomingSequence=0
if #vecSequences~=0 then
vecSequences={}
end
end
function SendDatagramHook(originalFunction)
local originalFunction=originalFunction
local sv_maxunlag = cvar["sv_maxunlag"]
function clamp(min, max, value)
return math.min(math.max(min, value), max)
end
function AddLatencyToNetChannel(pNetChannel,flMaxLatency)
for i,sequence in ipairs(vecSequences) do
if global_vars.realtime-sequence[4]>=flMaxLatency then
pNetChannel.iInReliableState=sequence[1]
pNetChannel.iInSequenceNr=sequence[3]
break
end
end
end
function SendDatagram(this,pDatagram)
local local_player = entities.get_entity(engine.get_local_player())
if not engine.is_in_game() or not local_player:is_valid() or not menu_elements.enable_ping:get_bool() or cheat_refs.anti_exploit:get_bool() or pDatagram~=nullptr then
return originalFunction(this,pDatagram)
end
local iOldInReliableState=this.iInReliableState
local iOldInSequenceNr=this.iInSequenceNr
local flMaxLatency=math.max(0,clamp(0,sv_maxunlag:get_float(),menu_elements.ping_amount:get_int()/1000)-nativeINetChannelGetLatency(this)(0))
AddLatencyToNetChannel(this,flMaxLatency)
local res=originalFunction(this,pDatagram)
this.iInReliableState=iOldInReliableState
this.iInSequenceNr=iOldInSequenceNr
return res
end
return SendDatagram
end
local INetChannel
local initialize=false
function on_setup_move(cmd)
INetChannelPtr=nativeGetNetChannel()
if menu_elements.enable_ping:get_bool() then
UpdateIncomingSequences(INetChannelPtr)
else
ClearIncomingSequences()
end
if initialize then return end
initialize=true
INetChannel=hook.jmp.new("int(__thiscall*)(INetChannel*,void*)",SendDatagramHook,ffi.cast("intptr_t**",INetChannelPtr)[0][46],6,true)
end
function on_frame_stage_notify(stage, pre_original)
if engine.is_in_game() then return end
ClearIncomingSequences()
end
function on_shutdown()
if INetChannel~=nil then INetChannel.stop() end
end
local function handle_visiblity()
if menu_elements.enable_ping:get_bool() then
gui.set_visible("Lua>Tab A>Amount", true)
else
gui.set_visible("Lua>Tab A>Amount", false)
end
end
local screen_width, screen_height = render.get_screen_size()
local y = screen_height / 2
--local function indicator()
-- render.text(render.font_indicator, 10, y + 130 , "PING", render.color(5,150,195,255), render.align_left, render.align_center)
--end
function on_paint()
handle_visiblity()
local local_player = entities.get_entity(engine.get_local_player())
if not engine.is_in_game() or not local_player:is_valid() or not menu_elements.enable_ping:get_bool() then
return
end
--indicator()
end