LUA скрипт Better lagcomp tracking

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
6 Дек 2021
Сообщения
58
Реакции
3
ну вот самолайк залог успеха -> engine.dll | sub_10339EE0, sub_103191F0, sub_1018E1F0, sub_10143640
lua -
Код:
Expand Collapse Copy
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)
 
useless and public for years
 
[gamesense] .\!ragebot.lua:48: attempt to perform arithmetic on a nil value
 
Назад
Сверху Снизу