-
Автор темы
- #1
resolver.cpp
animsys.cpp
animsys.h
Код:
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
#include "animation_system.h"
#include "..\ragebot\aim.h"
#include <random>
#include <algorithm>
void resolver::initialize(player_t* e, adjust_data* record, const float& m_flGoalFeetYaw, const float& pitch)
{
player = e;
player_record = record;
original_goal_feet_yaw = math::normalize_yaw(m_flGoalFeetYaw);
original_pitch = math::normalize_pitch(pitch);
}
void resolver::reset()
{
player = nullptr;
player_record = nullptr;
side = false;
fake = false;
was_first_bruteforce = false;
was_second_bruteforce = false;
original_goal_feet_yaw = 0.0f;
original_pitch = 0.0f;
}
float flAngleMod(float flAngle)
{
return((360.0f / 65536.0f) * ((int32_t)(flAngle * (65536.0f / 360.0f)) & 65535));
}
float flApproachAngle(float flTarget, float flValue, float flSpeed)
{
float flAdjustedSpeed = flSpeed;
if (flAdjustedSpeed < 0.0f)
{
flAdjustedSpeed *= -1.0f;
}
float flAngleModTarget = flAngleMod(flTarget);
float flAngleModValue = flAngleMod(flValue);
float flDelta = (flAngleModTarget - flAngleModValue);
if (flDelta >= -180.0f)
{
if (flDelta >= 180.0f)
{
flDelta -= 360.0f;
}
}
else
{
if (flDelta <= -180.0f)
{
flDelta += 360.0f;
}
}
float flReturn;
if (flDelta <= flAdjustedSpeed)
{
if ((flAdjustedSpeed * -1.0f) <= flDelta)
{
flReturn = flAngleModTarget;
}
else
{
flReturn = (flAngleModValue - flAdjustedSpeed);
}
}
else
{
flReturn = (flAngleModValue + flAdjustedSpeed);
}
return flReturn;
}
/* detect side output things */
float get_backward_side(player_t* player) {
return math::calculate_angle(g_ctx.local()->m_vecOrigin(), player->m_vecOrigin()).y;
}
float AngleDifference(float angle1, float angle2)
{
double diff = fmod((angle2 - angle1 + 180), 360) - 180;
return diff < -180 ? diff + 360 : diff;
}
/* detect desync side */
void detect_side(player_t* player, int* side) {
/* externs */
Vector src3D, dst3D, forward, right, up, src, dst;
float back_two, right_two, left_two;
CGameTrace tr;
CTraceFilter filter;
/* angle vectors */
math::angle_vectors(Vector(0, get_backward_side(player), 0), &forward, &right, &up);
/* filtering */
filter.pSkip = player;
src3D = player->get_shoot_position();
dst3D = src3D + (forward * 384);
/* back engine tracers */
m_trace()->TraceRay(Ray_t(src3D, dst3D), MASK_SHOT, &filter, &tr);
back_two = (tr.endpos - tr.startpos).Length();
/* right engine tracers */
m_trace()->TraceRay(Ray_t(src3D + right * 35, dst3D + right * 35), MASK_SHOT, &filter, &tr);
right_two = (tr.endpos - tr.startpos).Length();
/* left engine tracers */
m_trace()->TraceRay(Ray_t(src3D - right * 35, dst3D - right * 35), MASK_SHOT, &filter, &tr);
left_two = (tr.endpos - tr.startpos).Length();
/* fix side */
if (left_two > right_two) {
*side = -1;
}
else if (right_two > left_two) {
*side = 1;
}
else
*side = 0;
}
/* check low desync delta defines */
#define delta(angle1, angle2) remainderf(fabsf(angle1 - angle2), 360.0f)
#define n(yaw) math::normalize_yaw(fabsf(yaw))
#define ca(angle1, angle2) math::calculate_angle(angle1, angle2)
/* check low desync delta */
void check_low_delta_desync(player_t* player) {
/* setup animstate */
c_baseplayeranimationstate* animstate = player->get_animation_state();
/* setup desync delta vars */
static float fl_stored_yaw = player->m_angEyeAngles().y;
float fl_eye_yaw = player->m_angEyeAngles().y;
float fl_lby_yaw = player->m_flLowerBodyYawTarget();
float fl_desync_delta = delta(fl_eye_yaw, animstate->m_flGoalFeetYaw);
fl_desync_delta = std::clamp(fl_desync_delta, -60.f, 60.f);
/* setup target side */
float fl_left_yaw = n(fl_eye_yaw - 60.0);
float fl_right_yaw = n(fl_eye_yaw + 60.0);
/* setup low delta */
float fl_left_low_delta = n(fl_lby_yaw - 35.0);
float fl_right_low_delta = n(fl_lby_yaw + 35.0);
/* setup low desync checker */
if (fabs(fl_desync_delta) < 35.f) {
/* settup missed shots */
switch (g_ctx.globals.missed_shots[player->EntIndex()] % 3) {
case 0: {
animstate->m_flGoalFeetYaw = fl_stored_brute[player->EntIndex()];
} break;
case 1: {
animstate->m_flGoalFeetYaw = fl_left_low_delta;
fl_stored_brute[player->EntIndex()] = fl_left_low_delta;
} break;
case 2: {
animstate->m_flGoalFeetYaw = fl_right_low_delta;
fl_stored_brute[player->EntIndex()] = fl_right_low_delta;
} break;
}
}
/* fixing moving delta vars */
auto target_yaw = math::calculate_angle(g_ctx.local()->m_vecOrigin(), player->m_vecOrigin()).y;
auto target_left_direction = math::normalize_yaw(target_yaw - fl_left_yaw);
auto target_right_direction = math::normalize_yaw(target_yaw - fl_right_yaw);
/* fixing moving delta */
if (target_left_direction > target_right_direction) {
/* positive right target */
animstate->m_flGoalFeetYaw = fl_right_yaw;
}
else {
/* negative left target */
animstate->m_flGoalFeetYaw = fl_left_yaw;
}
/* get stored yaw */
if (fl_stored_yaw != fl_eye_yaw) {
if (animstate->m_flCurrentFeetYaw != animstate->m_flGoalFeetYaw) {
fl_stored_yaw = player->m_angEyeAngles().y;
animstate->m_flCurrentFeetYaw = animstate->m_flGoalFeetYaw;
animstate->m_flGoalFeetYaw = animstate->m_flFeetYawRate;
}
}
/* check animrate */
if (animstate->m_flFeetYawRate != 0) {
/* check positive */
if (animstate->m_flFeetYawRate == 60.0 || animstate->m_flFeetYawRate > 60.0) {
animstate->m_flGoalFeetYaw = fl_right_yaw;
}
else if (animstate->m_flFeetYawRate == -60.0 || animstate->m_flFeetYawRate < -60.0) {
animstate->m_flGoalFeetYaw = fl_left_yaw;
}
}
/* check last desync delta ticks */
if (fabs(fl_desync_delta) > 60.0) {
if (fabs(fl_desync_delta) > 0) {
animstate->m_flGoalFeetYaw = fl_left_yaw;
}
else {
animstate->m_flGoalFeetYaw = fl_right_yaw;
}
}
else if (fabs(fl_desync_delta) < -60.0) {
if (fabs(fl_desync_delta) > 0) {
animstate->m_flGoalFeetYaw = fl_right_yaw;
}
else {
animstate->m_flGoalFeetYaw = fl_left_yaw;
}
}
/* check if low delta was wrong */
if (g_ctx.globals.missed_shots[player->EntIndex()] == 1 && fl_stored_brute[player->EntIndex()] == fl_left_yaw) {
animstate->m_flGoalFeetYaw = fl_right_yaw;
}
else if (g_ctx.globals.missed_shots[player->EntIndex()] == 1 && fl_stored_brute[player->EntIndex()] == fl_right_yaw) {
animstate->m_flGoalFeetYaw = fl_left_yaw;
}
else (g_ctx.globals.missed_shots[player->EntIndex()] == 0 && fl_stored_brute[player->EntIndex()] == fl_stored_yaw); {
animstate->m_flGoalFeetYaw = fl_stored_yaw;
}
/* bruteforce if check was wrong */
switch (g_ctx.globals.missed_shots[player->EntIndex()] % 3) {
if (g_ctx.globals.missed_shots[player->EntIndex()] % 1) {
case 3: {
animstate->m_flGoalFeetYaw = fl_eye_yaw;
fl_stored_brute[player->EntIndex()] = fl_eye_yaw;
}break;
}
case 0: {
animstate->m_flGoalFeetYaw = fl_stored_brute[player->EntIndex()];
} break;
case 1: {
animstate->m_flGoalFeetYaw = fl_left_low_delta;
fl_stored_brute[player->EntIndex()] = fl_left_low_delta;
} break;
case 2: {
animstate->m_flGoalFeetYaw = fl_right_low_delta;
fl_stored_brute[player->EntIndex()] = fl_right_low_delta;
} break;
}
}
float Bias(float x, float biasAmt)
{
// WARNING: not thread safe
static float lastAmt = -1;
static float lastExponent = 0;
if (lastAmt != biasAmt)
{
lastExponent = log(biasAmt) * -1.4427f; // (-1.4427 = 1 / log(0.5))
}
return pow(x, lastExponent);
}
inline float AngleNormalizePositive(float angle)
{
angle = fmodf(angle, 360.0f);
if (angle < 0.0f)
{
angle += 360.0f;
}
return angle;
}
float build_server_abs_yaw(player_t* m_player, float angle)
{
Vector velocity = m_player->m_vecVelocity();
auto anim_state = m_player->get_animation_state();
float m_flEyeYaw = angle;
float m_flGoalFeetYaw = 0.f;
float eye_feet_delta = AngleDifference(m_flEyeYaw, m_flGoalFeetYaw);
static auto GetSmoothedVelocity = [](float min_delta, Vector a, Vector b) {
Vector delta = a - b;
float delta_length = delta.Length();
if (delta_length <= min_delta)
{
Vector result;
if (-min_delta <= delta_length)
return a;
else
{
float iradius = 1.0f / (delta_length + FLT_EPSILON);
return b - ((delta * iradius) * min_delta);
}
}
else
{
float iradius = 1.0f / (delta_length + FLT_EPSILON);
return b + ((delta * iradius) * min_delta);
}
};
float spd = velocity.LengthSqr();
if (spd > std::powf(1.2f * 260.0f, 2.f))
{
Vector velocity_normalized = velocity.Normalized();
velocity = velocity_normalized * (1.2f * 260.0f);
}
float m_flChokedTime = anim_state->m_flLastClientSideAnimationUpdateTime;
float v25 = std::clamp(m_player->m_flDuckAmount() + anim_state->m_fLandingDuckAdditiveSomething, 0.0f, 1.0f);
float v26 = anim_state->m_fDuckAmount;
float v27 = m_flChokedTime * 6.0f;
float v28;
// clamp
if ((v25 - v26) <= v27) {
if (-v27 <= (v25 - v26))
v28 = v25;
else
v28 = v26 - v27;
}
else {
v28 = v26 + v27;
}
float flDuckAmount = std::clamp(v28, 0.0f, 1.0f);
Vector animationVelocity = GetSmoothedVelocity(m_flChokedTime * 2000.0f, velocity, m_player->m_vecVelocity());
float speed = std::fminf(animationVelocity.Length(), 260.0f);
float flMaxMovementSpeed = 260.0f;
weapon_t* pWeapon = m_player->m_hActiveWeapon().Get();
if (pWeapon)
flMaxMovementSpeed = std::fmaxf(pWeapon->get_csweapon_info()->flMaxPlayerSpeedAlt, 0.001f);
float flRunningSpeed = speed / (flMaxMovementSpeed * 0.520f);
float flDuckingSpeed = speed / (flMaxMovementSpeed * 0.340f);
flRunningSpeed = std::clamp(flRunningSpeed, 0.0f, 1.0f);
float flYawModifier = (((anim_state->m_flStopToFullRunningFraction * -0.30000001) - 0.19999999) * flRunningSpeed) + 1.0f;
if (flDuckAmount > 0.0f)
{
float flDuckingSpeed = std::clamp(flDuckingSpeed, 0.0f, 1.0f);
flYawModifier += (flDuckAmount * flDuckingSpeed) * (0.5f - flYawModifier);
}
const float v60 = -58.f;
const float v61 = 58.f;
float flMinYawModifier = v60 * flYawModifier;
float flMaxYawModifier = v61 * flYawModifier;
if (eye_feet_delta <= flMaxYawModifier)
{
if (flMinYawModifier > eye_feet_delta)
m_flGoalFeetYaw = fabs(flMinYawModifier) + m_flEyeYaw;
}
else
{
m_flGoalFeetYaw = m_flEyeYaw - fabs(flMaxYawModifier);
}
math::normalize_yaw(m_flGoalFeetYaw);
if (speed > 0.1f || fabs(velocity.z) > 100.0f)
{
m_flGoalFeetYaw = flApproachAngle(
m_flEyeYaw,
m_flGoalFeetYaw,
((anim_state->m_flStopToFullRunningFraction * 20.0f) + 30.0f)
* m_flChokedTime);
}
else
{
m_flGoalFeetYaw = flApproachAngle(
m_player->m_flLowerBodyYawTarget(),
m_flGoalFeetYaw,
m_flChokedTime * 100.0f);
}
return m_flGoalFeetYaw;
}
void resolver::resolve_yaw()
{
player_info_t player_info;
if (!m_engine()->GetPlayerInfo(player->EntIndex(), &player_info))
return;
#if RELEASE
if (player_info.fakeplayer || !g_ctx.local()->is_alive() || player->m_iTeamNum() == g_ctx.local()->m_iTeamNum()) //-V807
#else
if (!g_ctx.local()->is_alive() || player->m_iTeamNum() == g_ctx.local()->m_iTeamNum())
#endif
{
player_record->side = RESOLVER_ORIGINAL;
return;
}
if (g_ctx.globals.missed_shots[player->EntIndex()] >= 2 || g_ctx.globals.missed_shots[player->EntIndex()] && aim::get().last_target[player->EntIndex()].record.type != LBY)
{
switch (last_side)
{
case RESOLVER_ORIGINAL:
g_ctx.globals.missed_shots[player->EntIndex()] = 0;
fake = true;
break;
case RESOLVER_ZERO:
player_record->type = BRUTEFORCE;
player_record->side = RESOLVER_LOW_FIRST;
was_first_bruteforce = false;
was_second_bruteforce = false;
return;
case RESOLVER_FIRST:
player_record->type = BRUTEFORCE;
player_record->side = was_second_bruteforce ? RESOLVER_ZERO : RESOLVER_SECOND;
was_first_bruteforce = true;
return;
case RESOLVER_SECOND:
player_record->type = BRUTEFORCE;
player_record->side = was_first_bruteforce ? RESOLVER_ZERO : RESOLVER_FIRST;
was_second_bruteforce = true;
return;
case RESOLVER_LOW_FIRST:
player_record->type = BRUTEFORCE;
player_record->side = RESOLVER_LOW_SECOND;
return;
case RESOLVER_LOW_SECOND:
player_record->type = BRUTEFORCE;
player_record->side = RESOLVER_FIRST;
return;
}
}
auto animstate = player->get_animation_state();
if (!animstate)
{
player_record->side = RESOLVER_ORIGINAL;
return;
}
if (fabs(original_pitch) > 85.0f)
fake = true;
else if (!fake)
{
player_record->side = RESOLVER_ORIGINAL;
return;
}
auto delta = math::normalize_yaw(player->m_angEyeAngles().y - original_goal_feet_yaw);
auto valid_lby = true;
if (animstate->m_velocity > 0.1f || fabs(animstate->flUpVelocity) > 100.f)
valid_lby = animstate->m_flTimeSinceStartedMoving < 0.22f;
if (fabs(delta) > 30.0f && valid_lby)
{
if (g_ctx.globals.missed_shots[player->EntIndex()])
delta = -delta;
if (delta > 30.0f)
{
player_record->type = LBY;
player_record->side = RESOLVER_FIRST;
}
else if (delta < -30.0f)
{
player_record->type = LBY;
player_record->side = RESOLVER_SECOND;
}
}
else
{
int side;
detect_side(player, &side);
if (side == 1)
{
player_record->type = TRACE;
player_record->side = RESOLVER_FIRST;
}
else if (side == -1) {
player_record->type = TRACE;
player_record->side = RESOLVER_SECOND;
}
else
{
auto trace = false;
if (m_globals()->m_curtime - lock_side > 2.0f)
{
auto first_visible = util::visible(g_ctx.globals.eye_pos, player->hitbox_position_matrix(HITBOX_HEAD, player_record->matrixes_data.first), player, g_ctx.local());
auto second_visible = util::visible(g_ctx.globals.eye_pos, player->hitbox_position_matrix(HITBOX_HEAD, player_record->matrixes_data.second), player, g_ctx.local());
if (first_visible != second_visible)
{
trace = true;
side = second_visible;
lock_side = m_globals()->m_curtime;
}
else
{
auto first_position = g_ctx.globals.eye_pos. DistTo(player->hitbox_position_matrix(HITBOX_HEAD, player_record->matrixes_data.first));
auto second_position = g_ctx.globals.eye_pos. DistTo(player->hitbox_position_matrix(HITBOX_HEAD, player_record->matrixes_data.second));
if (fabs(first_position - second_position) > 1.0f)
side = first_position > second_position;
}
}
else
trace = true;
if (side)
{
player_record->type = trace ? TRACE : DIRECTIONAL;
player_record->side = RESOLVER_FIRST;
}
else
{
player_record->type = trace ? TRACE : DIRECTIONAL;
player_record->side = RESOLVER_SECOND;
}
}
}
}
float resolver::resolve_pitch()
{
return original_pitch;
}
animsys.cpp
Код:
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
#include "animation_system.h"
#include "..\misc\misc.h"
#include "..\misc\logs.h"
std::deque <adjust_data> player_records[65];
void lagcompensation::fsn(ClientFrameStage_t stage)
{
if (stage != FRAME_NET_UPDATE_END)
return;
if (!g_cfg.ragebot.enable && !g_cfg.legitbot.enabled)
return;
for (auto i = 1; i < m_globals()->m_maxclients; i++) //-V807
{
auto e = static_cast<player_t*>(m_entitylist()->GetClientEntity(i));
if (e == g_ctx.local())
continue;
if (!valid(i, e))
continue;
auto time_delta = abs(TIME_TO_TICKS(e->m_flSimulationTime()) - m_globals()->m_tickcount);
if (time_delta > 1.0f / m_globals()->m_intervalpertick)
continue;
auto update = player_records[i].empty() || e->m_flSimulationTime() != e->m_flOldSimulationTime(); //-V550
if (update && !player_records[i].empty())
{
auto server_tick = m_clientstate()->m_iServerTick - i % m_globals()->m_timestamprandomizewindow;
auto current_tick = server_tick - server_tick % m_globals()->m_timestampnetworkingbase;
if (TIME_TO_TICKS(e->m_flOldSimulationTime()) < current_tick && TIME_TO_TICKS(e->m_flSimulationTime()) == current_tick)
{
auto layer = &e->get_animlayers()[11];
auto previous_layer = &player_records[i].front().layers[11];
if (layer->m_flCycle == previous_layer->m_flCycle) //-V550
{
e->m_flSimulationTime() = e->m_flOldSimulationTime();
update = false;
}
}
}
if (update) //-V550
{
if (!player_records[i].empty() && (e->m_vecOrigin() - player_records[i].front().origin).LengthSqr() > 4096.0f)
for (auto& record : player_records[i])
record.invalid = true;
player_records[i].emplace_front(adjust_data());
update_player_animations(e);
while (player_records[i].size() > 32)
player_records[i].pop_back();
}
}
}
bool lagcompensation::valid(int i, player_t* e)
{
if (!g_cfg.ragebot.enable && !g_cfg.legitbot.enabled || !e->valid(false))
{
if (!e->is_alive())
{
is_dormant[i] = false;
player_resolver[i].reset();
g_ctx.globals.fired_shots[i] = 0;
g_ctx.globals.missed_shots[i] = 0;
}
else if (e->IsDormant())
is_dormant[i] = true;
player_records[i].clear();
return false;
}
return true;
}
void lagcompensation::update_player_animations(player_t* e)
{
auto animstate = e->get_animation_state();
if (!animstate)
return;
player_info_t player_info;
if (!m_engine()->GetPlayerInfo(e->EntIndex(), &player_info))
return;
auto records = &player_records[e->EntIndex()]; //-V826
if (records->empty())
return;
adjust_data* previous_record = nullptr;
if (records->size() >= 2)
previous_record = &records->at(1);
auto record = &records->front();
AnimationLayer animlayers[15];
memcpy(animlayers, e->get_animlayers(), e->animlayer_count() * sizeof(AnimationLayer));
memcpy(record->layers, animlayers, e->animlayer_count() * sizeof(AnimationLayer));
auto backup_lower_body_yaw_target = e->m_flLowerBodyYawTarget();
auto backup_duck_amount = e->m_flDuckAmount();
auto backup_flags = e->m_fFlags();
auto backup_eflags = e->m_iEFlags();
auto backup_curtime = m_globals()->m_curtime; //-V807
auto backup_frametime = m_globals()->m_frametime;
auto backup_realtime = m_globals()->m_realtime;
auto backup_framecount = m_globals()->m_framecount;
auto backup_tickcount = m_globals()->m_tickcount;
auto backup_interpolation_amount = m_globals()->m_interpolation_amount;
m_globals()->m_curtime = e->m_flSimulationTime();
m_globals()->m_frametime = m_globals()->m_intervalpertick;
if (previous_record)
{
auto velocity = e->m_vecVelocity();
auto was_in_air = e->m_fFlags() & FL_ONGROUND && previous_record->flags & FL_ONGROUND;
auto time_difference = max(m_globals()->m_intervalpertick, e->m_flSimulationTime() - previous_record->simulation_time);
auto origin_delta = e->m_vecOrigin() - previous_record->origin;
auto animation_speed = 0.0f;
if (!origin_delta.IsZero() && TIME_TO_TICKS(time_difference) > 0)
{
e->m_vecVelocity() = origin_delta * (1.0f / time_difference);
if (e->m_fFlags() & FL_ONGROUND && animlayers[11].m_flWeight > 0.0f && animlayers[11].m_flWeight < 1.0f && animlayers[11].m_flCycle > previous_record->layers[11].m_flCycle)
{
auto weapon = e->m_hActiveWeapon().Get();
if (weapon)
{
auto max_speed = 260.0f;
auto weapon_info = e->m_hActiveWeapon().Get()->get_csweapon_info();
if (weapon_info)
max_speed = e->m_bIsScoped() ? weapon_info->flMaxPlayerSpeedAlt : weapon_info->flMaxPlayerSpeed;
auto modifier = 0.35f * (1.0f - animlayers[11].m_flWeight);
if (modifier > 0.0f && modifier < 1.0f)
animation_speed = max_speed * (modifier + 0.55f);
}
}
if (animation_speed > 0.0f)
{
animation_speed /= e->m_vecVelocity().Length2D();
e->m_vecVelocity().x *= animation_speed;
e->m_vecVelocity().y *= animation_speed;
}
if (records->size() >= 3 && time_difference > m_globals()->m_intervalpertick)
{
auto previous_velocity = (previous_record->origin - records->at(2).origin) * (1.0f / time_difference);
if (!previous_velocity.IsZero() && !was_in_air)
{
auto current_direction = math::normalize_yaw(RAD2DEG(atan2(e->m_vecVelocity().y, e->m_vecVelocity().x)));
auto previous_direction = math::normalize_yaw(RAD2DEG(atan2(previous_velocity.y, previous_velocity.x)));
auto average_direction = current_direction - previous_direction;
average_direction = DEG2RAD(math::normalize_yaw(current_direction + average_direction * 0.5f));
auto direction_cos = cos(average_direction);
auto dirrection_sin = sin(average_direction);
auto velocity_speed = e->m_vecVelocity().Length2D();
e->m_vecVelocity().x = direction_cos * velocity_speed;
e->m_vecVelocity().y = dirrection_sin * velocity_speed;
}
}
if (!(e->m_fFlags() & FL_ONGROUND))
{
static auto sv_gravity = m_cvar()->FindVar(crypt_str("sv_gravity"));
auto fixed_timing = math::clamp(time_difference, m_globals()->m_intervalpertick, 1.0f);
e->m_vecVelocity().z -= sv_gravity->GetFloat() * fixed_timing * 0.5f;
}
else
e->m_vecVelocity().z = 0.0f;
}
}
e->m_iEFlags() &= ~0x1800;
if (e->m_fFlags() & FL_ONGROUND && e->m_vecVelocity().Length() > 0.0f && animlayers[6].m_flWeight <= 0.0f)
e->m_vecVelocity().Zero();
e->m_vecAbsVelocity() = e->m_vecVelocity();
e->m_bClientSideAnimation() = true;
if (is_dormant[e->EntIndex()])
{
is_dormant[e->EntIndex()] = false;
if (e->m_fFlags() & FL_ONGROUND)
{
animstate->m_bOnGround = true;
animstate->m_bInHitGroundAnimation = false;
}
animstate->time_since_in_air() = 0.0f;
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y);
}
auto updated_animations = false;
c_baseplayeranimationstate state;
memcpy(&state, animstate, sizeof(c_baseplayeranimationstate));
if (previous_record)
{
memcpy(e->get_animlayers(), previous_record->layers, e->animlayer_count() * sizeof(AnimationLayer));
auto ticks_chocked = 1;
auto simulation_ticks = TIME_TO_TICKS(e->m_flSimulationTime() - previous_record->simulation_time);
if (simulation_ticks > 0 && simulation_ticks < 31)
ticks_chocked = simulation_ticks;
if (ticks_chocked > 1)
{
auto land_time = 0.0f;
auto land_in_cycle = false;
auto is_landed = false;
auto on_ground = false;
if (animlayers[4].m_flCycle < 0.5f && (!(e->m_fFlags() & FL_ONGROUND) || !(previous_record->flags & FL_ONGROUND)))
{
land_time = e->m_flSimulationTime() - animlayers[4].m_flPlaybackRate * animlayers[4].m_flCycle;
land_in_cycle = land_time >= previous_record->simulation_time;
}
auto duck_amount_per_tick = (e->m_flDuckAmount() - previous_record->duck_amount) / ticks_chocked;
for (auto i = 0; i < ticks_chocked; ++i)
{
auto lby_delta = fabs(math::normalize_yaw(e->m_flLowerBodyYawTarget() - previous_record->lby));
if (lby_delta > 0.0f && e->m_vecVelocity().Length() < 5.0f)
{
auto delta = ticks_chocked - i;
auto use_new_lby = true;
if (lby_delta < 1.0f)
use_new_lby = !delta; //-V547
else
use_new_lby = delta < 2;
e->m_flLowerBodyYawTarget() = use_new_lby ? backup_lower_body_yaw_target : previous_record->lby;
}
auto simulated_time = previous_record->simulation_time + TICKS_TO_TIME(i);
if (duck_amount_per_tick) //-V550
e->m_flDuckAmount() = previous_record->duck_amount + duck_amount_per_tick * (float)i;
on_ground = e->m_fFlags() & FL_ONGROUND;
if (land_in_cycle && !is_landed)
{
if (land_time <= simulated_time)
{
is_landed = true;
on_ground = true;
}
else
on_ground = previous_record->flags & FL_ONGROUND;
}
if (on_ground)
e->m_fFlags() |= FL_ONGROUND;
else
e->m_fFlags() &= ~FL_ONGROUND;
auto simulated_ticks = TIME_TO_TICKS(simulated_time);
m_globals()->m_realtime = simulated_time;
m_globals()->m_curtime = simulated_time;
m_globals()->m_framecount = simulated_ticks;
m_globals()->m_tickcount = simulated_ticks;
m_globals()->m_interpolation_amount = 0.0f;
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
m_globals()->m_realtime = backup_realtime;
m_globals()->m_curtime = backup_curtime;
m_globals()->m_framecount = backup_framecount;
m_globals()->m_tickcount = backup_tickcount;
m_globals()->m_interpolation_amount = backup_interpolation_amount;
updated_animations = true;
}
}
}
if (!updated_animations)
{
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
}
memcpy(animstate, &state, sizeof(c_baseplayeranimationstate));
auto setup_matrix = [&](player_t* e, AnimationLayer* layers, const int& matrix) -> void
{
e->invalidate_physics_recursive(8);
AnimationLayer backup_layers[15];
memcpy(backup_layers, e->get_animlayers(), e->animlayer_count() * sizeof(AnimationLayer));
memcpy(e->get_animlayers(), layers, e->animlayer_count() * sizeof(AnimationLayer));
switch (matrix)
{
case MAIN:
e->setup_bones_fixed(record->matrixes_data.main, BONE_USED_BY_ANYTHING);
break;
case NONE:
e->setup_bones_fixed(record->matrixes_data.zero, BONE_USED_BY_HITBOX);
break;
case FIRST:
e->setup_bones_fixed(record->matrixes_data.first, BONE_USED_BY_HITBOX);
break;
case SECOND:
e->setup_bones_fixed(record->matrixes_data.second, BONE_USED_BY_HITBOX);
break;
}
memcpy(e->get_animlayers(), backup_layers, e->animlayer_count() * sizeof(AnimationLayer));
};
#if RELEASE
if (!player_info.fakeplayer && g_ctx.local()->is_alive() && e->m_iTeamNum() != g_ctx.local()->m_iTeamNum() && !g_cfg.legitbot.enabled) //-V807
#else
if (g_ctx.local()->is_alive() && e->m_iTeamNum() != g_ctx.local()->m_iTeamNum() && !g_cfg.legitbot.enabled)
#endif
{
animstate->m_flGoalFeetYaw = previous_goal_feet_yaw[e->EntIndex()]; //-V807
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
previous_goal_feet_yaw[e->EntIndex()] = animstate->m_flGoalFeetYaw;
memcpy(animstate, &state, sizeof(c_baseplayeranimationstate));
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y); //-V807
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
setup_matrix(e, animlayers, NONE);
memcpy(animstate, &state, sizeof(c_baseplayeranimationstate));
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y + 60.0f);
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
setup_matrix(e, animlayers, FIRST);
memcpy(animstate, &state, sizeof(c_baseplayeranimationstate));
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y - 60.0f);
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
setup_matrix(e, animlayers, SECOND);
memcpy(animstate, &state, sizeof(c_baseplayeranimationstate));
player_resolver[e->EntIndex()].initialize(e, record, previous_goal_feet_yaw[e->EntIndex()], e->m_angEyeAngles().x);
player_resolver[e->EntIndex()].resolve_yaw();
if (g_cfg.player_list.low_delta[e->EntIndex()])
{
switch (record->side)
{
case RESOLVER_FIRST:
record->side = RESOLVER_LOW_FIRST;
break;
case RESOLVER_SECOND:
record->side = RESOLVER_LOW_SECOND;
break;
case RESOLVER_LOW_FIRST:
record->side = RESOLVER_FIRST;
break;
case RESOLVER_LOW_SECOND:
record->side = RESOLVER_SECOND;
break;
}
}
switch (record->side)
{
case RESOLVER_ORIGINAL:
animstate->m_flGoalFeetYaw = previous_goal_feet_yaw[e->EntIndex()];
break;
case RESOLVER_ZERO:
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y);
break;
case RESOLVER_FIRST:
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y + 60.0f);
break;
case RESOLVER_SECOND:
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y - 60.0f);
break;
case RESOLVER_LOW_FIRST:
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y + 30.0f);
break;
case RESOLVER_LOW_SECOND:
animstate->m_flGoalFeetYaw = math::normalize_yaw(e->m_angEyeAngles().y - 30.0f);
break;
}
e->m_angEyeAngles().x = player_resolver[e->EntIndex()].resolve_pitch();
}
g_ctx.globals.updating_animation = true;
e->update_clientside_animation();
g_ctx.globals.updating_animation = false;
setup_matrix(e, animlayers, MAIN);
memcpy(e->m_CachedBoneData(). Base(), record->matrixes_data.main, e->m_CachedBoneData(). Count() * sizeof(matrix3x4_t));
m_globals()->m_curtime = backup_curtime;
m_globals()->m_frametime = backup_frametime;
e->m_flLowerBodyYawTarget() = backup_lower_body_yaw_target;
e->m_flDuckAmount() = backup_duck_amount;
e->m_fFlags() = backup_flags;
e->m_iEFlags() = backup_eflags;
memcpy(e->get_animlayers(), animlayers, e->animlayer_count() * sizeof(AnimationLayer));
record->store_data(e, false);
if (e->m_flSimulationTime() < e->m_flOldSimulationTime())
record->invalid = true;
}
animsys.h
Код:
#pragma once
#include "..\..\includes.hpp"
#include "..\..\sdk\structs.hpp"
enum
{
MAIN,
NONE,
FIRST,
SECOND
};
enum resolver_type
{
ORIGINAL,
BRUTEFORCE,
LBY,
TRACE,
DIRECTIONAL
};
enum resolver_side
{
RESOLVER_ORIGINAL,
RESOLVER_ZERO,
RESOLVER_FIRST,
RESOLVER_SECOND,
RESOLVER_LOW_FIRST,
RESOLVER_LOW_SECOND
};
struct matrixes
{
matrix3x4_t main[MAXSTUDIOBONES];
matrix3x4_t zero[MAXSTUDIOBONES];
matrix3x4_t first[MAXSTUDIOBONES];
matrix3x4_t second[MAXSTUDIOBONES];
};
class adjust_data;
class resolver
{
player_t* player = nullptr;
adjust_data* player_record = nullptr;
bool side = false;
bool fake = false;
bool was_first_bruteforce = false;
bool was_second_bruteforce = false;
float lock_side = 0.0f;
float original_goal_feet_yaw = 0.0f;
float original_pitch = 0.0f;
public:
void initialize(player_t* e, adjust_data* record, const float& goal_feet_yaw, const float& pitch);
void reset();
void resolve_yaw();
float resolve_pitch();
resolver_side last_side = RESOLVER_ORIGINAL;
};
static float fl_stored_brute[65];
class adjust_data //-V730
{
public:
player_t* player;
int i;
AnimationLayer layers[15];
matrixes matrixes_data;
resolver_type type;
resolver_side side;
bool invalid;
bool immune;
bool dormant;
bool bot;
int flags;
int bone_count;
float simulation_time;
float duck_amount;
float lby;
Vector angles;
Vector abs_angles;
Vector velocity;
Vector origin;
Vector mins;
Vector maxs;
adjust_data() //-V730
{
reset();
}
void reset()
{
player = nullptr;
i = -1;
type = ORIGINAL;
side = RESOLVER_ORIGINAL;
invalid = false;
immune = false;
dormant = false;
bot = false;
flags = 0;
bone_count = 0;
simulation_time = 0.0f;
duck_amount = 0.0f;
lby = 0.0f;
angles.Zero();
abs_angles.Zero();
velocity.Zero();
origin.Zero();
mins.Zero();
maxs.Zero();
}
adjust_data(player_t* e, bool store = true)
{
type = ORIGINAL;
side = RESOLVER_ORIGINAL;
invalid = false;
store_data(e, store);
}
void store_data(player_t* e, bool store = true)
{
if (!e->is_alive())
return;
player = e;
i = player->EntIndex();
if (store)
{
memcpy(layers, e->get_animlayers(), e->animlayer_count() * sizeof(AnimationLayer));
memcpy(matrixes_data.main, player->m_CachedBoneData().Base(), player->m_CachedBoneData().Count() * sizeof(matrix3x4_t));
}
immune = player->m_bGunGameImmunity() || player->m_fFlags() & FL_FROZEN;
dormant = player->IsDormant();
#if RELEASE
player_info_t player_info;
m_engine()->GetPlayerInfo(i, &player_info);
bot = player_info.fakeplayer;
#else
bot = false;
#endif
flags = player->m_fFlags();
bone_count = player->m_CachedBoneData().Count();
simulation_time = player->m_flSimulationTime();
duck_amount = player->m_flDuckAmount();
lby = player->m_flLowerBodyYawTarget();
angles = player->m_angEyeAngles();
abs_angles = player->GetAbsAngles();
velocity = player->m_vecVelocity();
origin = player->m_vecOrigin();
mins = player->GetCollideable()->OBBMins();
maxs = player->GetCollideable()->OBBMaxs();
}
void adjust_player()
{
if (!valid(false))
return;
memcpy(player->get_animlayers(), layers, player->animlayer_count() * sizeof(AnimationLayer));
memcpy(player->m_CachedBoneData(). Base(), matrixes_data.main, player->m_CachedBoneData(). Count() * sizeof(matrix3x4_t)); -V807
player->m_fFlags() = flags;
player->m_CachedBoneData().m_Size = bone_count;
player->m_flSimulationTime() = simulation_time;
player->m_flDuckAmount() = duck_amount;
player->m_flLowerBodyYawTarget() = lby;
player->m_angEyeAngles() = angles;
player->set_abs_angles(abs_angles);
player->m_vecVelocity() = velocity;
player->m_vecOrigin() = origin;
player->set_abs_origin(origin);
player->GetCollideable()->OBBMins() = mins;
player->GetCollideable()->OBBMaxs() = maxs;
}
bool valid(bool extra_checks = true)
{
if (!this) //-V704
return false;
if (i > 0)
player = (player_t*)m_entitylist()->GetClientEntity(i);
if (!player)
return false;
if (player->m_lifeState() != LIFE_ALIVE)
return false;
if (immune)
return false;
if (dormant)
return false;
if (!extra_checks)
return true;
if (invalid)
return false;
auto net_channel_info = m_engine()->GetNetChannelInfo();
if (!net_channel_info)
return false;
static auto sv_maxunlag = m_cvar()->FindVar(crypt_str("sv_maxunlag"));
auto outgoing = net_channel_info->GetLatency(FLOW_OUTGOING);
auto incoming = net_channel_info->GetLatency(FLOW_INCOMING);
auto correct = math::clamp(outgoing + incoming + util::get_interpolation(), 0.0f, sv_maxunlag->GetFloat());
auto curtime = g_ctx.local()->is_alive() ? TICKS_TO_TIME(g_ctx.globals.fixed_tickbase) : m_globals()->m_curtime; -V807
auto delta_time = correct - (curtime - simulation_time);
if (fabs(delta_time) > 0.2f)
return false;
auto extra_choke = 0;
if (g_ctx.globals.fakeducking)
extra_choke = 14 - m_clientstate()->iChokedCommands;
auto server_tickcount = extra_choke + m_globals()->m_tickcount + TIME_TO_TICKS(outgoing + incoming);
auto dead_time = (int)(TICKS_TO_TIME(server_tickcount) - sv_maxunlag->GetFloat());
if (simulation_time < (float)dead_time)
return false;
return true;
}
};
class optimized_adjust_data
{
public:
int i;
player_t* player;
float simulation_time;
float duck_amount;
Vector angles;
Vector origin;
optimized_adjust_data() //-V730
{
reset();
}
void reset()
{
i = 0;
player = nullptr;
simulation_time = 0.0f;
duck_amount = 0.0f;
angles. Zero();
origin. Zero();
}
};
extern std::deque <adjust_data> player_records[65];
class lagcompensation : public singleton <lagcompensation>
{
public:
void fsn(ClientFrameStage_t stage);
bool valid(int i, player_t* e);
void update_player_animations(player_t* e);
resolver player_resolver[65];
bool is_dormant[65];
float previous_goal_feet_yaw[65];
};