Исходник Fix animations memory leak weave

// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
AnimationFix.cpp
Код:
#include "Hooks.h"
#include "AnimationFix.h"
#include "RageBackTracking.h"
#include "Resolver.h"
#include "Ragebot.h"
#include "AntiAims.h"

CMAnimationFix* g_Animfix = new CMAnimationFix();
CResolver* resolver = new CResolver();

float calculate_lerp()
{
    static auto cl_interp = interfaces.cvars->FindVar(hs::cl_interp::s().c_str());
    static auto cl_updaterate = interfaces.cvars->FindVar(hs::cl_updaterate::s().c_str());
    const auto update_rate = cl_updaterate->GetInt();
    const auto interp_ratio = cl_interp->GetFloat();

    auto lerp = interp_ratio / update_rate;

    if (lerp <= interp_ratio)
        lerp = interp_ratio;

    return lerp;
}

void Extrapolate(IBasePlayer* player, Vector& origin, Vector& velocity, int& flags, bool on_ground)
{
    static const auto sv_gravity = interfaces.cvars->FindVar(hs::sv_gravity::s().c_str());
    static const auto sv_jump_impulse = interfaces.cvars->FindVar(hs::sv_jump_impulse::s().c_str());

    if (!(flags & FL_ONGROUND))
        velocity.z -= TICKS_TO_TIME(sv_gravity->GetFloat());
    else if (player->GetFlags() & FL_ONGROUND && !on_ground)
        velocity.z = sv_jump_impulse->GetFloat();

    const auto src = origin;
    auto end = src + velocity * interfaces.global_vars->interval_per_tick;

    Ray_t r;
    r.Init(src, end, player->GetMins(), player->GetMaxs());

    trace_t t;
    CTraceFilter filter;
    filter.pSkip = player;

    interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

    if (t.fraction != 1.f)
    {
        for (auto i = 0; i < 2; i++)
        {
            velocity -= t.plane.normal * velocity.Dot(t.plane.normal);

            const auto dot = velocity.Dot(t.plane.normal);
            if (dot < 0.f)
                velocity -= Vector(dot * t.plane.normal.x,
                    dot * t.plane.normal.y, dot * t.plane.normal.z);

            end = t.endpos + velocity * TICKS_TO_TIME(1.f - t.fraction);

            r.Init(t.endpos, end, player->GetMins(), player->GetMaxs());
            interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

            if (t.fraction == 1.f)
                break;
        }
    }

    origin = end = t.endpos;
    end.z -= 2.f;

    r.Init(origin, end, player->GetMins(), player->GetMaxs());
    interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

    flags &= ~FL_ONGROUND;

    if (t.DidHit() && t.plane.normal.z > .7f)
        flags |= FL_ONGROUND;
}

bool animation::is_valid(float range = .2f, float max_unlag = .2f)
{
    if (!interfaces.engine->GetNetChannelInfo() || !valid)
        return false;

    const auto correct = std::clamp(interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_INCOMING)
        + interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING)
        + calculate_lerp(), 0.f, max_unlag);
    //if (CanDT() && csgo->dt_charged && !CMAntiAim::Get().did_shot && !vars.ragebot.disable_dt_delay)
    //    range += TICKS_TO_TIME(8);
    return fabsf(correct - (interfaces.global_vars->curtime - sim_time)) < range && correct < 1.f;
}


animation::animation(IBasePlayer* player)
{
    const auto weapon = player->GetWeapon();

    this->player = player;
    index = player->GetIndex();
    dormant = player->IsDormant();
    velocity = player->GetVelocity();
    origin = player->GetOrigin();
    abs_origin = player->GetAbsOrigin();
    obb_mins = player->GetMins();
    obb_maxs = player->GetMaxs();
    memcpy(layers, player->GetAnimOverlays(), sizeof(CAnimationLayer) * 13);
    poses = player->m_flPoseParameter();
    //if ((has_anim_state = player->GetPlayerAnimState()))
    anim_state = player->GetPlayerAnimState();
    //anim_time = player->GetOldSimulationTime() + interfaces.global_vars->interval_per_tick;
    sim_time = player->GetSimulationTime();
    interp_time = 0.f;
    last_shot_time = weapon ? weapon->GetLastShotTime() : 0.f;
    duck = player->GetDuckAmount();
    lby = player->GetLBY();
    eye_angles = player->GetEyeAngles();
    abs_ang = player->GetAbsAngles();
    flags = player->GetFlags();
    eflags = player->GetEFlags();
    effects = player->GetEffects();

    lag = TIME_TO_TICKS(player->GetSimulationTime() - player->GetOldSimulationTime());

    // animations are off when we enter pvs, we do not want to shoot yet.
    valid = lag >= 0 && lag <= 17;

    // clamp it so we don't interpolate too far : )
    lag = std::clamp(lag, 0, 17);
}

animation::animation(IBasePlayer* player, Vector last_reliable_angle) : animation(player)
{
    this->last_reliable_angle = last_reliable_angle;
}

void animation::restore(IBasePlayer* player) const
{
    //player->GetVelocity() = velocity;
    player->GetFlagsPtr() = flags;
    //player->GetEFlags() = eflags;
    player->GetDuckAmount() = duck;
    memcpy(player->GetAnimOverlays(), layers, sizeof(CAnimationLayer) * 13);
    //player->GetLBY() = lby;
    player->GetOrigin() = origin;
    player->SetAbsOrigin(abs_origin);
    //player->m_flPoseParameter() = poses;
}

void animation::apply(IBasePlayer* player) const
{
    //player->m_flPoseParameter() = poses;
    *player->GetEyeAnglesPointer() = eye_angles;
    //player->GetVelocity() = velocity;
    //player->GetLBY() = lby;
    player->GetDuckAmount() = duck;
    player->GetFlagsPtr() = flags;
    player->GetOrigin() = origin;
    player->SetAbsOrigin(abs_origin);
    /*if (anim_state) {
        player->SetAnimState(anim_state);
    }*/
}

void animation::build_server_bones(IBasePlayer* player)
{
    const auto backup_occlusion_flags = player->GetOcclusionFlags();
    const auto backup_occlusion_framecount = player->GetOcclusionFramecount();

    player->GetOcclusionFlags() = 0;
    player->GetOcclusionFramecount() = 0;

    player->GetReadableBones() = player->GetWritableBones() = 0;

    player->InvalidateBoneCache();

    player->GetEffects() |= 0x8;

    const auto backup_bone_array = player->GetBoneArrayForWrite();
    player->GetBoneArrayForWrite() = bones;

    csgo->UpdateMatrix = true;
    player->SetupBones(nullptr, -1, 0x7FF00, interfaces.global_vars->curtime);
    csgo->UpdateMatrix = false;

    player->GetBoneArrayForWrite() = backup_bone_array;
    player->GetOcclusionFlags() = backup_occlusion_flags;
    player->GetOcclusionFramecount() = backup_occlusion_framecount;

    player->GetEffects() &= ~0x8;
}

void CMAnimationFix::animation_info::update_animations(animation* record, animation* from)
{
    auto Interpolate = [](const Vector from, const Vector to, const float percent) {
        return to * percent + from * (1.f - percent);
    };
    auto Interpolate2 = [](const float from, const float to, const float percent) {
        return to * percent + from * (1.f - percent);
    };

    if (!from)
    {
        // set velocity and layers.
        record->velocity = player->GetVelocity();

        // fix feet spin.
        record->anim_state->m_flFeetYawRate = 0.f;

        // apply record.
        record->apply(player);

        // run update.
        return g_Animfix->update_player(player);
    }

    const auto new_velocity = player->GetVelocity();

    // restore old record.

    memcpy(player->GetAnimOverlays(), from->layers, sizeof(CAnimationLayer) * 13);
    player->SetAbsOrigin(record->origin);
    player->SetAbsAngles(from->abs_ang);
    player->GetVelocity() = from->velocity;

    // setup velocity.
    record->velocity = new_velocity;

    // did the player shoot?

    // setup extrapolation parameters.
    auto old_origin = from->origin;
    auto old_flags = from->flags;



    for (auto i = 0; i < record->lag; i++)
    {

        // move time forward.
        const auto time = from->sim_time + TICKS_TO_TIME(i + 1);
        const auto lerp = 1.f - (record->sim_time - time) / (record->sim_time - from->sim_time);

        /*player->GetDuckAmount() = Interpolate2(from->duck, record->duck, lerp);*/

        // resolve player.
        if (record->lag - 1 == i)
        {
            player->GetVelocity() = new_velocity;
            player->GetFlagsPtr() = record->flags;
        }
        else // compute velocity and flags.
        {
            Extrapolate(player, old_origin, player->GetVelocity(), player->GetFlagsPtr(), old_flags & FL_ONGROUND);
            old_flags = player->GetFlags();
        }

        record->resolver = ResolverMode[player->GetIndex()];

        player->GetPlayerAnimState()->m_flFeetYawRate = 0.f;

        // backup simtime.
        const auto backup_simtime = player->GetSimulationTime();

        // set new simtime.
        player->GetSimulationTime() = time;

        // run update.
        g_Animfix->update_player(player);

        // restore old simtime.
        player->GetSimulationTime() = backup_simtime;
    }
    if (!record->dormant && !from->dormant)
        record->didshot = record->last_shot_time > from->sim_time && record->last_shot_time <= record->sim_time;
}

void CMAnimationFix::UpdatePlayers() {
    if (!interfaces.engine->IsInGame())
        return;

    const auto local = csgo->local;

    // erase outdated entries
    for (auto it = animation_infos.begin(); it != animation_infos.end();) {
        auto player = reinterpret_cast<IBasePlayer*>(interfaces.ent_list->GetClientEntityFromHandle(it->first));

        if (!player || player != it->second.player || !player->isAlive()
            || !local)
        {
            if (player)
                player->GetClientSideAnims() = true;
            it = animation_infos.erase(it);
        }
        else
            it = next(it);
    }

    if (!local)
    {
        for (auto i = 1; i <= interfaces.engine->GetMaxClients(); ++i) {
            const auto entity = interfaces.ent_list->GetClientEntity(i);
            if (entity && entity->IsPlayer())
                entity->GetClientSideAnims() = true;
        }
    }


    for (auto i = 1; i <= interfaces.engine->GetMaxClients(); ++i) {
        const auto entity = interfaces.ent_list->GetClientEntity(i);
        if (!entity || !entity->IsPlayer())
            continue;
        if (!entity->isAlive() || entity->IsDormant())
            continue;

        if (entity == local)
            continue;

        if (entity != local && entity->GetTeam() == local->GetTeam()) {
            csgo->EnableBones = entity->GetClientSideAnims() = true;
            continue;
        }

        if (animation_infos.find(entity->GetRefEHandle()) == animation_infos.end())
            animation_infos.insert_or_assign(entity->GetRefEHandle(), animation_info(entity, {}));
    }

    // run post update
    for (auto& info : animation_infos)
    {
        auto& _animation = info.second;
        const auto player = _animation.player;

        // erase frames out-of-range
        for (int i = 0; i < _animation.frames.size(); i++)
            if (!_animation.frames[i].is_valid(0.45f, 0.2f))
                _animation.frames.erase(_animation.frames.begin() + i);

    //    resolver->Do(_animation.player);

        // have we already seen this update?
        if (player->GetSimulationTime() == player->GetOldSimulationTime())
            continue;

        // reset animstate
        if (_animation.last_spawn_time != player->GetSpawnTime())
        {
            const auto state = player->GetPlayerAnimState();
            if (state)
                player->ResetAnimationState(state);

            _animation.last_spawn_time = player->GetSpawnTime();
        }

        // grab weapon
        const auto weapon = player->GetWeapon();

        // make a full backup of the player
        auto backup = animation(player);
        backup.apply(player);

        // grab previous
        animation* previous = nullptr;

        if (!_animation.frames.empty() && !_animation.frames.front().dormant)
            previous = &_animation.frames.front();

        const auto shot = weapon && previous && weapon->LastShotTime() > previous->sim_time
            && weapon->LastShotTime() <= player->GetSimulationTime();

        if (!shot)
            info.second.last_reliable_angle = player->GetEyeAngles();

        // store server record
        auto& record = _animation.frames.emplace_front(player, info.second.last_reliable_angle);

        // run full update
        _animation.update_animations(&record, previous);

        // restore correctly synced values
        backup.restore(player);

        // use uninterpolated data to generate our bone matrix
        record.build_server_bones(player);
    }
}

void CMAnimationFix::update_player(IBasePlayer* player)
{
    static auto& enable_bone_cache_invalidation = **reinterpret_cast<bool**>(
        reinterpret_cast<uint32_t>((void*)csgo->Utils.FindPatternIDA(GetModuleHandleA(g_Modules[fnv::hash(hs::client_dll::s().c_str())].c_str()),
            hs::bone_cache_validation::s().c_str())) + 2);

    //// make a backup of globals
    const auto backup_frametime = interfaces.global_vars->frametime;
    const auto backup_curtime = interfaces.global_vars->curtime;
    const auto old_flags = player->GetFlagsPtr();

    // get player anim state
    auto state = player->GetPlayerAnimState();

    if (state->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        state->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    // fixes for networked players
    interfaces.global_vars->frametime = interfaces.global_vars->interval_per_tick;
    interfaces.global_vars->curtime = player->GetSimulationTime();
    player->GetEFlags() &= ~0x1000;

    player->GetAbsVelocity() = player->GetVelocity();

    if (player->GetAnimOverlay(5)->m_flWeight > 0.0f)
        player->GetFlagsPtr() |= FL_ONGROUND;

    //player->InvalidatePhysicsRecursive(ANIMATION_CHANGED);

    // make sure we keep track of the original invalidation state
    const auto old_invalidation = enable_bone_cache_invalidation;

    // notify the other hooks to instruct animations and pvs fix

    csgo->EnableBones = player->GetClientSideAnims() = true;
    player->UpdateClientSideAnimation();
    csgo->EnableBones = player->GetClientSideAnims() = false;

    //player->InvalidatePhysicsRecursive(BOUNDS_CHANGED);

    player->InvalidatePhysicsRecursive(0x2A);

    // we don't want to enable cache invalidation by accident
    enable_bone_cache_invalidation = old_invalidation;

    // restore globals
    interfaces.global_vars->curtime = backup_curtime;
    interfaces.global_vars->frametime = backup_frametime;

    player->GetFlagsPtr() = old_flags;
}

CMAnimationFix::animation_info* CMAnimationFix::get_animation_info(IBasePlayer* player)
{
    auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end())
        return nullptr;

    return &info->second;
}

bool animation::is_valid_extended()
{
    if (!interfaces.engine->GetNetChannelInfo() || !valid)
        return false;

    const auto correct = std::clamp(interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_INCOMING)
        + interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING)
        + calculate_lerp(), 0.f, 0.2f);

    float deltaTime = fabsf(correct - (interfaces.global_vars->curtime - sim_time));
    float ping = 0.2f;
    //if (CanDT() && csgo->dt_charged && !CMAntiAim::Get().did_shot)
    //    ping += TICKS_TO_TIME(8);
    return deltaTime < ping && deltaTime >= ping - .2f;
}

std::optional<animation*> CMAnimationFix::get_latest_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it)) {
        if ((*it).is_valid_extended()) {
            if (TIME_TO_TICKS(fabsf((*it).sim_time - player->GetSimulationTime())) < 25)
                return &*it;
        }
    }

    return std::nullopt;
}

std::optional<animation*> CMAnimationFix::get_oldest_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.rbegin(); it != info->second.frames.rend(); it = next(it)) {
        if ((*it).is_valid_extended()) {
            return &*it;
        }
    }

    return std::nullopt;
}

std::vector<animation*> CMAnimationFix::get_valid_animations(IBasePlayer* player, const float range)
{
    std::vector<animation*> result;

    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return result;

    result.reserve(static_cast<int>(std::ceil(range * .2f / interfaces.global_vars->interval_per_tick)));

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it))
        if ((*it).is_valid(range * .2f))
            result.push_back(&*it);

    return result;
}


std::optional<animation*> CMAnimationFix::get_latest_firing_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it))
        if ((*it).is_valid_extended() && (*it).didshot)
            return &*it;

    return std::nullopt;
}

void CMAnimationFix::UpdateFakeState()
{
    //static bool ShouldInitAnimstate = false;

    if ((!interfaces.engine->IsConnected() && !interfaces.engine->IsInGame()) || !csgo->local) {
        //ShouldInitAnimstate = false;
        return;
    }

    if (!csgo->local->isAlive() /*|| csgo->game_rules->IsFreezeTime()*/) {
        //ShouldInitAnimstate = false;
        return;
    }

    if (csgo->DoUnload) {
        return;
    }


    static CBaseHandle* selfhandle = nullptr;
    static float spawntime = csgo->local->GetSpawnTime();

    auto alloc = FakeAnimstate == nullptr;
    auto change = !alloc && selfhandle != &csgo->local->GetRefEHandle();
    auto reset = !alloc && !change && csgo->local->GetSpawnTime() != spawntime;

    if (change) {
        memset(&FakeAnimstate, 0, sizeof(FakeAnimstate));
        selfhandle = (CBaseHandle*)&csgo->local->GetRefEHandle();
    }
    if (reset) {
        csgo->local->ResetAnimationState(FakeAnimstate);
        spawntime = csgo->local->GetSpawnTime();
    }

    if (alloc || change) {
        FakeAnimstate = reinterpret_cast<CCSGOPlayerAnimState*>(interfaces.memalloc->Alloc(sizeof(CCSGOPlayerAnimState)));
        if (FakeAnimstate)
            csgo->local->CreateAnimationState(FakeAnimstate);
    }

    if (FakeAnimstate->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        FakeAnimstate->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    csgo->local->GetEffects() |= 0x8;

    csgo->local->InvalidateBoneCache();

    CAnimationLayer backup_layers[13];
    if (csgo->local->GetOldSimulationTime() != csgo->local->GetSimulationTime())
    {
        std::memcpy(backup_layers, csgo->local->GetAnimOverlays(),
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));

        csgo->local->UpdateAnimationState(FakeAnimstate, csgo->FakeAngle); // update animstate
        csgo->local->SetAbsAngles(Vector(0, FakeAnimstate->m_flGoalFeetYaw, 0));
        csgo->local->GetAnimOverlay(12)->m_flWeight = FLT_EPSILON;
        csgo->local->SetupBones(csgo->fakematrix, 128, 0x7FF00, interfaces.global_vars->curtime);// setup matrix
        csgo->local->SetupBones(csgo->fakelag_matrix, 128, 0x7FF00, interfaces.global_vars->curtime);// setup matrix
        if (!vars.visuals.interpolated_dsy) {
            for (auto& i : csgo->fakematrix)
            {
                i[0][3] -= csgo->local->GetRenderOrigin().x;
                i[1][3] -= csgo->local->GetRenderOrigin().y;
                i[2][3] -= csgo->local->GetRenderOrigin().z;
            }
        }

        std::memcpy(csgo->local->GetAnimOverlays(), backup_layers,
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));
    }

    csgo->animstate = FakeAnimstate;

    csgo->local->GetEffects() &= ~0x8;
}

void CMAnimationFix::ApplyLocalPlayer() {
    auto animstate = csgo->local->GetPlayerAnimState();
    if (!animstate)
        return;

    const auto backup_frametime = interfaces.global_vars->frametime;
    const auto backup_curtime = interfaces.global_vars->curtime;

    animstate->m_flGoalFeetYaw = csgo->VisualAngle.y;

    if (animstate->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        animstate->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    interfaces.global_vars->frametime = interfaces.global_vars->interval_per_tick;
    interfaces.global_vars->curtime = csgo->local->GetSimulationTime();

    csgo->local->GetEFlags() &= ~0x1000;
    csgo->local->GetAbsVelocity() = csgo->local->GetVelocity();

    static float angle = animstate->m_flGoalFeetYaw;

    animstate->m_flFeetYawRate = 0.f;

    CAnimationLayer backup_layers[13];
    if (csgo->local->GetSimulationTime() != csgo->local->GetOldSimulationTime())
    {
        std::memcpy(backup_layers, csgo->local->GetAnimOverlays(),
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));

        csgo->ShouldUpdate = csgo->local->GetClientSideAnims() = true;
        csgo->local->UpdateAnimationState(animstate, csgo->FakeAngle);
        csgo->local->UpdateClientSideAnimation();
        csgo->ShouldUpdate = csgo->local->GetClientSideAnims() = false;

        angle = animstate->m_flGoalFeetYaw;

        std::memcpy(csgo->local->GetAnimOverlays(), backup_layers,
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));
    }
    animstate->m_flGoalFeetYaw = angle;
    interfaces.global_vars->curtime = backup_curtime;
    interfaces.global_vars->frametime = backup_frametime;
    //csgo->local->DrawServerHitboxes();
}
AnimationFix.h
Код:
#pragma once
#include "Hooks.h"
#include <unordered_map>
#include <optional>
#include <deque>

struct animation
{
    animation() = default;
    explicit animation(IBasePlayer* player);
    explicit animation(IBasePlayer* player, Vector last_reliable_angle);
    void restore(IBasePlayer* player) const;
    void apply(IBasePlayer* player) const;
    void build_server_bones(IBasePlayer* player);
    bool is_valid(float range, float max_unlag);
    bool is_valid_extended();

    IBasePlayer* player{};
    int32_t index{};

    bool valid{}, has_anim_state{};
    alignas(16) matrix bones[128];

    bool dormant{};
    Vector velocity;
    Vector origin;
    matrix* bone_cache;
    Vector abs_origin;
    Vector obb_mins;
    Vector obb_maxs;
    CAnimationLayer layers[13];
    std::array<float, 24> poses;
    CCSGOPlayerAnimState* anim_state;
    float anim_time{};
    float sim_time{};
    float interp_time{};
    float duck{};
    float lby{};
    float last_shot_time{};
    Vector last_reliable_angle{};
    Vector eye_angles;
    Vector abs_ang;
    int flags{};
    int eflags{};
    int effects{};
    float m_flFeetCycle{};
    float m_flFeetYawRate{};
    int lag{};
    bool didshot;
    string resolver;
};


class CMAnimationFix
{
public:

private:
    struct animation_info {
        animation_info(IBasePlayer* player, std::deque<animation> animations)
            : player(player), frames(std::move(animations)), last_spawn_time(0) { }

        void update_animations(animation* to, animation* from);

        IBasePlayer* player{};
        std::deque<animation> frames;

        // last time this player spawned
        float last_spawn_time;
        float goal_feet_yaw;
        Vector last_reliable_angle;
    };

    std::unordered_map<CBaseHandle, animation_info> animation_infos;

public:
    void ApplyLocalPlayer();
    void UpdatePlayers();
    void UpdateFakeState();

    CCSGOPlayerAnimState* RealAnimstate = nullptr;
    CCSGOPlayerAnimState* FakeAnimstate = nullptr;
    CBaseHandle* selfhandle;
    void update_player(IBasePlayer* player);


    animation_info* get_animation_info(IBasePlayer* player);
    std::optional<animation*> get_latest_animation(IBasePlayer* player);
    std::optional<animation*> get_oldest_animation(IBasePlayer* player);
    std::vector<animation*> get_valid_animations(IBasePlayer* player, float range = 1.f);
    std::optional<animation*> get_latest_firing_animation(IBasePlayer* player);
};
extern CMAnimationFix* g_Animfix;
взято с этой темы: https://yougame.biz/threads/160078/

Тестил на ботах, краш с tier0 пропал Screenshot_4.png
 
Последнее редактирование:
Президент
Забаненный
Статус
Оффлайн
Регистрация
27 Авг 2018
Сообщения
53
Реакции[?]
17
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
тему на используемый исходник прикрепи, ибо твой фикс на переделках не пойдет.
 
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
тему на используемый исходник прикрепи, ибо твой фикс на переделках не пойдет.
почему? Кроме анимаций ничего не менял, в других файлах у меня ошибок нету
 
gayware
Забаненный
Статус
Оффлайн
Регистрация
6 Дек 2017
Сообщения
141
Реакции[?]
19
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
дай длл :roflanEbalo:
 
Президент
Забаненный
Статус
Оффлайн
Регистрация
27 Авг 2018
Сообщения
53
Реакции[?]
17
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
почему? Кроме анимаций ничего не менял, в других файлах у меня ошибок нету
в переделках функции переименованы, поэтому, я считаю, твой фикс приведет к крашам при заходе на мапу, либо при инжекте. просто прикрепи исходники, на которых ты юзаешь этот фикс, чтобы миллион вопросов не было к тебе:)
 
Забаненный
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
161
Реакции[?]
58
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
нихуево :roflanBuldiga:
 
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
в переделках функции переименованы, поэтому, я считаю, твой фикс приведет к крашам при заходе на мапу, либо при инжекте. просто прикрепи исходники, на которых ты юзаешь этот фикс, чтобы миллион вопросов не было к тебе:)
у меня крашей нету, но все таки прикрепил тему.
 
Президент
Забаненный
Статус
Оффлайн
Регистрация
27 Авг 2018
Сообщения
53
Реакции[?]
17
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
родной, нужно указать скорее не ту тему, откуда ты взял, а ту тему, с исходниками которой этот фикс прокатит:)
 
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
родной, нужно указать скорее не ту тему, откуда ты взял, а ту тему, с исходниками которой этот фикс прокатит:)
я хз откуда брал, дефолтный weave. На все пойдет
 
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
ставь чайник, зажигай плиту
Эксперт
Статус
Оффлайн
Регистрация
22 Май 2020
Сообщения
1,442
Реакции[?]
1,092
Поинты[?]
10K
родной, нужно указать скорее не ту тему, откуда ты взял, а ту тему, с исходниками которой этот фикс прокатит:)
Просто так прямо и скажи - дай мне ебучий исходник я не могу спастить
 
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
ставь чайник, зажигай плиту
Эксперт
Статус
Оффлайн
Регистрация
22 Май 2020
Сообщения
1,442
Реакции[?]
1,092
Поинты[?]
10K
Президент
Забаненный
Статус
Оффлайн
Регистрация
27 Авг 2018
Сообщения
53
Реакции[?]
17
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Забаненный
Статус
Оффлайн
Регистрация
15 Сен 2020
Сообщения
82
Реакции[?]
5
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
AnimationFix.cpp
Код:
#include "Hooks.h"
#include "AnimationFix.h"
#include "RageBackTracking.h"
#include "Resolver.h"
#include "Ragebot.h"
#include "AntiAims.h"

CMAnimationFix* g_Animfix = new CMAnimationFix();
CResolver* resolver = new CResolver();

float calculate_lerp()
{
    static auto cl_interp = interfaces.cvars->FindVar(hs::cl_interp::s().c_str());
    static auto cl_updaterate = interfaces.cvars->FindVar(hs::cl_updaterate::s().c_str());
    const auto update_rate = cl_updaterate->GetInt();
    const auto interp_ratio = cl_interp->GetFloat();

    auto lerp = interp_ratio / update_rate;

    if (lerp <= interp_ratio)
        lerp = interp_ratio;

    return lerp;
}

void Extrapolate(IBasePlayer* player, Vector& origin, Vector& velocity, int& flags, bool on_ground)
{
    static const auto sv_gravity = interfaces.cvars->FindVar(hs::sv_gravity::s().c_str());
    static const auto sv_jump_impulse = interfaces.cvars->FindVar(hs::sv_jump_impulse::s().c_str());

    if (!(flags & FL_ONGROUND))
        velocity.z -= TICKS_TO_TIME(sv_gravity->GetFloat());
    else if (player->GetFlags() & FL_ONGROUND && !on_ground)
        velocity.z = sv_jump_impulse->GetFloat();

    const auto src = origin;
    auto end = src + velocity * interfaces.global_vars->interval_per_tick;

    Ray_t r;
    r.Init(src, end, player->GetMins(), player->GetMaxs());

    trace_t t;
    CTraceFilter filter;
    filter.pSkip = player;

    interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

    if (t.fraction != 1.f)
    {
        for (auto i = 0; i < 2; i++)
        {
            velocity -= t.plane.normal * velocity.Dot(t.plane.normal);

            const auto dot = velocity.Dot(t.plane.normal);
            if (dot < 0.f)
                velocity -= Vector(dot * t.plane.normal.x,
                    dot * t.plane.normal.y, dot * t.plane.normal.z);

            end = t.endpos + velocity * TICKS_TO_TIME(1.f - t.fraction);

            r.Init(t.endpos, end, player->GetMins(), player->GetMaxs());
            interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

            if (t.fraction == 1.f)
                break;
        }
    }

    origin = end = t.endpos;
    end.z -= 2.f;

    r.Init(origin, end, player->GetMins(), player->GetMaxs());
    interfaces.trace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);

    flags &= ~FL_ONGROUND;

    if (t.DidHit() && t.plane.normal.z > .7f)
        flags |= FL_ONGROUND;
}

bool animation::is_valid(float range = .2f, float max_unlag = .2f)
{
    if (!interfaces.engine->GetNetChannelInfo() || !valid)
        return false;

    const auto correct = std::clamp(interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_INCOMING)
        + interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING)
        + calculate_lerp(), 0.f, max_unlag);
    //if (CanDT() && csgo->dt_charged && !CMAntiAim::Get().did_shot && !vars.ragebot.disable_dt_delay)
    //    range += TICKS_TO_TIME(8);
    return fabsf(correct - (interfaces.global_vars->curtime - sim_time)) < range && correct < 1.f;
}


animation::animation(IBasePlayer* player)
{
    const auto weapon = player->GetWeapon();

    this->player = player;
    index = player->GetIndex();
    dormant = player->IsDormant();
    velocity = player->GetVelocity();
    origin = player->GetOrigin();
    abs_origin = player->GetAbsOrigin();
    obb_mins = player->GetMins();
    obb_maxs = player->GetMaxs();
    memcpy(layers, player->GetAnimOverlays(), sizeof(CAnimationLayer) * 13);
    poses = player->m_flPoseParameter();
    //if ((has_anim_state = player->GetPlayerAnimState()))
    anim_state = player->GetPlayerAnimState();
    //anim_time = player->GetOldSimulationTime() + interfaces.global_vars->interval_per_tick;
    sim_time = player->GetSimulationTime();
    interp_time = 0.f;
    last_shot_time = weapon ? weapon->GetLastShotTime() : 0.f;
    duck = player->GetDuckAmount();
    lby = player->GetLBY();
    eye_angles = player->GetEyeAngles();
    abs_ang = player->GetAbsAngles();
    flags = player->GetFlags();
    eflags = player->GetEFlags();
    effects = player->GetEffects();

    lag = TIME_TO_TICKS(player->GetSimulationTime() - player->GetOldSimulationTime());

    // animations are off when we enter pvs, we do not want to shoot yet.
    valid = lag >= 0 && lag <= 17;

    // clamp it so we don't interpolate too far : )
    lag = std::clamp(lag, 0, 17);
}

animation::animation(IBasePlayer* player, Vector last_reliable_angle) : animation(player)
{
    this->last_reliable_angle = last_reliable_angle;
}

void animation::restore(IBasePlayer* player) const
{
    //player->GetVelocity() = velocity;
    player->GetFlagsPtr() = flags;
    //player->GetEFlags() = eflags;
    player->GetDuckAmount() = duck;
    memcpy(player->GetAnimOverlays(), layers, sizeof(CAnimationLayer) * 13);
    //player->GetLBY() = lby;
    player->GetOrigin() = origin;
    player->SetAbsOrigin(abs_origin);
    //player->m_flPoseParameter() = poses;
}

void animation::apply(IBasePlayer* player) const
{
    //player->m_flPoseParameter() = poses;
    *player->GetEyeAnglesPointer() = eye_angles;
    //player->GetVelocity() = velocity;
    //player->GetLBY() = lby;
    player->GetDuckAmount() = duck;
    player->GetFlagsPtr() = flags;
    player->GetOrigin() = origin;
    player->SetAbsOrigin(abs_origin);
    /*if (anim_state) {
        player->SetAnimState(anim_state);
    }*/
}

void animation::build_server_bones(IBasePlayer* player)
{
    const auto backup_occlusion_flags = player->GetOcclusionFlags();
    const auto backup_occlusion_framecount = player->GetOcclusionFramecount();

    player->GetOcclusionFlags() = 0;
    player->GetOcclusionFramecount() = 0;

    player->GetReadableBones() = player->GetWritableBones() = 0;

    player->InvalidateBoneCache();

    player->GetEffects() |= 0x8;

    const auto backup_bone_array = player->GetBoneArrayForWrite();
    player->GetBoneArrayForWrite() = bones;

    csgo->UpdateMatrix = true;
    player->SetupBones(nullptr, -1, 0x7FF00, interfaces.global_vars->curtime);
    csgo->UpdateMatrix = false;

    player->GetBoneArrayForWrite() = backup_bone_array;
    player->GetOcclusionFlags() = backup_occlusion_flags;
    player->GetOcclusionFramecount() = backup_occlusion_framecount;

    player->GetEffects() &= ~0x8;
}

void CMAnimationFix::animation_info::update_animations(animation* record, animation* from)
{
    auto Interpolate = [](const Vector from, const Vector to, const float percent) {
        return to * percent + from * (1.f - percent);
    };
    auto Interpolate2 = [](const float from, const float to, const float percent) {
        return to * percent + from * (1.f - percent);
    };

    if (!from)
    {
        // set velocity and layers.
        record->velocity = player->GetVelocity();

        // fix feet spin.
        record->anim_state->m_flFeetYawRate = 0.f;

        // apply record.
        record->apply(player);

        // run update.
        return g_Animfix->update_player(player);
    }

    const auto new_velocity = player->GetVelocity();

    // restore old record.

    memcpy(player->GetAnimOverlays(), from->layers, sizeof(CAnimationLayer) * 13);
    player->SetAbsOrigin(record->origin);
    player->SetAbsAngles(from->abs_ang);
    player->GetVelocity() = from->velocity;

    // setup velocity.
    record->velocity = new_velocity;

    // did the player shoot?

    // setup extrapolation parameters.
    auto old_origin = from->origin;
    auto old_flags = from->flags;



    for (auto i = 0; i < record->lag; i++)
    {

        // move time forward.
        const auto time = from->sim_time + TICKS_TO_TIME(i + 1);
        const auto lerp = 1.f - (record->sim_time - time) / (record->sim_time - from->sim_time);

        /*player->GetDuckAmount() = Interpolate2(from->duck, record->duck, lerp);*/

        // resolve player.
        if (record->lag - 1 == i)
        {
            player->GetVelocity() = new_velocity;
            player->GetFlagsPtr() = record->flags;
        }
        else // compute velocity and flags.
        {
            Extrapolate(player, old_origin, player->GetVelocity(), player->GetFlagsPtr(), old_flags & FL_ONGROUND);
            old_flags = player->GetFlags();
        }

        record->resolver = ResolverMode[player->GetIndex()];

        player->GetPlayerAnimState()->m_flFeetYawRate = 0.f;

        // backup simtime.
        const auto backup_simtime = player->GetSimulationTime();

        // set new simtime.
        player->GetSimulationTime() = time;

        // run update.
        g_Animfix->update_player(player);

        // restore old simtime.
        player->GetSimulationTime() = backup_simtime;
    }
    if (!record->dormant && !from->dormant)
        record->didshot = record->last_shot_time > from->sim_time && record->last_shot_time <= record->sim_time;
}

void CMAnimationFix::UpdatePlayers() {
    if (!interfaces.engine->IsInGame())
        return;

    const auto local = csgo->local;

    // erase outdated entries
    for (auto it = animation_infos.begin(); it != animation_infos.end();) {
        auto player = reinterpret_cast<IBasePlayer*>(interfaces.ent_list->GetClientEntityFromHandle(it->first));

        if (!player || player != it->second.player || !player->isAlive()
            || !local)
        {
            if (player)
                player->GetClientSideAnims() = true;
            it = animation_infos.erase(it);
        }
        else
            it = next(it);
    }

    if (!local)
    {
        for (auto i = 1; i <= interfaces.engine->GetMaxClients(); ++i) {
            const auto entity = interfaces.ent_list->GetClientEntity(i);
            if (entity && entity->IsPlayer())
                entity->GetClientSideAnims() = true;
        }
    }


    for (auto i = 1; i <= interfaces.engine->GetMaxClients(); ++i) {
        const auto entity = interfaces.ent_list->GetClientEntity(i);
        if (!entity || !entity->IsPlayer())
            continue;
        if (!entity->isAlive() || entity->IsDormant())
            continue;

        if (entity == local)
            continue;

        if (entity != local && entity->GetTeam() == local->GetTeam()) {
            csgo->EnableBones = entity->GetClientSideAnims() = true;
            continue;
        }

        if (animation_infos.find(entity->GetRefEHandle()) == animation_infos.end())
            animation_infos.insert_or_assign(entity->GetRefEHandle(), animation_info(entity, {}));
    }

    // run post update
    for (auto& info : animation_infos)
    {
        auto& _animation = info.second;
        const auto player = _animation.player;

        // erase frames out-of-range
        for (int i = 0; i < _animation.frames.size(); i++)
            if (!_animation.frames[i].is_valid(0.45f, 0.2f))
                _animation.frames.erase(_animation.frames.begin() + i);

    //    resolver->Do(_animation.player);

        // have we already seen this update?
        if (player->GetSimulationTime() == player->GetOldSimulationTime())
            continue;

        // reset animstate
        if (_animation.last_spawn_time != player->GetSpawnTime())
        {
            const auto state = player->GetPlayerAnimState();
            if (state)
                player->ResetAnimationState(state);

            _animation.last_spawn_time = player->GetSpawnTime();
        }

        // grab weapon
        const auto weapon = player->GetWeapon();

        // make a full backup of the player
        auto backup = animation(player);
        backup.apply(player);

        // grab previous
        animation* previous = nullptr;

        if (!_animation.frames.empty() && !_animation.frames.front().dormant)
            previous = &_animation.frames.front();

        const auto shot = weapon && previous && weapon->LastShotTime() > previous->sim_time
            && weapon->LastShotTime() <= player->GetSimulationTime();

        if (!shot)
            info.second.last_reliable_angle = player->GetEyeAngles();

        // store server record
        auto& record = _animation.frames.emplace_front(player, info.second.last_reliable_angle);

        // run full update
        _animation.update_animations(&record, previous);

        // restore correctly synced values
        backup.restore(player);

        // use uninterpolated data to generate our bone matrix
        record.build_server_bones(player);
    }
}

void CMAnimationFix::update_player(IBasePlayer* player)
{
    static auto& enable_bone_cache_invalidation = **reinterpret_cast<bool**>(
        reinterpret_cast<uint32_t>((void*)csgo->Utils.FindPatternIDA(GetModuleHandleA(g_Modules[fnv::hash(hs::client_dll::s().c_str())].c_str()),
            hs::bone_cache_validation::s().c_str())) + 2);

    //// make a backup of globals
    const auto backup_frametime = interfaces.global_vars->frametime;
    const auto backup_curtime = interfaces.global_vars->curtime;
    const auto old_flags = player->GetFlagsPtr();

    // get player anim state
    auto state = player->GetPlayerAnimState();

    if (state->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        state->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    // fixes for networked players
    interfaces.global_vars->frametime = interfaces.global_vars->interval_per_tick;
    interfaces.global_vars->curtime = player->GetSimulationTime();
    player->GetEFlags() &= ~0x1000;

    player->GetAbsVelocity() = player->GetVelocity();

    if (player->GetAnimOverlay(5)->m_flWeight > 0.0f)
        player->GetFlagsPtr() |= FL_ONGROUND;

    //player->InvalidatePhysicsRecursive(ANIMATION_CHANGED);

    // make sure we keep track of the original invalidation state
    const auto old_invalidation = enable_bone_cache_invalidation;

    // notify the other hooks to instruct animations and pvs fix

    csgo->EnableBones = player->GetClientSideAnims() = true;
    player->UpdateClientSideAnimation();
    csgo->EnableBones = player->GetClientSideAnims() = false;

    //player->InvalidatePhysicsRecursive(BOUNDS_CHANGED);

    player->InvalidatePhysicsRecursive(0x2A);

    // we don't want to enable cache invalidation by accident
    enable_bone_cache_invalidation = old_invalidation;

    // restore globals
    interfaces.global_vars->curtime = backup_curtime;
    interfaces.global_vars->frametime = backup_frametime;

    player->GetFlagsPtr() = old_flags;
}

CMAnimationFix::animation_info* CMAnimationFix::get_animation_info(IBasePlayer* player)
{
    auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end())
        return nullptr;

    return &info->second;
}

bool animation::is_valid_extended()
{
    if (!interfaces.engine->GetNetChannelInfo() || !valid)
        return false;

    const auto correct = std::clamp(interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_INCOMING)
        + interfaces.engine->GetNetChannelInfo()->GetLatency(FLOW_OUTGOING)
        + calculate_lerp(), 0.f, 0.2f);

    float deltaTime = fabsf(correct - (interfaces.global_vars->curtime - sim_time));
    float ping = 0.2f;
    //if (CanDT() && csgo->dt_charged && !CMAntiAim::Get().did_shot)
    //    ping += TICKS_TO_TIME(8);
    return deltaTime < ping && deltaTime >= ping - .2f;
}

std::optional<animation*> CMAnimationFix::get_latest_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it)) {
        if ((*it).is_valid_extended()) {
            if (TIME_TO_TICKS(fabsf((*it).sim_time - player->GetSimulationTime())) < 25)
                return &*it;
        }
    }

    return std::nullopt;
}

std::optional<animation*> CMAnimationFix::get_oldest_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.rbegin(); it != info->second.frames.rend(); it = next(it)) {
        if ((*it).is_valid_extended()) {
            return &*it;
        }
    }

    return std::nullopt;
}

std::vector<animation*> CMAnimationFix::get_valid_animations(IBasePlayer* player, const float range)
{
    std::vector<animation*> result;

    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return result;

    result.reserve(static_cast<int>(std::ceil(range * .2f / interfaces.global_vars->interval_per_tick)));

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it))
        if ((*it).is_valid(range * .2f))
            result.push_back(&*it);

    return result;
}


std::optional<animation*> CMAnimationFix::get_latest_firing_animation(IBasePlayer* player)
{
    const auto info = animation_infos.find(player->GetRefEHandle());

    if (info == animation_infos.end() || info->second.frames.empty())
        return std::nullopt;

    for (auto it = info->second.frames.begin(); it != info->second.frames.end(); it = next(it))
        if ((*it).is_valid_extended() && (*it).didshot)
            return &*it;

    return std::nullopt;
}

void CMAnimationFix::UpdateFakeState()
{
    //static bool ShouldInitAnimstate = false;

    if ((!interfaces.engine->IsConnected() && !interfaces.engine->IsInGame()) || !csgo->local) {
        //ShouldInitAnimstate = false;
        return;
    }

    if (!csgo->local->isAlive() /*|| csgo->game_rules->IsFreezeTime()*/) {
        //ShouldInitAnimstate = false;
        return;
    }

    if (csgo->DoUnload) {
        return;
    }


    static CBaseHandle* selfhandle = nullptr;
    static float spawntime = csgo->local->GetSpawnTime();

    auto alloc = FakeAnimstate == nullptr;
    auto change = !alloc && selfhandle != &csgo->local->GetRefEHandle();
    auto reset = !alloc && !change && csgo->local->GetSpawnTime() != spawntime;

    if (change) {
        memset(&FakeAnimstate, 0, sizeof(FakeAnimstate));
        selfhandle = (CBaseHandle*)&csgo->local->GetRefEHandle();
    }
    if (reset) {
        csgo->local->ResetAnimationState(FakeAnimstate);
        spawntime = csgo->local->GetSpawnTime();
    }

    if (alloc || change) {
        FakeAnimstate = reinterpret_cast<CCSGOPlayerAnimState*>(interfaces.memalloc->Alloc(sizeof(CCSGOPlayerAnimState)));
        if (FakeAnimstate)
            csgo->local->CreateAnimationState(FakeAnimstate);
    }

    if (FakeAnimstate->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        FakeAnimstate->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    csgo->local->GetEffects() |= 0x8;

    csgo->local->InvalidateBoneCache();

    CAnimationLayer backup_layers[13];
    if (csgo->local->GetOldSimulationTime() != csgo->local->GetSimulationTime())
    {
        std::memcpy(backup_layers, csgo->local->GetAnimOverlays(),
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));

        csgo->local->UpdateAnimationState(FakeAnimstate, csgo->FakeAngle); // update animstate
        csgo->local->SetAbsAngles(Vector(0, FakeAnimstate->m_flGoalFeetYaw, 0));
        csgo->local->GetAnimOverlay(12)->m_flWeight = FLT_EPSILON;
        csgo->local->SetupBones(csgo->fakematrix, 128, 0x7FF00, interfaces.global_vars->curtime);// setup matrix
        csgo->local->SetupBones(csgo->fakelag_matrix, 128, 0x7FF00, interfaces.global_vars->curtime);// setup matrix
        if (!vars.visuals.interpolated_dsy) {
            for (auto& i : csgo->fakematrix)
            {
                i[0][3] -= csgo->local->GetRenderOrigin().x;
                i[1][3] -= csgo->local->GetRenderOrigin().y;
                i[2][3] -= csgo->local->GetRenderOrigin().z;
            }
        }

        std::memcpy(csgo->local->GetAnimOverlays(), backup_layers,
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));
    }

    csgo->animstate = FakeAnimstate;

    csgo->local->GetEffects() &= ~0x8;
}

void CMAnimationFix::ApplyLocalPlayer() {
    auto animstate = csgo->local->GetPlayerAnimState();
    if (!animstate)
        return;

    const auto backup_frametime = interfaces.global_vars->frametime;
    const auto backup_curtime = interfaces.global_vars->curtime;

    animstate->m_flGoalFeetYaw = csgo->VisualAngle.y;

    if (animstate->m_iLastClientSideAnimationUpdateFramecount == interfaces.global_vars->framecount)
        animstate->m_iLastClientSideAnimationUpdateFramecount -= 1.f;

    interfaces.global_vars->frametime = interfaces.global_vars->interval_per_tick;
    interfaces.global_vars->curtime = csgo->local->GetSimulationTime();

    csgo->local->GetEFlags() &= ~0x1000;
    csgo->local->GetAbsVelocity() = csgo->local->GetVelocity();

    static float angle = animstate->m_flGoalFeetYaw;

    animstate->m_flFeetYawRate = 0.f;

    CAnimationLayer backup_layers[13];
    if (csgo->local->GetSimulationTime() != csgo->local->GetOldSimulationTime())
    {
        std::memcpy(backup_layers, csgo->local->GetAnimOverlays(),
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));

        csgo->ShouldUpdate = csgo->local->GetClientSideAnims() = true;
        csgo->local->UpdateAnimationState(animstate, csgo->FakeAngle);
        csgo->local->UpdateClientSideAnimation();
        csgo->ShouldUpdate = csgo->local->GetClientSideAnims() = false;

        angle = animstate->m_flGoalFeetYaw;

        std::memcpy(csgo->local->GetAnimOverlays(), backup_layers,
            (sizeof(CAnimationLayer) * csgo->local->GetNumAnimOverlays()));
    }
    animstate->m_flGoalFeetYaw = angle;
    interfaces.global_vars->curtime = backup_curtime;
    interfaces.global_vars->frametime = backup_frametime;
    //csgo->local->DrawServerHitboxes();
}
AnimationFix.h
Код:
#pragma once
#include "Hooks.h"
#include <unordered_map>
#include <optional>
#include <deque>

struct animation
{
    animation() = default;
    explicit animation(IBasePlayer* player);
    explicit animation(IBasePlayer* player, Vector last_reliable_angle);
    void restore(IBasePlayer* player) const;
    void apply(IBasePlayer* player) const;
    void build_server_bones(IBasePlayer* player);
    bool is_valid(float range, float max_unlag);
    bool is_valid_extended();

    IBasePlayer* player{};
    int32_t index{};

    bool valid{}, has_anim_state{};
    alignas(16) matrix bones[128];

    bool dormant{};
    Vector velocity;
    Vector origin;
    matrix* bone_cache;
    Vector abs_origin;
    Vector obb_mins;
    Vector obb_maxs;
    CAnimationLayer layers[13];
    std::array<float, 24> poses;
    CCSGOPlayerAnimState* anim_state;
    float anim_time{};
    float sim_time{};
    float interp_time{};
    float duck{};
    float lby{};
    float last_shot_time{};
    Vector last_reliable_angle{};
    Vector eye_angles;
    Vector abs_ang;
    int flags{};
    int eflags{};
    int effects{};
    float m_flFeetCycle{};
    float m_flFeetYawRate{};
    int lag{};
    bool didshot;
    string resolver;
};


class CMAnimationFix
{
public:

private:
    struct animation_info {
        animation_info(IBasePlayer* player, std::deque<animation> animations)
            : player(player), frames(std::move(animations)), last_spawn_time(0) { }

        void update_animations(animation* to, animation* from);

        IBasePlayer* player{};
        std::deque<animation> frames;

        // last time this player spawned
        float last_spawn_time;
        float goal_feet_yaw;
        Vector last_reliable_angle;
    };

    std::unordered_map<CBaseHandle, animation_info> animation_infos;

public:
    void ApplyLocalPlayer();
    void UpdatePlayers();
    void UpdateFakeState();

    CCSGOPlayerAnimState* RealAnimstate = nullptr;
    CCSGOPlayerAnimState* FakeAnimstate = nullptr;
    CBaseHandle* selfhandle;
    void update_player(IBasePlayer* player);


    animation_info* get_animation_info(IBasePlayer* player);
    std::optional<animation*> get_latest_animation(IBasePlayer* player);
    std::optional<animation*> get_oldest_animation(IBasePlayer* player);
    std::vector<animation*> get_valid_animations(IBasePlayer* player, float range = 1.f);
    std::optional<animation*> get_latest_firing_animation(IBasePlayer* player);
};
extern CMAnimationFix* g_Animfix;
взято с этой темы: https://yougame.biz/threads/160078/

Тестил на ботах, краш с tier0 пропал Посмотреть вложение 101222
есть какие нибудь приколы кроме крашей?
 
фывфывфывфывфыфывфывфывфывфывфыв
Забаненный
Статус
Оффлайн
Регистрация
2 Июл 2020
Сообщения
557
Реакции[?]
140
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
// removed because antipasta
Забаненный
Статус
Оффлайн
Регистрация
10 Сен 2018
Сообщения
312
Реакции[?]
145
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Сверху Снизу