ну вот самолайк залог успеха -> engine.dll | sub_10339EE0, sub_103191F0, sub_1018E1F0, sub_10143640
lua -
lua -
Код:
local ffi = require("ffi")
local bit = require("bit")
ffi.cdef[[
typedef struct {
char pad[0x14];
float cycle;
float weight;
int sequence;
float playback_rate;
char pad2[0x4];
} animation_layer_t;
]]
local g_esp_data = {}
local g_sim_ticks = {}
local g_net_data = {}
local globals_tickinterval = globals.tickinterval
local globals_curtime = globals.curtime
local entity_is_enemy = entity.is_enemy
local entity_get_prop = entity.get_prop
local entity_is_dormant = entity.is_dormant
local entity_is_alive = entity.is_alive
local entity_get_origin = entity.get_origin
local entity_get_local_player = entity.get_local_player
local entity_get_player_resource = entity.get_player_resource
local entity_get_bounding_box = entity.get_bounding_box
local entity_get_player_name = entity.get_player_name
local renderer_text = renderer.text
local renderer_world_to_screen = renderer.world_to_screen
local renderer_line = renderer.line
local table_insert = table.insert
local table_remove = table.remove
local client_trace_line = client.trace_line
local math_floor = math.floor
local math_sqrt = math.sqrt
local math_atan2 = math.atan2
local math_cos = math.cos
local math_sin = math.sin
local math_min = math.min
local math_abs = math.abs
local globals_frametime = globals.frametime
local bit_band = bit.band
local bit_bor = bit.bor
local RECORD_LIFETIME = 1.0
local function time_to_ticks(t)
return math_floor(0.5 + (t / globals_tickinterval()))
end
local function vec_subtract(a, b)
return { a[1] - b[1], a[2] - b[2], a[3] - b[3] }
end
local function vec_add(a, b)
return { a[1] + b[1], a[2] + b[2], a[3] + b[3] }
end
local function vec_length(v)
return math_sqrt(v[1] * v[1] + v[2] * v[2] + v[3] * v[3])
end
local function matrix_to_angles(matrix)
local forward_x = matrix[1]
local forward_y = matrix[5]
local up_z = -matrix[9]
local forward_length = math_sqrt(forward_x * forward_x + forward_y * forward_y)
local yaw, pitch
if forward_length > 0.001 then
yaw = math_atan2(forward_y, forward_x) * 57.29578
pitch = math_atan2(up_z, forward_length) * 57.29578
else
yaw = 0
pitch = math_atan2(-matrix[2], matrix[6]) * 57.29578
end
return { pitch, yaw, 0 }
end
local function interpolate_animation(prev_record, curr_record, t)
local interp_factor = math_min(t / globals_tickinterval(), 1.0)
local anim_layers = {}
for i = 0, 12 do
local prev_layer = prev_record.anim_layers and prev_record.anim_layers[i] or { sequence = 0, cycle = 0, weight = 0, playback_rate = 0 }
local curr_layer = curr_record.anim_layers and curr_record.anim_layers[i] or { sequence = 0, cycle = 0, weight = 0, playback_rate = 0 }
anim_layers[i] = {
sequence = curr_layer.sequence,
cycle = prev_layer.cycle + (curr_layer.cycle - prev_layer.cycle) * interp_factor,
weight = prev_layer.weight + (curr_layer.weight - prev_layer.weight) * interp_factor,
playback_rate = prev_layer.playback_rate + (curr_layer.playback_rate - prev_layer.playback_rate) * interp_factor
}
if curr_layer.weight <= 0 or curr_layer.cycle <= 0 then
anim_layers[i].weight = 0
anim_layers[i].cycle = 0
end
end
local pose_params = {}
for i = 0, 23 do
local prev_param = prev_record.pose_params and prev_record.pose_params[i] or 0
local curr_param = curr_record.pose_params and curr_record.pose_params[i] or 0
pose_params[i] = prev_param + (curr_param - prev_param) * interp_factor
end
return anim_layers, pose_params
end
local function get_entities(enemy_only, alive_only)
enemy_only = enemy_only ~= nil and enemy_only or false
alive_only = alive_only ~= nil and alive_only or true
local result = {}
local me = entity_get_local_player()
local player_resource = entity_get_player_resource()
for player = 1, globals.maxplayers() do
local is_enemy, is_alive = true, true
if enemy_only and not entity_is_enemy(player) then
is_enemy = false
end
if is_enemy then
if alive_only and entity_get_prop(player_resource, 'm_bAlive', player) ~= 1 then
is_alive = false
end
if is_alive then
table_insert(result, player)
end
end
end
return result
end
local get_client_entity = vtable_bind('client.dll', 'VClientEntityList003', 3, 'void*(__thiscall*)(void*, int)')
local function get_anim_overlay(ent, layer)
local anim_layers = ffi.cast('animation_layer_t*', ffi.cast('char*', get_client_entity(ent)) + 0x2980)
return anim_layers[layer]
end
local function extrapolate(ent, origin, velocity, flags, ticks, sim_time, prev_record)
local tickinterval = globals_tickinterval()
local sv_gravity_value = cvar.sv_gravity:get_float() * tickinterval
local sv_jump_impulse_value = cvar.sv_jump_impulse:get_float() * tickinterval
local max_unlag = cvar.sv_maxunlag:get_float()
local p_origin = { origin[1], origin[2], origin[3] }
local prev_origin = p_origin
local gravity = velocity[3] > 0 and -sv_gravity_value or sv_jump_impulse_value
local pose_params = {}
for i = 0, 23 do
pose_params[i] = entity_get_prop(ent, 'm_flPoseParameter', i) or 0
end
local anim_layers = {}
for i = 0, 12 do
local layer = get_anim_overlay(ent, i)
anim_layers[i] = {
sequence = layer.sequence,
cycle = layer.cycle,
weight = layer.weight,
playback_rate = layer.playback_rate
}
end
if prev_record then
anim_layers, pose_params = interpolate_animation(
prev_record,
{ anim_layers = anim_layers, pose_params = pose_params },
sim_time - prev_record.sim_time
)
end
local angles = { entity_get_prop(ent, 'm_angEyeAngles') or 0, 0, 0 }
local matrix = {
math_cos(angles[1] * 0.017453292), 0, -math_sin(angles[1] * 0.017453292),
0, 1, 0,
math_sin(angles[1] * 0.017453292), 0, math_cos(angles[1] * 0.017453292)
}
for i = 1, ticks do
prev_origin = p_origin
local new_velocity = { velocity[1], velocity[2], velocity[3] + gravity }
p_origin = {
p_origin[1] + (new_velocity[1] * tickinterval),
p_origin[2] + (new_velocity[2] * tickinterval),
p_origin[3] + (new_velocity[3] * tickinterval)
}
local fraction = client_trace_line(ent,
prev_origin[1], prev_origin[2], prev_origin[3],
p_origin[1], p_origin[2], p_origin[3]
)
if fraction <= 0.99 then
p_origin = {
prev_origin[1] + (p_origin[1] - prev_origin[1]) * 0.95,
prev_origin[2] + (p_origin[2] - prev_origin[2]) * 0.95,
prev_origin[3] + (p_origin[3] - prev_origin[3]) * 0.95
}
break
end
local time_diff = math_abs(sim_time - (globals_curtime() - i * tickinterval))
if time_diff > max_unlag then
break
end
end
return p_origin, pose_params, anim_layers, matrix_to_angles(matrix)
end
local function is_valid_entity(player)
local sim_time = entity_get_prop(player, 'm_flSimulationTime')
return sim_time and sim_time > 0
end
local function cleanup_records(player)
local sim_records = g_sim_ticks[player]
local net_records = g_net_data[player]
local current_time = globals_curtime()
if sim_records then
if type(sim_records) ~= "table" or sim_records.records == nil then
g_sim_ticks[player] = { records = {}, count = 0 }
sim_records = g_sim_ticks[player]
end
local i = 1
while i <= #sim_records.records do
local record = sim_records.records[i]
if (current_time - record.sim_time) > RECORD_LIFETIME or not is_valid_entity(player) then
table_remove(sim_records.records, i)
sim_records.count = sim_records.count - 1
else
i = i + 1
end
end
end
if net_records then
if type(net_records) ~= "table" or net_records.records == nil then
g_net_data[player] = { records = {}, count = 0 }
net_records = g_net_data[player]
end
local i = 1
while i <= #net_records.records do
local record = net_records.records[i]
if (current_time - record.sim_time) > RECORD_LIFETIME or not is_valid_entity(player) then
table_remove(net_records.records, i)
net_records.count = net_records.count - 1
else
i = i + 1
end
end
end
end
local function check_player_state(player)
local flags = entity_get_prop(player, 'm_fFlags')
local state_flags = 0
if flags then
if bit_band(flags, 0x4000) ~= 0 then
state_flags = bit_bor(state_flags, 0x4000)
end
if bit_band(flags, 0x8000) ~= 0 then
state_flags = bit_bor(state_flags, 0x8000)
end
end
return state_flags
end
local function net_update()
local me = entity_get_local_player()
local players = get_entities(true, true)
for i = 1, #players do
local idx = players[i]
if not is_valid_entity(idx) then
g_sim_ticks[idx] = nil
g_net_data[idx] = nil
g_esp_data[idx] = nil
goto continue
end
cleanup_records(idx)
local player_origin = { entity_get_origin(idx) }
local sim_time = entity_get_prop(idx, 'm_flSimulationTime')
local tick = time_to_ticks(sim_time)
local velocity = { entity_get_prop(idx, 'm_vecVelocity') }
local flags = entity_get_prop(idx, 'm_fFlags')
local state_flags = check_player_state(idx)
local sim_records = g_sim_ticks[idx] or { records = {}, count = 0 }
local net_records = g_net_data[idx] or { records = {}, count = 0 }
table_insert(sim_records.records, {
tick = tick,
origin = player_origin,
velocity = velocity,
sim_time = sim_time,
state_flags = state_flags,
anim_layers = {},
pose_params = {}
})
sim_records.count = sim_records.count + 1
g_sim_ticks[idx] = sim_records
if sim_records.count > 1 then
local prev_record = sim_records.records[#sim_records.records - 1]
local delta = tick - prev_record.tick
if delta < 0 then
local diff_origin = vec_subtract(player_origin, prev_record.origin)
local teleport_distance = vec_length(diff_origin)
local predicted_origin, pose_params, anim_layers, angles = extrapolate(idx, player_origin, velocity, flags, delta - 1, sim_time, prev_record)
table_insert(net_records.records, {
tick = delta - 1,
origin = player_origin,
predicted_origin = predicted_origin,
pose_params = pose_params,
anim_layers = anim_layers,
angles = angles,
tickbase = delta < 0,
lagcomp = teleport_distance > 64,
sim_time = sim_time,
state_flags = state_flags
})
net_records.count = net_records.count + 1
g_net_data[idx] = net_records
if delta < 0 or bit_band(state_flags, 0x8000) ~= 0 then
g_esp_data[idx] = 1
end
end
end
if g_esp_data[idx] == nil then
g_esp_data[idx] = 0
end
::continue::
end
end
local function paint_handler()
local me = entity_get_local_player()
local player_resource = entity_get_player_resource()
if not me or not entity_is_alive(me) then
return
end
local observer_mode = entity_get_prop(me, 'm_iObserverMode')
local active_players = {}
if observer_mode == 0 or observer_mode == 1 or observer_mode == 2 or observer_mode == 6 then
active_players = get_entities(true, true)
elseif observer_mode == 4 or observer_mode == 5 then
local all_players = get_entities(false, true)
local observer_target = entity_get_prop(me, 'm_hObserverTarget')
local observer_target_team = entity_get_prop(observer_target, 'm_iTeamNum')
for _, test_player in ipairs(all_players) do
if observer_target_team ~= entity_get_prop(test_player, 'm_iTeamNum') and test_player ~= me then
table_insert(active_players, test_player)
end
end
end
if #active_players == 0 then
return
end
for idx, net_data in pairs(g_net_data) do
if entity_is_alive(idx) and entity_is_enemy(idx) and net_data ~= nil and net_data.records ~= nil then
local latest_record = net_data.records[#net_data.records]
if not latest_record then
goto continue
end
local predicted_pos = latest_record.predicted_origin
local min = vec_add({ entity_get_prop(idx, 'm_vecMins') }, predicted_pos)
local max = vec_add({ entity_get_prop(idx, 'm_vecMaxs') }, predicted_pos)
local points = {
{min[1], min[2], min[3]}, {min[1], max[2], min[3]},
{max[1], max[2], min[3]}, {max[1], min[2], min[3]},
{min[1], min[2], max[3]}, {min[1], max[2], max[3]},
{max[1], max[2], max[3]}, {max[1], min[2], max[3]}
}
local edges = {
{1, 2}, {2, 3}, {3, 4}, {4, 1},
{5, 6}, {6, 7}, {7, 8}, {8, 5},
{1, 5}, {2, 6}, {3, 7}, {4, 8}
}
local color = latest_record.lagcomp and {47, 117, 221, 255} or {255, 255, 255, 255}
if bit_band(latest_record.state_flags, 0x8000) ~= 0 then
color = {255, 165, 0, 255}
end
for _, edge in ipairs(edges) do
local p1 = { renderer_world_to_screen(points[edge[1]][1], points[edge[1]][2], points[edge[1]][3]) }
local p2 = { renderer_world_to_screen(points[edge[2]][1], points[edge[2]][2], points[edge[2]][3]) }
if p1[1] and p2[1] then
renderer_line(p1[1], p1[2], p2[1], p2[2], color[1], color[2], color[3], color[4])
end
end
local text = {
[0] = '',
[1] = 'LAG COMP BREAKER',
[2] = 'SHIFTING TICKBASE',
[3] = 'STATE FLAGS ACTIVE'
}
local x1, y1, x2, y2, alpha = entity_get_bounding_box(idx)
local palpha = g_esp_data[idx] > 0 and g_esp_data[idx] or alpha / 255
if g_esp_data[idx] > 0 then
g_esp_data[idx] = g_esp_data[idx] - globals_frametime() * 2
g_esp_data[idx] = math.max(0, g_esp_data[idx])
end
local tb = latest_record.tickbase or g_esp_data[idx] > 0
local lc = latest_record.lagcomp
local state = bit_band(latest_record.state_flags, 0x8000) ~= 0
if x1 and alpha > 0 then
local name = entity_get_player_name(idx)
local y_add = name == '' and -8 or 0
local display_text = state and text[3] or (tb and text[2] or (lc and text[1] or text[0]))
renderer_text(x1 + (x2 - x1) / 2, y1 - 18 + y_add, 255, 45, 45, palpha * 255, 'c', 0, display_text)
end
end
::continue::
end
end
client.set_event_callback('net_update_end', net_update)
client.set_event_callback('paint', paint_handler)