Исходник Semi proper animation fix (sup paste ready)

Начинающий
Статус
Оффлайн
Регистрация
22 Сен 2018
Сообщения
25
Реакции[?]
5
Поинты[?]
3K
Для просмотра содержимого вам необходимо авторизоваться.


I'm just adding onto what plztellmewhattheheck said, if a player is ducking the const var would be 0.34, if the player is triggering IsWalking() (offset that can be grabbed), it would be 0.52
 
Начинающий
Статус
Оффлайн
Регистрация
15 Окт 2019
Сообщения
18
Реакции[?]
5
Поинты[?]
5K
edit added "silent updates" fix after comment war lol.

credits: https://yougame.biz/threads/325142/

Пожалуйста, авторизуйтесь для просмотра ссылки.

formated bonzo code, added velocity recalculation and land/fall fix:
#include "includes.h"
// credits: https://yougame.biz/threads/325142/
// https://github.com/LAITHCOOL/laith-legendware-rework/blob/05d18bde61644291e29a5d81f9772c16770fe223/cheats/lagcompensation/animation_system.cpp

void handle_silent_updates(Player* player, c_animstate* state) {
    if (!player || !state) return;

    // Check if the last frame was updated or if there is a significant time difference
    if (state->last_update_frame == g_csgo.m_globals->m_framecount) {
        // No need to update, as the frame was recently updated
        return;
    }

    // If a silent update is detected, reapply or interpolate the last known correct state
    float time_difference = g_csgo.m_globals->m_curtime - state->last_update_time;

    // If the time difference exceeds a threshold, consider it a silent update
    if (time_difference > g_csgo.m_globals->m_interval * 2) {
        // Reapply the last known state or interpolate to the current state
        state->eye_yaw = interpolate(state->eye_yaw, player->m_flLowerBodyYawTarget(), time_difference);
    }

    // Update the state variables to the current frame and time
    state->last_update_frame = g_csgo.m_globals->m_framecount;
    state->last_update_time = g_csgo.m_globals->m_curtime;

// Mini update function for handling animations
void anims::mini_update(Player* player) {
    if (!player) return;  // check for null pointer.

    C_AnimationLayer backup_layers[13];
    player->GetAnimLayers(backup_layers);

    // backup globalvars.
    float curtime = g_csgo.m_globals->m_curtime;
    float frame = g_csgo.m_globals->m_frame;
    float frametime = g_csgo.m_globals->m_frametime;

    // set frametime to IPT just like on the server during simulation.
    g_csgo.m_globals->m_curtime = player->m_flSimulationTime();
    g_csgo.m_globals->m_frame = g_csgo.m_cl->m_server_tick;
    g_csgo.m_globals->m_frametime = g_csgo.m_globals->m_interval;

    // remove abs velocity.
    player->m_iEFlags() &= ~0x1000;
    player->SetAbsVelocity(player->m_vecVelocity());

  // Handle silent updates before updating animations 
   handle_silent_updates(player, player->m_AnimState());

    // update animations.
    g_hooks.m_UpdateClientSideAnimation(player);

    // restore layers to networked.
    player->SetAnimLayers(backup_layers);

    // restore once we're done.
    g_csgo.m_globals->m_frame = frame;
    g_csgo.m_globals->m_curtime = curtime;
    g_csgo.m_globals->m_frametime = frametime;
}

// function to reset state variables.
void reset_state_vars(Player* player, c_animstate* state, LagRecord* record) {
    if (!player || !state || !record) return;

    state->on_ground = !!(player->m_fFlags() & FL_ONGROUND);
    state->landing = false;
    state->abs_yaw_last = state->abs_yaw = player->m_flLowerBodyYawTarget();
    state->eye_yaw = player->m_flLowerBodyYawTarget();
    state->eye_pitch = record->m_eye_angles.x;
    state->primary_cycle = record->m_layers[6].m_cycle;
    state->move_weight = record->m_layers[6].m_weight;
    state->strafe_sequence = record->m_layers[7].m_sequence;
    state->strafe_change_weight = record->m_layers[7].m_weight;
    state->strafe_change_cycle = record->m_layers[7].m_cycle;
    state->acceleration_weight = record->m_layers[12].m_weight;

    player->m_flOldSimulationTime() = state->last_update_time = record->m_sim_time - g_csgo.m_globals->m_interval;
    state->last_update_frame = g_csgo.m_cl->m_server_tick - 1;
    state->duration_in_air = 0.f;

    record->m_anim_velocity = player->m_vecVelocity();
    if (state->on_ground) {
        record->m_anim_velocity.z = 0.f;
        if (state->primary_cycle == 0.f || state->move_weight == 0.f) {
            record->m_anim_velocity = vec3_t();
        }
    }
}

// function to apply previous animation state.
void apply_previous_state(Player* player, c_animstate* state, LagRecord* record,  LagRecord* previous) {
    if (!player || !state || !record || !previous) return;

    player->SetAnimLayers(previous->m_layers);
    player->SetPoseParameters(previous->m_poses);
    state->primary_cycle = previous->m_layers[6].m_cycle;
    state->move_weight = previous->m_layers[6].m_weight;
    state->strafe_sequence = previous->m_layers[7].m_sequence;
    state->strafe_change_weight = previous->m_layers[7].m_weight;
    state->strafe_change_cycle = previous->m_layers[7].m_cycle;
    state->acceleration_weight = previous->m_layers[12].m_weight;

    // https://gitlab.com/KittenPopo/csgo-2018-source/-/blob/main/game/client/c_baseplayer.cpp#L1139
    // void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType )
    record->m_anim_velocity = (record->m_origin - previous->m_origin) * (1.f / game::TICKS_TO_TIME(record->m_lag));

    // task for reader: add proper velocity recalculation
    // hint CCSGOPlayerAnimState::SetUpAliveLoop
    // Ensure the player is on the ground and adjust the z-component of the velocity
    if ((previous->m_flags & FL_ONGROUND) && (record->m_flags & FL_ONGROUND)) {
        record->m_anim_velocity.z = 0.f;

        // Check if the player is in a fake walk state where the animation might have stopped
        if (record->m_layers[6].m_playback_rate == 0.f) {
            record->m_anim_velocity = vec3_t(); // Set velocity to zero if not moving
        }
    }
    else {
        // Handle airborne or jumping states where gravity and falling velocity should be calculated
        if (!(previous->m_flags & FL_ONGROUND)) {
            record->m_anim_velocity.z -= g_csgo.sv_gravity->GetFloat() * g_csgo.m_globals->m_interval;
        }
    }

    // Apply the recalculated velocity to the player's current state
    player->m_vecVelocity() = record->m_anim_velocity;
    player->SetAbsVelocity(record->m_anim_velocity);
}

void SimulatePlayerActivity(Player* pPlayer, LagRecord* m_LagRecord, LagRecord* m_PrevRecord) {
    if (!pPlayer || !m_LagRecord || !m_PrevRecord) return;

    // get animation layers.
    const C_AnimationLayer* m_JumpingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_JUMP_OR_FALL];
    const C_AnimationLayer* m_LandingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_LAND_OR_CLIMB];
    const C_AnimationLayer* m_PrevJumpingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_JUMP_OR_FALL];
    const C_AnimationLayer* m_PrevLandingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_LAND_OR_CLIMB];

    // detect jump/land, collect its data, rebuild time in air.
    const int nJumpingActivity = pPlayer->GetSequenceActivity(m_JumpingLayer->m_sequence);
    const int nLandingActivity = pPlayer->GetSequenceActivity(m_LandingLayer->m_sequence);

    // collect jump data.
    if (nJumpingActivity == ACT_CSGO_JUMP) {
        // check duration bounds.
        if (m_JumpingLayer->m_weight > 0.0f && m_JumpingLayer->m_playback_rate > 0.0f) {
            // check cycle changed.
            if (m_JumpingLayer->m_cycle < m_PrevJumpingLayer->m_cycle) {
                m_LagRecord->m_flDurationInAir = m_JumpingLayer->m_cycle / m_JumpingLayer->m_playback_rate;
                if (m_LagRecord->m_flDurationInAir > 0.0f) {
                    m_LagRecord->m_nActivityTick = game::TIME_TO_TICKS(m_LagRecord->m_sim_time - m_LagRecord->m_flDurationInAir) + 1;
                    m_LagRecord->m_nActivityType = EPlayerActivityC::CJump;
                }
            }
        }
    }

    // collect land data.
    if (nLandingActivity == ACT_CSGO_LAND_LIGHT || nLandingActivity == ACT_CSGO_LAND_HEAVY) {
        // weight changing everytime on activity switch in this layer.
        if (m_LandingLayer->m_weight > 0.0f && m_PrevLandingLayer->m_weight <= 0.0f) {
            // check cycle changed.
            if (m_LandingLayer->m_cycle > m_PrevLandingLayer->m_cycle) {
                float flLandDuration = m_LandingLayer->m_cycle / m_LandingLayer->m_playback_rate;

                if (flLandDuration > 0.0f) {
                    m_LagRecord->m_nActivityTick = game::TIME_TO_TICKS(m_LagRecord->m_sim_time - flLandDuration) + 1;
                    m_LagRecord->m_nActivityType = EPlayerActivityC::CLand;

                    // determine duration in air.
                    float flDurationInAir = (m_JumpingLayer->m_cycle - m_LandingLayer->m_cycle);
                    if (flDurationInAir < 0.0f)
                        flDurationInAir += 1.0f;

                    // set time in air.
                    m_LagRecord->m_flDurationInAir = flDurationInAir / m_JumpingLayer->m_playback_rate;
                }
            }
        }
    }
}

float ComputeActivityPlayback(Player* pPlayer, LagRecord* m_Record) {
    if (!pPlayer || !m_Record)  return 0.0f;

    // get animation layers.
    C_AnimationLayer* m_JumpingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_JUMP_OR_FALL];
    C_AnimationLayer* m_LandingLayer = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_LAND_OR_CLIMB];
    C_AnimationLayer* moving = &pPlayer->m_AnimOverlay()[ANIMATION_LAYER_MOVEMENT_MOVE];

    // determine playback.
    float flActivityPlayback = 0.0f;

    switch (m_Record->m_nActivityType) {
    case EPlayerActivityC::CJump:
    {
        flActivityPlayback = pPlayer->GetLayerSequenceCycleRate(m_JumpingLayer, m_JumpingLayer->m_sequence);
    }
    break;

    case EPlayerActivityC::CLand:
    {
        flActivityPlayback = pPlayer->GetLayerSequenceCycleRate(m_LandingLayer, m_LandingLayer->m_sequence);
    }
    break;
    }

    return flActivityPlayback;

}

// Function to recalculate player velocity based on different conditions.
void RecalculateVelocity(Player* player, LagRecord* record, LagRecord* previous) {
    // Check if the player is valid
    if (!player || !record) return;

    // Check if previous record exists
    if (!previous) {
        // Default velocity calculation, using current velocity and potentially other factors.
        record->m_anim_velocity = player->m_vecVelocity();
        return;
    }

    // Calculate the velocity difference between the current and previous records
    vec3_t velocity_diff = record->m_origin - previous->m_origin;
    float time_diff = game::TICKS_TO_TIME(record->m_lag);

    // Handle case where there is no time difference to prevent division by zero
    if (time_diff > 0.f) {
        record->m_anim_velocity = velocity_diff * (1.f / time_diff);
    }
    else {
        // Set velocity to zero if time difference is invalid
        record->m_anim_velocity = vec3_t();
    }

    // Adjust z component for on-ground state
    if (record->m_flags & FL_ONGROUND) {
        record->m_anim_velocity.z = 0.f;
    }
    else {
        // Apply gravity for airborne state
        record->m_anim_velocity.z -= g_csgo.sv_gravity->GetFloat() * g_csgo.m_globals->m_interval;
    }
}

// function to handle the main update logic.
void perform_update_logic(Player* player, LagRecord* record, LagRecord* previous, c_animstate* state) {
    if (!player || !record || !state) return;

    // simulate player activity (jump/land) before processing.
    SimulatePlayerActivity(player, record, previous);

    // Recalculate velocity before updating animations.
    RecalculateVelocity(player, record, previous);

    // compute activity playback ( jump and land ).
    record->m_flActivityPlayback = ComputeActivityPlayback(player, record);

    for (int i = 1; i <= record->m_lag; i++) {
        const float interp = std::clamp(static_cast<float>(i) / static_cast<float>(record->m_lag), 0.f, 1.f);

        if (previous && record->m_lag > 1) {
            g_csgo.m_globals->m_curtime = math::lerp(interp, previous->m_sim_time, record->m_sim_time);
            player->m_vecVelocity() = math::lerp(interp, previous->m_anim_velocity, record->m_anim_velocity);
            player->m_flDuckAmount() = math::lerp(interp, previous->m_duck, record->m_duck);

            // handle jump and land activity.
            if (record->m_nActivityType != EPlayerActivityC::CNoActivity) {
                if (record->m_lag == record->m_nActivityTick) {
                    // compute the correct animation layer.
                    int nLayer = ANIMATION_LAYER_MOVEMENT_JUMP_OR_FALL;
                    if (record->m_nActivityType == EPlayerActivityC::CLand)
                        nLayer = ANIMATION_LAYER_MOVEMENT_LAND_OR_CLIMB;

                    // set the player's animation state based on activity.
                    player->m_AnimOverlay()[nLayer].m_cycle = 0.0f;
                    player->m_AnimOverlay()[nLayer].m_weight = 0.0f;
                    player->m_AnimOverlay()[nLayer].m_playback_rate = record->m_flActivityPlayback;

                    // update player's ground state based on activity.
                    if (record->m_nActivityType == EPlayerActivityC::CJump)
                        player->m_fFlags() &= ~FL_ONGROUND;
                    else if (record->m_nActivityType == EPlayerActivityC::CLand)
                        player->m_fFlags() |= FL_ONGROUND;
                }
                else if (record->m_lag < record->m_nActivityTick) {
                    // force the player's ground state before the activity tick.
                    if (record->m_nActivityType == EPlayerActivityC::CJump)
                        player->m_fFlags() |= FL_ONGROUND;
                    else if (record->m_nActivityType == EPlayerActivityC::CLand)
                        player->m_fFlags() &= ~FL_ONGROUND;
                }
            }
        }
        else {
            player->m_vecVelocity() = record->m_anim_velocity;
        }

        player->m_iEFlags() &= ~0x1000;
        player->SetAbsVelocity(player->m_vecVelocity());
        player->m_angEyeAngles() = record->m_eye_angles;

        g_hooks.m_UpdateClientSideAnimation(player);
        record->m_abs_ang = ang_t(0.f, state->abs_yaw, 0.f);
        player->GetPoseParameters(record->m_poses);
    }

    player->UpdateCollisionBounds();
    record->m_maxs = player->m_vecMaxs();
    record->m_mins = player->m_vecMins();
    player->SetAnimLayers(record->m_layers);
    record->m_setup = player->SetupBones(record->m_bones, 128, BONE_USED_BY_ANYTHING, state->last_update_time);
}

// restore global variables after animation update.
void restore_globals(float frame, float curtime, float frametime) {
    g_csgo.m_globals->m_frame = frame;
    g_csgo.m_globals->m_curtime = curtime;
    g_csgo.m_globals->m_frametime = frametime;
}

// update function for handling detailed player animations.
void anims::update(Player* player, LagRecord* record, LagRecord* previous) {
    c_animstate* state = player->m_PlayerAnimState();

    // backup globalvars.
    float curtime = g_csgo.m_globals->m_curtime;
    float frame = g_csgo.m_globals->m_frame;
    float frametime = g_csgo.m_globals->m_frametime;

    // backup current animation state.
    AnimationBackup_t backup;
    backup.store(player);

    // set timing and simulate player animation state.
    g_csgo.m_globals->m_curtime = record->m_anim_time;
    g_csgo.m_globals->m_frame = g_csgo.m_cl->m_server_tick;
    g_csgo.m_globals->m_frametime = g_csgo.m_globals->m_interval;

    // handle player origins and reset state vars if needed.
    player->SetAbsOrigin(player->m_vecOrigin());

    // fix our animstate vars when animstate resets
    if (state->last_update_time == 0.f || !previous) {
        reset_state_vars(player, state, record);
    }
    // or fix animstate netvars using networked values
    else if (previous) {
        apply_previous_state(player, state, record, previous);
    }

    // resolve angles and update animations.
    if (!previous || (record->m_lag != 1 || previous->m_lag != 1)) {
        g_resolver.ResolveAngles(player, record);
    }

    perform_update_logic(player, record, previous, state);

    // restore backup and globalvars.
    backup.apply(player);
    restore_globals(frame, curtime, frametime);
}

// task: hook C_BasePlayer::PostDataUpdate() and call this in it
// or use FRAME_NET_UPDATE_POSTDATAUPDATE_START
void anims::player_instance(Player* player) {
    if (!player) return;

    c_animstate* state = player->m_PlayerAnimState();
    if (!state)
        return;

    AimPlayer* data = &g_aimbot.m_players[player->index() - 1];

    if (!player->alive() || !g_cl.m_processing) {
        if (player->m_flSimulationTime() != player->m_flOldSimulationTime())
            mini_update(player);

        data->m_records.clear();
        data->m_clear_next = true;
        return;
    }


    if (player->dormant()) {
        if (data->m_records.empty() || !data->m_records[0]->dormant()) {
            data->m_records.emplace_front(std::make_shared< LagRecord >(player));
            LagRecord* current = data->m_records.front().get();
            current->m_dormant = true;
            current->m_setup = false;
        }


        data->m_clear_next = true;
        return;
    }

    const float new_spawn = player->m_flSpawnTime();

    // fix
    if (player != data->m_player || data->m_clear_next || data->m_spawn != new_spawn) {
        // reset animation state and records (they're all invalid).
        game::ResetAnimationState(state);
        data->m_records.clear();
        data->m_walk_record = LagRecordMove{};

        // alternative fix.
        player->m_flOldSimulationTime() = player->m_flSimulationTime() - g_csgo.m_globals->m_interval;
    }

    // update our vars
    data->m_player = player;
    data->m_clear_next = false;
    data->m_spawn = new_spawn;

    // player updated.
    if (data->m_records.empty() || data->m_records[0]->m_sim_time != player->m_flSimulationTime()) {
        // emplace new record.
        data->m_records.emplace_front(std::make_shared< LagRecord >(player));

        // get our new record.
        LagRecord* current = data->m_records.front().get();
        current->m_dormant = false;

        // update animations.
        update(player, current, data->m_records.size() > 1 ? data->m_records[1].get() : nullptr);
    }

    // don't store records that are too old.
    while (data->m_records.size() > 1) {
        if (std::abs(g_csgo.m_cl->m_server_tick - data->m_records.back()->m_tick) < 256)
            break;

        data->m_records.pop_back();
    }
}
 
Последнее редактирование:
Сверху Снизу